Filter simpul pada beberapa properti - Julia

Saya sedang mengerjakan julia dengan perpustakaan Metagraphs.jl. Untuk melakukan masalah optimasi, saya ingin mendapatkan himpunan/daftar sisi pada grafik yang menunjuk ke himpunan simpul khusus yang memiliki 2 properti tertentu yang sama.

Tebakan pertama saya adalah mendapatkan set/daftar simpul terlebih dahulu. Namun saya menghadapi masalah pertama yaitu fungsi filter_vertices sepertinya tidak menerima penerapan filter pada lebih dari satu properti. Berikut ini contoh apa yang ingin saya lakukan:

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))

Dan saya ingin col menemukan simpul 3 dan tidak yang lain.

Tetapi filter_vertices hanya akan menerima satu properti pada satu waktu dan kemudian membuatnya lebih mahal untuk melakukan perulangan dengan 2 filter dan kemudian mencoba membandingkan untuk mengurutkan daftar dengan simpul yang memiliki kedua properti tersebut.

Mempertimbangkan ukuran grafik saya, saya ingin menghindari mendefinisikan kumpulan ini dengan banyak loop dan mahal. Adakah di antara Anda yang memiliki gagasan tentang cara mengatasi masalah ini dengan cara yang mudah dan lembut?

Saya akhirnya membuat ini untuk menjawab pertanyaan saya sendiri:

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)

Tapi beri tahu saya jika Anda mendapatkan sesuatu yang lebih menarik

Terima kasih atas bantuan Anda!


person Alexo    schedule 07.03.2018    source sumber
comment
Harap pertimbangkan untuk membuka masalah di repo LightGraphs/MetaGraphs. Dengan cara ini kami segera diberitahu dan dapat membantu secara langsung.   -  person sbromberger    schedule 13.04.2018


Jawaban (2)


Harap berikan contoh kerja minimal yang dapat kami salin dan tempel, dan segera mulai. Harap tunjukkan juga di mana masalah terjadi dalam kode. Di bawah ini adalah contoh skenario Anda:

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]

Silakan periksa ?filter_vertices --- ini memberi Anda petunjuk tentang apa/bagaimana menulis untuk menentukan filter khusus Anda.

EDIT. Untuk memfilter tepi, Anda dapat melihat ?filter_edges untuk mengetahui apa yang Anda perlukan untuk mencapai pemfilteran tepi. Tambahkan kutipan kode di bawah ini ke solusi di atas untuk mendapatkan hasil Anda:

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
Terima kasih atas bantuan Anda, ini memang berfungsi lebih baik. Tapi saya punya pertanyaan tentang sisa dari apa yang ingin saya lakukan, saya ingin membuat tepi masuk ke simpul ini dengan alat peraga khusus ini dan saya menggunakan fungsi in_edges tetapi tampaknya mengembalikan simpul masuk. Saya ingin mengembalikan tepinya, tahukah Anda cara sederhana untuk melakukannya? - person Alexo; 07.03.2018
comment
@Alexo Saya telah memperbarui jawaban saya. Sulit untuk memahami dari komentar Anda, tetapi saya rasa Anda memerlukan sesuatu seperti itu. Silakan, untuk kali berikutnya, tuliskan masalah persis yang ingin Anda selesaikan. Anda dapat memperbarui pertanyaan Anda di atas. - person Arda Aytekin; 07.03.2018
comment
Hai @Arda, terima kasih dan ya, itulah yang saya butuhkan. Masalah mengenai masalah saya sebenarnya yang ingin saya selesaikan adalah: 1. Ini cukup besar dan memerlukan beberapa file julia dengan beberapa objek, grafik, variabel yang berbeda. 2. Konten dan data model tidak dapat ditampilkan secara online. Inilah sebabnya saya mencoba menjelaskan masalah saya dengan model sederhana dan Anda melakukannya dengan benar. Saya sebenarnya tidak tahu cara mendefinisikan fungsi untuk input fungsi filter_edges. Terima kasih lagi. - person Alexo; 09.03.2018
comment
@Alexo Sejujurnya, saya tidak bisa melakukannya pada tembakan pertama. Mungkin kita harus membuka permintaan tarik ke dokumentasi paket itu. Jika ada contoh mengenai skenario ini, akan lebih mudah bagi orang seperti Anda di masa depan. Saya baru saja memeriksa bantuan REPL, dan menebak-nebak menggunakan fungsi yang diekspor dari paket. Sesuai dengan MWE Anda, menurut pendapat saya, cukup menulis kutipan kode Anda dengan hanya tiga add_edge! dan set_props!, dan ajukan pertanyaan yang Anda ajukan di sini di komentar: Bagaimana cara memfilter tepi pada dua properti? Saya ingin mendapatkan 1 => 3. - person Arda Aytekin; 09.03.2018
comment
ya, saya tidak dapat menemukan penjelasan apa pun tentang cara mendefinisikan fungsi fn yang mereka jelaskan di halaman Github. Hanya ditulis bahwa inputnya harus (g,v). Lebih banyak informasi untuk orang-orang di masa depan pasti akan bermanfaat. Dan ya untuk fungsi in_edges, sepertinya tidak mengembalikan edge. Namun saya tidak tahu cara membuka permintaan tarik atau yang lain... Saya baru memulai julia dua bulan lalu. - person Alexo; 12.03.2018
comment
Fungsi filter_vertices yang mengambil grafik dan simpul dimaksudkan untuk mengembalikan boolean jika simpul tersebut harus disertakan. Lihat juliagraphs.github.io/MetaGraphs.jl/latest /{MetaGraphs.AbstractMetaGraph,Function}: Mengembalikan iterator ke semua simpul... dengan fungsi fn mengembalikan nilai true hanya untuk simpul yang harus disertakan dalam iterator. - person sbromberger; 13.03.2018
comment
Jika ada contoh mengenai skenario ini, akan lebih mudah bagi orang seperti Anda di masa depan. Saya setuju bahwa dokumentasi mendokumentasikannya dengan benar. Contohnya pasti menyenangkan. Saya perlu memeriksa baris yang sesuai untuk tulis kodenya dengan benar. - person Arda Aytekin; 13.03.2018

Saya menemukan solusi ini:

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

Hal ini tampaknya berhasil dan cukup mudah diterapkan. Hanya saja saya tidak tahu apakah fungsi filter_vertices memakan banyak daya komputasi. Kalau tidak, loop sederhana seperti ini sepertinya juga berfungsi:

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

Saya terbuka untuk jawaban lain jika Anda memiliki jawaban yang lebih elegan.

person Alexo    schedule 07.03.2018
comment
Periksa jawaban saya. Saya tidak berpikir Anda harus mengulang dua kali --- paket ini memungkinkan Anda untuk menulis filter khusus. Di atas, filter_function1 mengulangi grafik Anda dua kali, dan memanggil intersect. Kompleksitasnya sangat besar. Anda dapat membuat filter_function2 lebih baik dengan pemahaman array sederhana. - person Arda Aytekin; 07.03.2018