|
1 | 1 | module TestCSets |
2 | 2 | using Test |
3 | | -using Random: seed! |
4 | 3 |
|
5 | 4 | using Catlab.GATs, Catlab.Theories, Catlab.Graphs, Catlab.CategoricalAlgebra |
6 | 5 |
|
7 | | -seed!(100) |
8 | | - |
9 | 6 | @present SchDDS(FreeSchema) begin |
10 | 7 | X::Ob |
11 | 8 | Φ::Hom(X,X) |
@@ -423,137 +420,6 @@ colim = pushout(β, γ, type_components=[g,h]) |
423 | 420 | h′ = (D=FinFunction(Dict(:z=>:b)),) |
424 | 421 | @test_throws ErrorException pushout(β, γ, type_components=[g,h′]) |
425 | 422 |
|
426 | | -# Finding C-set morphisms |
427 | | -######################### |
428 | | - |
429 | | -# Graphs |
430 | | -#------- |
431 | | - |
432 | | -g, h = path_graph(Graph, 3), path_graph(Graph, 4) |
433 | | -homs = [CSetTransformation((V=[1,2,3], E=[1,2]), g, h), |
434 | | - CSetTransformation((V=[2,3,4], E=[2,3]), g, h)] |
435 | | -@test homomorphisms(g, h) == homs |
436 | | -@test homomorphisms(g, h, alg=HomomorphismQuery()) == homs |
437 | | -@test !is_isomorphic(g, h) |
438 | | - |
439 | | -I = ob(terminal(Graph)) |
440 | | -α = CSetTransformation((V=[1,1,1], E=[1,1]), g, I) |
441 | | -@test homomorphism(g, I) == α |
442 | | -@test homomorphism(g, I, alg=HomomorphismQuery()) == α |
443 | | -@test !is_homomorphic(g, I, monic=true) |
444 | | -@test !is_homomorphic(I, h) |
445 | | -@test !is_homomorphic(I, h, alg=HomomorphismQuery()) |
446 | | - |
447 | | -# Graph homomorphism starting from partial assignment, e.g. vertex assignment. |
448 | | -α = CSetTransformation((V=[2,3,4], E=[2,3]), g, h) |
449 | | -@test homomorphisms(g, h, initial=(V=[2,3,4],)) == [α] |
450 | | -@test homomorphisms(g, h, initial=(V=Dict(1 => 2, 3 => 4),)) == [α] |
451 | | -@test homomorphisms(g, h, initial=(E=Dict(1 => 2),)) == [α] |
452 | | -# Inconsistent initial assignment. |
453 | | -@test !is_homomorphic(g, h, initial=(V=Dict(1 => 1), E=Dict(1 => 3))) |
454 | | -# Consistent initial assignment but no extension to complete assignment. |
455 | | -@test !is_homomorphic(g, h, initial=(V=Dict(1 => 2, 3 => 3),)) |
456 | | - |
457 | | -# Monic and iso on a componentwise basis. |
458 | | -g1, g2 = path_graph(Graph, 3), path_graph(Graph, 2) |
459 | | -add_edges!(g1, [1,2,3,2], [1,2,3,3]) # loops on each node and one double arrow |
460 | | -add_edge!(g2, 1, 2) # double arrow |
461 | | -@test length(homomorphisms(g2, g1)) == 8 # each vertex + 1->2, and four for 2->3 |
462 | | -@test length(homomorphisms(g2, g1, monic=[:V])) == 5 # remove vertex solutions |
463 | | -@test length(homomorphisms(g2, g1, monic=[:E])) == 2 # two for 2->3 |
464 | | -@test length(homomorphisms(g2, g1, iso=[:E])) == 0 |
465 | | - |
466 | | -# Loose |
467 | | -s1 = SetAttr{Int}() |
468 | | -add_part!(s1, :X, f=1) |
469 | | -add_part!(s1, :X, f=1) |
470 | | -s2, s3 = deepcopy(s1), deepcopy(s1) |
471 | | -set_subpart!(s2, :f, [2,1]) |
472 | | -set_subpart!(s3, :f, [20,10]) |
473 | | -@test length(homomorphisms(s2,s3))==0 |
474 | | -@test length(homomorphisms(s2,s3; type_components=(D=x->10*x,)))==1 |
475 | | -@test homomorphism(s2,s3; type_components=(D=x->10*x,)) isa LooseACSetTransformation |
476 | | -@test length(homomorphisms(s1,s1; type_components=(D=x->x^x,)))==4 |
477 | | - |
478 | | -#Backtracking with monic and iso failure objects |
479 | | -g1, g2 = path_graph(Graph, 3), path_graph(Graph, 2) |
480 | | -rem_part!(g1,:E,2) |
481 | | -@test_throws ErrorException homomorphism(g1,g2;monic=true,error_failures=true) |
482 | | - |
483 | | -# Symmetric graphs |
484 | | -#----------------- |
485 | | - |
486 | | -g, h = path_graph(SymmetricGraph, 4), path_graph(SymmetricGraph, 4) |
487 | | -αs = homomorphisms(g, h) |
488 | | -@test all(is_natural(α) for α in αs) |
489 | | -@test length(αs) == 16 |
490 | | -αs = isomorphisms(g, h) |
491 | | -@test length(αs) == 2 |
492 | | -@test map(α -> collect(α[:V]), αs) == [[1,2,3,4], [4,3,2,1]] |
493 | | -g = path_graph(SymmetricGraph, 3) |
494 | | -@test length(homomorphisms(g, h, monic=true)) == 4 |
495 | | - |
496 | | -# Graph colorability via symmetric graph homomorphism. |
497 | | -# The 5-cycle has chromatic number 3 but the 6-cycle has chromatic number 2. |
498 | | -K₂, K₃ = complete_graph(SymmetricGraph, 2), complete_graph(SymmetricGraph, 3) |
499 | | -C₅, C₆ = cycle_graph(SymmetricGraph, 5), cycle_graph(SymmetricGraph, 6) |
500 | | -@test !is_homomorphic(C₅, K₂) |
501 | | -@test is_homomorphic(C₅, K₃) |
502 | | -@test is_natural(homomorphism(C₅, K₃)) |
503 | | -@test is_homomorphic(C₆, K₂) |
504 | | -@test is_natural(homomorphism(C₆, K₂)) |
505 | | - |
506 | | -# Labeled graphs |
507 | | -#--------------- |
508 | | - |
509 | | -g = cycle_graph(LabeledGraph{Symbol}, 4, V=(label=[:a,:b,:c,:d],)) |
510 | | -h = cycle_graph(LabeledGraph{Symbol}, 4, V=(label=[:c,:d,:a,:b],)) |
511 | | -α = ACSetTransformation((V=[3,4,1,2], E=[3,4,1,2]), g, h) |
512 | | -@test homomorphism(g, h) == α |
513 | | -@test homomorphism(g, h, alg=HomomorphismQuery()) == α |
514 | | -h = cycle_graph(LabeledGraph{Symbol}, 4, V=(label=[:a,:b,:d,:c],)) |
515 | | -@test !is_homomorphic(g, h) |
516 | | -@test !is_homomorphic(g, h, alg=HomomorphismQuery()) |
517 | | - |
518 | | -# Random |
519 | | -#------- |
520 | | - |
521 | | -comps(x) = sort([k=>collect(v) for (k,v) in pairs(components(x))]) |
522 | | -# same set of morphisms |
523 | | -K₆ = complete_graph(SymmetricGraph, 6) |
524 | | -hs = homomorphisms(K₆,K₆) |
525 | | -rand_hs = homomorphisms(K₆,K₆; random=true) |
526 | | -@test sort(hs,by=comps) == sort(rand_hs,by=comps) # equal up to order |
527 | | -@test hs != rand_hs # not equal given order |
528 | | -@test homomorphism(K₆,K₆) != homomorphism(K₆,K₆;random=true) |
529 | | - |
530 | | -# As a macro |
531 | | -#----------- |
532 | | - |
533 | | -g = cycle_graph(LabeledGraph{String}, 4, V=(label=["a","b","c","d"],)) |
534 | | -h = cycle_graph(LabeledGraph{String}, 4, V=(label=["b","c","d","a"],)) |
535 | | -α = @acset_transformation g h |
536 | | -β = @acset_transformation g h begin |
537 | | - V = [4,1,2,3] |
538 | | - E = [4,1,2,3] |
539 | | -end monic=true |
540 | | -γ = @acset_transformation g h begin end monic=[:V] |
541 | | -@test α[:V](1) == 4 |
542 | | -@test α[:E](1) == 4 |
543 | | -@test α == β == γ |
544 | | - |
545 | | -x = @acset Graph begin |
546 | | - V = 2 |
547 | | - E = 2 |
548 | | - src = [1,1] |
549 | | - tgt = [2,2] |
550 | | -end |
551 | | -@test length(@acset_transformations x x) == length(@acset_transformations x x monic=[:V]) == 4 |
552 | | -@test length(@acset_transformations x x monic = true) == 2 |
553 | | -@test length(@acset_transformations x x begin V=[1,2] end monic = [:E]) == 2 |
554 | | -@test length(@acset_transformations x x begin V = Dict(1=>1) end monic = [:E]) == 2 |
555 | | -@test_throws ErrorException @acset_transformation g h begin V = [4,3,2,1]; E = [1,2,3,4] end |
556 | | - |
557 | 423 | # Sub-C-sets |
558 | 424 | ############ |
559 | 425 |
|
@@ -646,65 +512,6 @@ for i in 1:3 |
646 | 512 | path_graph(Graph, i)) |
647 | 513 | end |
648 | 514 |
|
649 | | -# Enumeration of subobjects |
650 | | -G = path_graph(Graph, 3) |
651 | | -subG, subobjs = subobject_graph(G) |> collect |
652 | | -@test length(subobjs) == 13 # ⊤,2x •→• •,2x •→•, •••,3x ••, 3x •, ⊥ |
653 | | -@test length(incident(subG, 13, :src)) == 13 # ⊥ is initial |
654 | | -@test length(incident(subG, 1, :src)) == 1 # ⊤ is terminal |
655 | | - |
656 | | -# Graph and ReflexiveGraph should have same subobject structure |
657 | | -subG = subobject_graph(path_graph(Graph, 2)) |> first |
658 | | -subRG, sos = subobject_graph(path_graph(ReflexiveGraph, 2)) |
659 | | -@test all(is_natural, hom.(sos)) |
660 | | -@test is_isomorphic(subG, subRG) |
661 | | - |
662 | | -# Partial overlaps |
663 | | -G,H = path_graph.(Graph, 2:3) |
664 | | -os = collect(partial_overlaps(G,G)) |
665 | | -@test length(os) == 7 # ⊤, ••, 4× •, ⊥ |
666 | | - |
667 | | -po = partial_overlaps([G,H]) |
668 | | -@test length(collect(po))==12 # 2×⊤, 3ו•, 6× •, ⊥ |
669 | | -@test all(m -> apex(m) == G, Iterators.take(po, 2)) # first two are •→• |
670 | | -@test all(m -> apex(m) == Graph(2), |
671 | | - Iterators.take(Iterators.drop(po, 2), 3)) # next three are • • |
672 | | - |
673 | | -# Maximum Common C-Set |
674 | | -###################### |
675 | | - |
676 | | -""" |
677 | | -Searching for overlaps: •→•→•↺ vs ↻•→•→• |
678 | | -Two results: •→•→• || •↺ •→• |
679 | | -""" |
680 | | -g1 = @acset WeightedGraph{Bool} begin |
681 | | - V=3; E=3; src=[1,1,2]; tgt=[1,2,3]; weight=[true,false,false] |
682 | | -end |
683 | | -g2 = @acset WeightedGraph{Bool} begin |
684 | | - V=3; E=3; src=[1,2,3]; tgt=[2,3,3]; weight=[true,false,false] |
685 | | -end |
686 | | -apex1 = @acset WeightedGraph{Bool} begin |
687 | | - V=3; E=2; Weight=2; src=[1,2]; tgt=[2,3]; weight=AttrVar.(1:2) |
688 | | -end |
689 | | -apex2 = @acset WeightedGraph{Bool} begin |
690 | | - V=3; E=2; Weight=2; src=[1,3]; tgt=[2,3]; weight=AttrVar.(1:2) |
691 | | -end |
692 | | - |
693 | | -results = collect(maximum_common_subobject(g1, g2)) |
694 | | -@test length(results) == 2 |
695 | | -is_iso1 = map(result -> is_isomorphic(first(result), apex1), results) |
696 | | -@test sum(is_iso1) == 1 |
697 | | -results = first(is_iso1) ? results : reverse(results) |
698 | | -(apx1,((L1,R1),)), (apx2,((L2,R2),)) = results |
699 | | -@test collect(L1[:V]) == [1,2,3] |
700 | | -@test collect(R1[:V]) == [1,2,3] |
701 | | -@test L1(apx1) == Subobject(g1, V=[1,2,3], E=[2,3]) |
702 | | - |
703 | | -@test is_isomorphic(apx2, apex2) |
704 | | -@test collect(L2[:V]) == [1,2,3] |
705 | | -@test collect(R2[:V]) == [3,1,2] |
706 | | -@test L2(apx2) == Subobject(g1, V=[1,2,3], E=[1,3]) |
707 | | - |
708 | 515 | # AttrVars |
709 | 516 | ########## |
710 | 517 |
|
|
0 commit comments