123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- import time
- import matcher as j # joeri's matcher
- import graph as sgraph # sten's graph
- import patternMatching as s # sten's matcher
- import generator
- def j_to_s(j):
- s = sgraph.Graph()
- m = {}
- for jv in j.vtxs:
- sv = s.addCreateVertex(jv.value) # value becomes type
- m[jv] = sv
- for je in j.edges:
- s.addCreateEdge(m[je.src], m[je.tgt], "e") # only one type
- return s
- def s_to_j(s):
- jg = j.Graph()
- jg.vtxs = [ j.Vertex(typ) for (typ,svs) in s.vertices.items() for sv in svs ]
- m = { sv : jg.vtxs[i] for svs in s.vertices.values() for i,sv in enumerate(svs) }
- jg.edges = [j.Edge(m[se.src], m[se.tgt]) for ses in s.edges.values() for se in ses ]
- return j
- def run_benchmark(jhost, jguest, shost, sguest, expected=None):
- j_durations = 0
- s_durations = 0
- # benchmark Joeri
- m = j.MatcherVF2(host, guest,
- lambda g_vtx, h_vtx: g_vtx.value == h_vtx.value) # all vertices can be matched
- iterations = 50
- print(" Patience (joeri)...")
- for n in range(iterations):
- time_start = time.perf_counter_ns()
- matches = [mm for mm in m.match()]
- time_end = time.perf_counter_ns()
- duration = time_end - time_start
- j_durations += duration
- print(f' {iterations} iterations, took {j_durations/1000000:.3f} ms, {j_durations/iterations/1000000:.3f} ms per iteration')
- if expected == None:
- print(f" {len(matches)} matches")
- else:
- if len(matches) == expected:
- print(" correct (probably)")
- else:
- print(f" WRONG! expected: {expected}, got: {len(matches)}")
- # print([m.mapping_vtxs for m in matches])
- # print([m.mapping_edges for m in matches])
- # benchmark Sten
- m = s.PatternMatching()
- print(" Patience (sten)...")
- for n in range(iterations):
- time_start = time.perf_counter_ns()
- matches = [mm for mm in m.matchVF2(sguest, shost)]
- time_end = time.perf_counter_ns()
- duration = time_end - time_start
- s_durations += duration
- print(f' {iterations} iterations, took {s_durations/1000000:.3f} ms, {s_durations/iterations/1000000:.3f} ms per iteration')
- if expected == None:
- print(f" {len(matches)} matches")
- else:
- if len(matches) == expected:
- print(" correct (probably)")
- else:
- print(f" WRONG! expected: {expected}, got: {len(matches)}")
- # print(matches)
- print(f" joeri is {s_durations/j_durations:.2f} times faster")
- if __name__ == "__main__":
- print("\nBENCHMARK: small graph, simple pattern")
- host = j.Graph()
- host.vtxs = [j.Vertex(0), j.Vertex(0), j.Vertex(0), j.Vertex(0)]
- host.edges = [
- j.Edge(host.vtxs[0], host.vtxs[1]),
- j.Edge(host.vtxs[1], host.vtxs[2]),
- j.Edge(host.vtxs[2], host.vtxs[0]),
- j.Edge(host.vtxs[2], host.vtxs[3]),
- j.Edge(host.vtxs[3], host.vtxs[2]),
- ]
- guest = j.Graph()
- guest.vtxs = [
- j.Vertex(0),
- j.Vertex(0)]
- guest.edges = [
- # Look for a simple loop:
- j.Edge(guest.vtxs[0], guest.vtxs[1]),
- j.Edge(guest.vtxs[1], guest.vtxs[0]),
- ]
- # because of the symmetry in our pattern, there will be 2 matches
- run_benchmark(host, guest, j_to_s(host), j_to_s(guest), expected=2)
- #######################################################################
- print("\nBENCHMARK: larger graph, simple pattern")
- host = j.Graph()
- host.vtxs = [
- j.Vertex('triangle'), # 0
- j.Vertex('square'), # 1
- j.Vertex('square'), # 2
- j.Vertex('circle'), # 3
- j.Vertex('circle'), # 4
- j.Vertex('circle'), # 5
- ]
- host.edges = [
- # not a match:
- j.Edge(host.vtxs[0], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[0]),
- # will be a match:
- j.Edge(host.vtxs[1], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[1]),
- # noise:
- j.Edge(host.vtxs[1], host.vtxs[2]),
- # will be a match:
- j.Edge(host.vtxs[2], host.vtxs[4]),
- j.Edge(host.vtxs[4], host.vtxs[2]),
- # noise:
- j.Edge(host.vtxs[0], host.vtxs[1]),
- j.Edge(host.vtxs[0], host.vtxs[3]),
- j.Edge(host.vtxs[0], host.vtxs[0]),
- j.Edge(host.vtxs[1], host.vtxs[1]),
- # will be a match:
- j.Edge(host.vtxs[3], host.vtxs[2]),
- j.Edge(host.vtxs[2], host.vtxs[3]),
- ]
- guest = j.Graph()
- guest.vtxs = [
- j.Vertex('square'), # 0
- j.Vertex('circle')] # 1
- guest.edges = [
- j.Edge(guest.vtxs[0], guest.vtxs[1]),
- j.Edge(guest.vtxs[1], guest.vtxs[0]),
- ]
- # should give 3 matches
- run_benchmark(host, guest, j_to_s(host), j_to_s(guest), expected=3)
- #######################################################################
- print("\nBENCHMARK: same as before, but with larger pattern")
- host = j.Graph()
- host.vtxs = [
- j.Vertex('triangle'), # 0
- j.Vertex('square'), # 1
- j.Vertex('square'), # 2
- j.Vertex('circle'), # 3
- j.Vertex('circle'), # 4
- j.Vertex('circle'), # 5
- ]
- host.edges = [
- # not a match:
- j.Edge(host.vtxs[0], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[0]),
- # will be a match:
- j.Edge(host.vtxs[1], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[1]),
- # noise:
- j.Edge(host.vtxs[1], host.vtxs[2]),
- # will be a match:
- j.Edge(host.vtxs[2], host.vtxs[4]),
- j.Edge(host.vtxs[4], host.vtxs[2]),
- # noise:
- j.Edge(host.vtxs[0], host.vtxs[1]),
- j.Edge(host.vtxs[0], host.vtxs[3]),
- j.Edge(host.vtxs[0], host.vtxs[0]),
- j.Edge(host.vtxs[1], host.vtxs[1]),
- # will be a match:
- j.Edge(host.vtxs[3], host.vtxs[2]),
- j.Edge(host.vtxs[2], host.vtxs[3]),
- ]
- guest = j.Graph()
- guest.vtxs = [
- j.Vertex('square'), # 0
- j.Vertex('circle'), # 1
- j.Vertex('square')] # 2
- guest.edges = [
- j.Edge(guest.vtxs[0], guest.vtxs[1]),
- j.Edge(guest.vtxs[1], guest.vtxs[0]),
- j.Edge(guest.vtxs[2], guest.vtxs[0]),
- ]
- # this time, only 2 matches
- run_benchmark(host, guest, j_to_s(host), j_to_s(guest), expected=2)
- #######################################################################
- print("\nBENCHMARK: disconnected pattern")
- host = j.Graph()
- host.vtxs = [
- j.Vertex('triangle'), # 0
- j.Vertex('square'), # 1
- j.Vertex('square'), # 2
- j.Vertex('circle'), # 3
- j.Vertex('circle'), # 4
- j.Vertex('circle'), # 5
- j.Vertex('bear'),
- j.Vertex('bear'),
- ]
- host.edges = [
- # not a match:
- j.Edge(host.vtxs[0], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[0]),
- # will be a match:
- j.Edge(host.vtxs[1], host.vtxs[5]),
- j.Edge(host.vtxs[5], host.vtxs[1]),
- # noise:
- j.Edge(host.vtxs[1], host.vtxs[2]),
- # will be a match:
- j.Edge(host.vtxs[2], host.vtxs[4]),
- j.Edge(host.vtxs[4], host.vtxs[2]),
- # noise:
- j.Edge(host.vtxs[0], host.vtxs[1]),
- j.Edge(host.vtxs[0], host.vtxs[3]),
- j.Edge(host.vtxs[0], host.vtxs[0]),
- j.Edge(host.vtxs[1], host.vtxs[1]),
- # will be a match:
- j.Edge(host.vtxs[3], host.vtxs[2]),
- j.Edge(host.vtxs[2], host.vtxs[3]),
- ]
- guest = j.Graph()
- guest.vtxs = [
- j.Vertex('square'), # 0
- j.Vertex('circle'), # 1
- j.Vertex('bear')]
- guest.edges = [
- j.Edge(guest.vtxs[0], guest.vtxs[1]),
- j.Edge(guest.vtxs[1], guest.vtxs[0]),
- ]
- # the 'bear' in our pattern can be matched with any of the two bears in the graph, effectively doubling the number of matches
- run_benchmark(host, guest, j_to_s(host), j_to_s(guest), expected=6)
- #######################################################################
- print("\nBENCHMARK: larger graph")
- shost, sguest = generator.get_large_host_and_guest()
- run_benchmark(s_to_j(shost), s_to_j(sguest), shost, sguest)
- #######################################################################
- print("\nBENCHMARK: large random graph")
- import random
- random.seed(0)
- shost, sguest = generator.get_random_host_and_guest(
- nr_vtxs = 10,
- nr_vtx_types = 0,
- nr_edges = 20,
- nr_edge_types = 0,
- )
- run_benchmark(s_to_j(shost), s_to_j(sguest), shost, sguest)
|