### ----------------------------------------------------
### -- Graph
### -- Licenses: Artistic-2.0
### -- Authors: Anton Antonov
### -- File: t/14-operations.rakutest
### ----------------------------------------------------
use v6.d;
use Test;

use lib <. lib>;
use Graph;
use Graph::Star;


my $d1 = Graph.new: [
    %('from' => '1', 'to' => '2', 'weight' => 1), %('from' => '2', 'to' => '3', 'weight' => 1),
    %('from' => '2', 'to' => '4', 'weight' => 1), %('from' => '3', 'to' => '1', 'weight' => 1),
    %('from' => '4', 'to' => '3', 'weight' => 1)],
        :directed;

my $d2 = Graph.new: [
    %('from' => '1', 'to' => '2', 'weight' => 1), %('from' => '3', 'to' => '2', 'weight' => 1),
    %('from' => '4', 'to' => '1', 'weight' => 1), %('from' => '4', 'to' => '3', 'weight' => 1)],
        :directed;

my $g =
        Graph.new: [
            %('from' => '1', 'to' => '2', 'weight' => 1), %('from' => '1', 'to' => '6', 'weight' => 1),
            %('from' => '2', 'to' => '3', 'weight' => 1), %('from' => '3', 'to' => '4', 'weight' => 1),
            %('from' => '4', 'to' => '5', 'weight' => 1), %('from' => '5', 'to' => '6', 'weight' => 1)];

my $h =
        Graph.new: [
            %('from' => '1', 'to' => '2', 'weight' => 1), %('from' => '1', 'to' => '3', 'weight' => 1),
            %('from' => '1', 'to' => '4', 'weight' => 1), %('from' => '1', 'to' => '5', 'weight' => 1),
            %('from' => '1', 'to' => '6', 'weight' => 1)];

## 1
subtest {
    ok $d1.union($d2);
    ok $g.union($h);
    my $u = $g.union($h);
    is-deeply
            $u.vertex-list,
            (1 .. 6)».Str,
            'expected vertices 1';
    is-deeply
            $u.vertex-list,
            ($g.vertex-list (|) $h.vertex-list).keys.sort.List,
            'expected vertices 2';
    is-deeply
            $u.edge-list.sort,
            [1 => 2, 1 => 6, 2 => 3, 3 => 4, 4 => 5, 5 => 6, 1 => 3, 1 => 4, 1 => 5].map({ $_.key.Str => $_.value.Str }).sort,
            "expected edges";
}, "Union";

## 2
subtest {
    ok $d1.intersection($d2);
    ok $g.intersection($h);
    my $u = $g.intersection($h);
    is-deeply
            $u.vertex-list,
            (1 .. 6)».Str,
            'expected vertices 1';
    is-deeply
            $u.vertex-list,
            ($g.vertex-list (&) $h.vertex-list).keys.sort.List,
            'expected vertices 2';
    is-deeply
            $u.edge-list.sort,
            ('1' => '2', '1' => '6').sort,
            "expected edges";
}, "Intersection";

## 3
subtest {

    ok $g.difference($h);
    my $u = $g.difference($h);

    is-deeply
            $u.vertex-list,
            (1 .. 6)».Str,
            'expected vertices 1';

    is-deeply
            $u.vertex-list,
            ($g.vertex-list (|) $h.vertex-list).keys.sort.List,
            'expected vertices 2';

    is-deeply
            $u.edge-list.sort,
            ('2' => '3', '3' => '4', '4' => '5', '5' => '6').sort,
            "expected edges";

    is
            $g.difference($g).is-empty,
            True,
            "self-difference produces an empty graph";

    is-deeply
            $d1.difference($d2).edge-list.sort,
            ('2' => '3', '2' => '4', '3' => '1').sort,
            "expected edges from directed graphs";
}, "Difference";

## 4
subtest {
    is-deeply
            $d1.disjoint-union($d2).vertex-list,
            (^($d1.vertex-count + $d2.vertex-count))».Str.sort.List,
            "Expected vertexes for two (directed)";

    is-deeply
            $g.disjoint-union($h).vertex-list,
            (^($g.vertex-count + $h.vertex-count))».Str.sort.List,
            "Expected vertexes for two (undericted)";

    is-deeply
            $d1.disjoint-union($h).vertex-list,
            (^($d1.vertex-count + $h.vertex-count))».Str.sort.List,
            "Expected vertexes for two (directed with undericted)";

    is-deeply
            $d1.disjoint-union([$d2, $g, $h]).vertex-list,
            (^($d1.vertex-count + $d2.vertex-count + $g.vertex-count + $h.vertex-count))».Str.sort.List,
            "Expected vertexes for array.";

    my @graphs = (^10).map({ Graph::Star.new(n => (8..16).pick, prefix => "$_-") });
    ok reduce({ $^a.disjoint-union($^b) }, |@graphs);

}, "Disjoint union";

## 5
subtest {
    is-deeply
            $g.union($h).vertex-list,
            $g.intersection($h).vertex-list,
            "The Graph union of two graphs has the same vertices as Graph intersection";
    is-deeply
            $g.union($h).vertex-list,
            $g.difference($h).vertex-list,
            "The Graph union of two graphs has the same vertices as Graph difference";
}, "Relationships";


done-testing;


