กรองจุดยอดบนคุณสมบัติต่างๆ - Julia

ฉันกำลังทำงานกับจูเลียด้วยไลบรารี Metagraphs.jl เพื่อดำเนินการแก้ไขปัญหาการปรับให้เหมาะสม ฉันต้องการรับชุด/รายการของขอบในกราฟที่ชี้ไปยังชุดจุดยอดพิเศษที่มีคุณสมบัติเฉพาะ 2 ประการที่เหมือนกัน

การเดาครั้งแรกของฉันคือการได้รับชุด/รายการจุดยอดก่อน แต่ฉันกำลังเผชิญกับปัญหาแรกซึ่งก็คือฟังก์ชัน filter_vertices ดูเหมือนจะไม่ยอมรับที่จะใช้ตัวกรองกับคุณสมบัติมากกว่าหนึ่งรายการ นี่คือตัวอย่างด้านล่างของสิ่งที่ฉันต้องการทำ:

g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)

add_vertex!(mg)

add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)

set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))

set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))

col=collect(filter_vertices(mg,:prop1,1,:prop2,2))

และฉันต้องการให้ col ค้นหาจุดยอด 3 และไม่มีจุดอื่น

แต่ filter_vertices จะยอมรับคุณสมบัติครั้งละหนึ่งรายการเท่านั้น จากนั้นจะทำให้มีค่าใช้จ่ายมากขึ้นในการทำลูปด้วยตัวกรอง 2 ตัว จากนั้นลองเปรียบเทียบเพื่อเรียงลำดับรายการด้วยจุดยอดที่มีคุณสมบัติทั้งสอง

เมื่อพิจารณาถึงขนาดของกราฟของฉัน ฉันต้องการหลีกเลี่ยงการกำหนดชุดนี้ด้วยการวนซ้ำหลายรอบและมีราคาแพง มีใครในพวกคุณมีไอเดียวิธีแก้ปัญหานี้ด้วยวิธีที่ง่ายและนุ่มนวลบ้างไหม?

ฉันทำสิ่งนี้เพื่อตอบคำถามของตัวเอง:

fil3=Array{Int64,1}()
fil1=filter_vertices(mg,:prop1,1)
for f in fil1
    if get_prop(mg,f,:prop2)==2
        push!(fil3,f)
    end
end            
println(fil3)

แต่บอกฉันถ้าคุณมีอะไรที่น่าสนใจกว่านี้

ขอบคุณสำหรับความช่วยเหลือของคุณ!


person Alexo    schedule 07.03.2018    source แหล่งที่มา
comment
โปรดพิจารณาเปิดประเด็นใน repos LightGraphs / MetaGraphs ด้วยวิธีนี้เราจะได้รับการแจ้งเตือนทันทีและสามารถช่วยเหลือได้โดยตรง   -  person sbromberger    schedule 13.04.2018


คำตอบ (2)


โปรดยกตัวอย่างการทำงานขั้นต่ำในแบบที่เราสามารถคัดลอกและวาง แล้วเริ่มได้ทันที โปรดระบุด้วยว่าปัญหาเกิดขึ้นที่ใดในรหัส ด้านล่างนี้คือตัวอย่างสำหรับสถานการณ์ของคุณ:

Pkg.add("MetaGraphs")

using LightGraphs, MetaGraphs

g = DiGraph(5)
mg = MetaDiGraph(g, 1.0)

add_vertex!(mg)

add_edge!(mg,1,2)
add_edge!(mg,1,3)
add_edge!(mg,1,4)
add_edge!(mg,2,5)
add_edge!(mg,3,5)
add_edge!(mg,5,6)
add_edge!(mg,4,6)

set_props!(mg,3,Dict(:prop1=>1,:prop2=>2))
set_props!(mg,1,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,2,Dict(:prop1=>1,:prop2=>0))
set_props!(mg,4,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,5,Dict(:prop1=>0,:prop2=>2))
set_props!(mg,6,Dict(:prop1=>0,:prop2=>0))

function my_vertex_filter(g::AbstractMetaGraph, v::Integer, prop1, prop2)
  return has_prop(g, v, :prop1) && get_prop(g, v, :prop1) == prop1 &&
         has_prop(g, v, :prop2) && get_prop(g, v, :prop2) == prop2
end

prop1 = 1
prop2 = 2

col = collect(filter_vertices(mg, (g,v)->my_vertex_filter(g,v,prop1,prop2)))
# returns Int[3]

โปรดตรวจสอบ ?filter_vertices --- ซึ่งจะให้คำแนะนำว่าควรเขียนอะไร/อย่างไรเพื่อกำหนดตัวกรองที่คุณกำหนดเอง

แก้ไข สำหรับการกรองขอบ คุณสามารถดูที่ ?filter_edges เพื่อดูว่าคุณต้องการอะไรเพื่อให้ได้รับการกรองขอบ เพิ่มข้อความที่ตัดตอนมาด้านล่างต่อท้ายโซลูชันด้านบนเพื่อรับผลลัพธ์ของคุณ:

function my_edge_filter(g, e, prop1, prop2)
  v = dst(e) # get the edge's destination vertex
  return my_vertex_filter(g, v, prop1, prop2)
end

myedges = collect(filter_edges(mg, (g,e)->my_edge_filter(g,e,prop1,prop2)))
# returns [Edge 1 => 3]
person Arda Aytekin    schedule 07.03.2018
comment
ขอบคุณสำหรับความช่วยเหลือของคุณ มันทำงานได้ดีขึ้นอย่างแน่นอน แต่ฉันมีคำถามเกี่ยวกับส่วนที่เหลือของสิ่งที่ฉันตั้งใจจะทำ ฉันต้องการให้ขอบเข้าไปในจุดยอดเหล่านี้ด้วยอุปกรณ์ประกอบฉากพิเศษเหล่านี้ และฉันกำลังใช้ฟังก์ชัน in_edges แต่ดูเหมือนว่าจะส่งคืนจุดยอดใน อยากให้คืนขอบ รู้วิธีทำง่ายๆ มั้ย? - person Alexo; 07.03.2018
comment
@Alexo ฉันได้อัปเดตคำตอบของฉันแล้ว ความคิดเห็นของคุณเป็นเรื่องยากที่จะเข้าใจ แต่ฉันคิดว่าคุณต้องการอะไรแบบนั้น โปรดเขียนปัญหาที่คุณต้องการแก้ไขในครั้งต่อไป คุณสามารถอัปเดตคำถามของคุณด้านบนได้ - person Arda Aytekin; 07.03.2018
comment
สวัสดี @Arda ขอบคุณและใช่ มันเป็นสิ่งที่ฉันต้องการ ปัญหาเกี่ยวกับปัญหาที่แท้จริงของฉันที่ฉันอยากจะแก้ไขคือ: 1. มันค่อนข้างใหญ่และต้องใช้ไฟล์จูเลียหลายไฟล์ที่มีออบเจ็กต์ กราฟ และตัวแปรที่แตกต่างกันหลายอย่าง 2. เนื้อหาและข้อมูลของแบบจำลองไม่สามารถวางออนไลน์ได้ นี่คือเหตุผลที่ฉันพยายามอธิบายปัญหาของฉันด้วยแบบจำลองง่ายๆ และคุณทำถูกแล้ว จริงๆ แล้วฉันไม่รู้วิธีกำหนดฟังก์ชันสำหรับอินพุตของฟังก์ชัน filter_edges ขอขอบคุณอีกครั้ง. - person Alexo; 09.03.2018
comment
@Alexo พูดตามตรงฉันทำไม่ได้ตั้งแต่นัดแรก บางทีเราควรเปิดคำขอดึงไปยังเอกสารประกอบของแพ็คเกจนั้น หากมีตัวอย่างเกี่ยวกับสถานการณ์นี้ คนเช่นคุณในอนาคตก็จะง่ายขึ้น ฉันเพิ่งตรวจสอบวิธีใช้ REPL และคาดเดาการทำงานโดยใช้ฟังก์ชันที่ส่งออกจากแพ็คเกจ ตาม MWE ของคุณ ในความคิดของฉัน การเขียนโค้ดที่ตัดตอนมาด้วย เพียง สาม add_edge! และ set_props! ก็เพียงพอแล้ว และถามคำถามที่คุณถามที่นี่ในความคิดเห็น: ฉันจะกรองขอบทั้งสองได้อย่างไร คุณสมบัติ? ฉันอยากได้ 1 => 3 - person Arda Aytekin; 09.03.2018
comment
ใช่ ฉันไม่พบคำอธิบายเกี่ยวกับวิธีการกำหนดฟังก์ชัน fn นี้ตามที่อธิบายไว้ในหน้า Github เขียนไว้เพียงว่าอินพุตควรเป็น (g,v) ข้อมูลเพิ่มเติมสำหรับคนในอนาคตจะดีเท่านั้น และใช่สำหรับฟังก์ชัน in_edges ดูเหมือนว่าจะไม่ส่งคืนขอบ อย่างไรก็ตาม ฉันไม่รู้วิธีเปิดคำขอดึงข้อมูล ไม่อย่างนั้น... ฉันเพิ่งเริ่มจูเลียเมื่อสองเดือนก่อน - person Alexo; 12.03.2018
comment
ฟังก์ชัน filter_vertices ที่รับกราฟและจุดยอดมีวัตถุประสงค์เพื่อส่งคืนบูลีนหากควรรวมจุดยอดด้วย ดู juliagraphs.github.io/MetaGraphs.jl/latest /{MetaGraphs.AbstractMetaGraph,Function}: ส่งคืนตัววนซ้ำไปยังจุดยอดทั้งหมด... โดยที่ฟังก์ชัน fn ส่งคืนค่าจริงเฉพาะสำหรับจุดยอดที่ควรรวมไว้ในตัววนซ้ำ - person sbromberger; 13.03.2018
comment
หากมีตัวอย่างเกี่ยวกับสถานการณ์นี้ คนเช่นคุณในอนาคตก็จะง่ายขึ้น ฉันยอมรับว่าเอกสารประกอบถูกต้อง ตัวอย่างคงจะดี ฉันต้องตรวจสอบ บรรทัดที่สอดคล้องกันเพื่อ เขียนโค้ดอย่างถูกต้อง - person Arda Aytekin; 13.03.2018

ฉันพบวิธีแก้ปัญหานี้:

function filter_function1(g,prop1,prop2)
  fil1=filter_vertices(g,:prop1,prop1)
  fil2=filter_vertices(g,:prop2,prop2)
  filter=intersect(fil1,fil2)
  return filter
end

ดูเหมือนว่าจะใช้งานได้และค่อนข้างง่ายที่จะนำไปใช้ ฉันไม่รู้ว่าฟังก์ชัน filter_vertices ใช้พลังงานในการคำนวณมากหรือไม่ มิฉะนั้นดูเหมือนว่าจะใช้การวนซ้ำแบบง่าย ๆ เช่นนี้:

function filter_function2(g,prop1,prop2)
  filter=Set{Int64}()
  fil1=filter_vertices(g,:prop1,prop1)
  for f in fil1
      if get_prop(g,f,:prop2)==prop2
          push!(filter,f)
      end
  end
  return filter
end

ฉันเปิดรับคำตอบอื่น ๆ หากคุณมีคำตอบที่หรูหรากว่านี้

person Alexo    schedule 07.03.2018
comment
ตรวจสอบคำตอบของฉัน ฉันไม่คิดว่าคุณควรวนซ้ำสองครั้ง --- แพ็คเกจอนุญาตให้คุณเขียนตัวกรองแบบกำหนดเอง ด้านบน filter_function1 วนซ้ำกราฟของคุณสองครั้ง และเรียก intersect ความซับซ้อนมีขนาดใหญ่มาก คุณสามารถทำให้ filter_function2 ดีขึ้นได้ด้วยการทำความเข้าใจอาเรย์แบบง่ายๆ - person Arda Aytekin; 07.03.2018