diff --git a/coverage.txt b/coverage.txt new file mode 100644 index 0000000..d0c829e --- /dev/null +++ b/coverage.txt @@ -0,0 +1,588 @@ +mode: atomic +github.com/dominikbraun/graph/collection.go:23.57,28.2 1 22 +github.com/dominikbraun/graph/collection.go:31.38,33.2 1 103 +github.com/dominikbraun/graph/collection.go:37.59,38.32 1 88 +github.com/dominikbraun/graph/collection.go:38.32,40.3 1 0 +github.com/dominikbraun/graph/collection.go:42.2,49.25 3 88 +github.com/dominikbraun/graph/collection.go:54.45,55.24 1 79 +github.com/dominikbraun/graph/collection.go:55.24,58.3 2 1 +github.com/dominikbraun/graph/collection.go:60.2,63.24 3 78 +github.com/dominikbraun/graph/collection.go:69.69,71.9 2 48 +github.com/dominikbraun/graph/collection.go:71.9,73.3 1 1 +github.com/dominikbraun/graph/collection.go:75.2,76.37 2 47 +github.com/dominikbraun/graph/collection.go:82.32,84.2 1 316 +github.com/dominikbraun/graph/collection.go:86.42,88.2 1 236 +github.com/dominikbraun/graph/collection.go:90.37,94.2 3 160 +github.com/dominikbraun/graph/collection.go:96.45,100.2 3 88 +github.com/dominikbraun/graph/collection.go:102.40,108.2 4 78 +github.com/dominikbraun/graph/collection.go:115.41,120.2 1 207 +github.com/dominikbraun/graph/collection.go:122.30,125.2 2 549 +github.com/dominikbraun/graph/collection.go:127.36,129.9 2 489 +github.com/dominikbraun/graph/collection.go:129.9,131.3 1 1 +github.com/dominikbraun/graph/collection.go:133.2,136.22 3 488 +github.com/dominikbraun/graph/collection.go:139.36,140.17 1 688 +github.com/dominikbraun/graph/collection.go:140.17,143.3 2 2 +github.com/dominikbraun/graph/collection.go:145.2,145.44 1 686 +github.com/dominikbraun/graph/collection.go:148.35,150.2 1 1843 +github.com/dominikbraun/graph/collection.go:152.39,153.31 1 380 +github.com/dominikbraun/graph/collection.go:153.31,155.3 1 2262 +github.com/dominikbraun/graph/collection.go:158.45,161.2 2 13 +github.com/dominikbraun/graph/collection.go:167.57,171.2 1 3 +github.com/dominikbraun/graph/collection.go:173.50,175.2 1 150 +github.com/dominikbraun/graph/collection.go:177.53,179.16 2 150 +github.com/dominikbraun/graph/collection.go:179.16,181.3 1 0 +github.com/dominikbraun/graph/collection.go:183.2,184.15 2 150 +github.com/dominikbraun/graph/collection.go:187.53,188.17 1 691 +github.com/dominikbraun/graph/collection.go:188.17,190.3 1 0 +github.com/dominikbraun/graph/collection.go:192.2,192.39 1 691 +github.com/dominikbraun/graph/collection.go:195.43,197.2 1 888 +github.com/dominikbraun/graph/dag.go:20.71,21.28 1 8 +github.com/dominikbraun/graph/dag.go:21.28,23.3 1 1 +github.com/dominikbraun/graph/dag.go:25.2,26.16 2 7 +github.com/dominikbraun/graph/dag.go:26.16,28.3 1 0 +github.com/dominikbraun/graph/dag.go:30.2,31.16 2 7 +github.com/dominikbraun/graph/dag.go:31.16,33.3 1 0 +github.com/dominikbraun/graph/dag.go:35.2,36.16 2 7 +github.com/dominikbraun/graph/dag.go:36.16,38.3 1 0 +github.com/dominikbraun/graph/dag.go:40.2,42.51 2 7 +github.com/dominikbraun/graph/dag.go:42.51,43.29 1 32 +github.com/dominikbraun/graph/dag.go:43.29,46.4 2 11 +github.com/dominikbraun/graph/dag.go:49.2,51.21 2 7 +github.com/dominikbraun/graph/dag.go:51.21,59.31 5 29 +github.com/dominikbraun/graph/dag.go:59.31,64.30 3 25 +github.com/dominikbraun/graph/dag.go:64.30,67.5 2 18 +github.com/dominikbraun/graph/dag.go:71.2,71.26 1 7 +github.com/dominikbraun/graph/dag.go:71.26,73.3 1 1 +github.com/dominikbraun/graph/dag.go:75.2,75.19 1 6 +github.com/dominikbraun/graph/dag.go:81.99,82.28 1 3 +github.com/dominikbraun/graph/dag.go:82.28,84.3 1 0 +github.com/dominikbraun/graph/dag.go:86.2,87.16 2 3 +github.com/dominikbraun/graph/dag.go:87.16,89.3 1 0 +github.com/dominikbraun/graph/dag.go:91.2,92.16 2 3 +github.com/dominikbraun/graph/dag.go:92.16,94.3 1 0 +github.com/dominikbraun/graph/dag.go:96.2,97.16 2 3 +github.com/dominikbraun/graph/dag.go:97.16,99.3 1 0 +github.com/dominikbraun/graph/dag.go:101.2,103.51 2 3 +github.com/dominikbraun/graph/dag.go:103.51,104.29 1 20 +github.com/dominikbraun/graph/dag.go:104.29,107.4 2 7 +github.com/dominikbraun/graph/dag.go:110.2,112.40 2 3 +github.com/dominikbraun/graph/dag.go:112.40,114.3 1 12 +github.com/dominikbraun/graph/dag.go:116.2,116.21 1 3 +github.com/dominikbraun/graph/dag.go:116.21,126.31 6 17 +github.com/dominikbraun/graph/dag.go:126.31,131.30 3 13 +github.com/dominikbraun/graph/dag.go:131.30,134.5 2 10 +github.com/dominikbraun/graph/dag.go:137.3,137.44 1 17 +github.com/dominikbraun/graph/dag.go:137.44,139.4 1 0 +github.com/dominikbraun/graph/dag.go:141.3,141.37 1 17 +github.com/dominikbraun/graph/dag.go:144.2,144.26 1 3 +github.com/dominikbraun/graph/dag.go:144.26,146.3 1 1 +github.com/dominikbraun/graph/dag.go:148.2,148.19 1 2 +github.com/dominikbraun/graph/dag.go:156.83,157.28 1 4 +github.com/dominikbraun/graph/dag.go:157.28,159.3 1 1 +github.com/dominikbraun/graph/dag.go:161.2,162.16 2 3 +github.com/dominikbraun/graph/dag.go:162.16,164.3 1 0 +github.com/dominikbraun/graph/dag.go:166.2,167.16 2 3 +github.com/dominikbraun/graph/dag.go:167.16,169.3 1 0 +github.com/dominikbraun/graph/dag.go:177.2,177.47 1 3 +github.com/dominikbraun/graph/dag.go:177.47,179.17 2 13 +github.com/dominikbraun/graph/dag.go:179.17,181.4 1 0 +github.com/dominikbraun/graph/dag.go:183.3,183.37 1 13 +github.com/dominikbraun/graph/dag.go:183.37,189.25 4 21 +github.com/dominikbraun/graph/dag.go:189.25,192.38 2 92 +github.com/dominikbraun/graph/dag.go:192.38,193.14 1 45 +github.com/dominikbraun/graph/dag.go:196.5,199.50 3 47 +github.com/dominikbraun/graph/dag.go:199.50,200.41 1 29 +github.com/dominikbraun/graph/dag.go:200.41,201.36 1 2 +github.com/dominikbraun/graph/dag.go:201.36,205.8 1 1 +github.com/dominikbraun/graph/dag.go:206.7,206.15 1 1 +github.com/dominikbraun/graph/dag.go:209.6,209.54 1 27 +github.com/dominikbraun/graph/dag.go:209.54,211.7 1 18 +github.com/dominikbraun/graph/dag.go:212.6,212.27 1 27 +github.com/dominikbraun/graph/dag.go:218.2,218.33 1 2 +github.com/dominikbraun/graph/directed.go:14.107,20.2 1 96 +github.com/dominikbraun/graph/directed.go:22.43,24.2 1 61 +github.com/dominikbraun/graph/directed.go:26.87,33.33 3 372 +github.com/dominikbraun/graph/directed.go:33.33,35.3 1 76 +github.com/dominikbraun/graph/directed.go:37.2,37.51 1 372 +github.com/dominikbraun/graph/directed.go:40.63,42.16 2 9 +github.com/dominikbraun/graph/directed.go:42.16,44.3 1 0 +github.com/dominikbraun/graph/directed.go:46.2,46.33 1 9 +github.com/dominikbraun/graph/directed.go:46.33,48.17 2 33 +github.com/dominikbraun/graph/directed.go:48.17,50.4 1 0 +github.com/dominikbraun/graph/directed.go:52.3,52.78 1 33 +github.com/dominikbraun/graph/directed.go:52.78,54.4 1 1 +github.com/dominikbraun/graph/directed.go:57.2,57.12 1 8 +github.com/dominikbraun/graph/directed.go:60.52,63.2 2 11 +github.com/dominikbraun/graph/directed.go:65.84,67.16 2 41 +github.com/dominikbraun/graph/directed.go:67.16,69.3 1 0 +github.com/dominikbraun/graph/directed.go:71.2,71.32 1 41 +github.com/dominikbraun/graph/directed.go:74.53,76.2 1 36 +github.com/dominikbraun/graph/directed.go:78.100,80.16 2 300 +github.com/dominikbraun/graph/directed.go:80.16,82.3 1 0 +github.com/dominikbraun/graph/directed.go:84.2,85.16 2 300 +github.com/dominikbraun/graph/directed.go:85.16,87.3 1 2 +github.com/dominikbraun/graph/directed.go:89.2,89.80 1 298 +github.com/dominikbraun/graph/directed.go:89.80,91.3 1 2 +github.com/dominikbraun/graph/directed.go:94.2,94.28 1 296 +github.com/dominikbraun/graph/directed.go:94.28,96.17 2 3 +github.com/dominikbraun/graph/directed.go:96.17,98.4 1 0 +github.com/dominikbraun/graph/directed.go:99.3,99.19 1 3 +github.com/dominikbraun/graph/directed.go:99.19,101.4 1 1 +github.com/dominikbraun/graph/directed.go:104.2,112.33 2 295 +github.com/dominikbraun/graph/directed.go:112.33,114.3 1 234 +github.com/dominikbraun/graph/directed.go:116.2,116.48 1 295 +github.com/dominikbraun/graph/directed.go:119.60,121.16 2 10 +github.com/dominikbraun/graph/directed.go:121.16,123.3 1 0 +github.com/dominikbraun/graph/directed.go:125.2,125.29 1 10 +github.com/dominikbraun/graph/directed.go:125.29,126.51 1 38 +github.com/dominikbraun/graph/directed.go:126.51,128.4 1 2 +github.com/dominikbraun/graph/directed.go:131.2,131.12 1 8 +github.com/dominikbraun/graph/directed.go:134.74,136.16 2 361 +github.com/dominikbraun/graph/directed.go:136.16,138.3 1 312 +github.com/dominikbraun/graph/directed.go:140.2,141.16 2 49 +github.com/dominikbraun/graph/directed.go:141.16,143.3 1 0 +github.com/dominikbraun/graph/directed.go:145.2,146.16 2 49 +github.com/dominikbraun/graph/directed.go:146.16,148.3 1 0 +github.com/dominikbraun/graph/directed.go:150.2,158.8 1 49 +github.com/dominikbraun/graph/directed.go:161.53,163.2 1 11 +github.com/dominikbraun/graph/directed.go:165.67,167.2 1 1 +github.com/dominikbraun/graph/directed.go:169.68,171.2 1 1 +github.com/dominikbraun/graph/directed.go:173.106,175.16 2 1 +github.com/dominikbraun/graph/directed.go:175.16,177.3 1 0 +github.com/dominikbraun/graph/directed.go:179.2,179.33 1 1 +github.com/dominikbraun/graph/directed.go:179.33,181.3 1 1 +github.com/dominikbraun/graph/directed.go:183.2,183.57 1 1 +github.com/dominikbraun/graph/directed.go:186.61,187.50 1 47 +github.com/dominikbraun/graph/directed.go:187.50,189.3 1 10 +github.com/dominikbraun/graph/directed.go:191.2,191.59 1 37 +github.com/dominikbraun/graph/directed.go:191.59,193.3 1 0 +github.com/dominikbraun/graph/directed.go:195.2,195.12 1 37 +github.com/dominikbraun/graph/directed.go:198.70,200.16 2 61 +github.com/dominikbraun/graph/directed.go:200.16,202.3 1 0 +github.com/dominikbraun/graph/directed.go:204.2,205.16 2 61 +github.com/dominikbraun/graph/directed.go:205.16,207.3 1 0 +github.com/dominikbraun/graph/directed.go:209.2,211.34 2 61 +github.com/dominikbraun/graph/directed.go:211.34,213.3 1 282 +github.com/dominikbraun/graph/directed.go:215.2,215.29 1 61 +github.com/dominikbraun/graph/directed.go:215.29,217.3 1 256 +github.com/dominikbraun/graph/directed.go:219.2,219.15 1 61 +github.com/dominikbraun/graph/directed.go:222.72,224.16 2 18 +github.com/dominikbraun/graph/directed.go:224.16,226.3 1 0 +github.com/dominikbraun/graph/directed.go:228.2,229.16 2 18 +github.com/dominikbraun/graph/directed.go:229.16,231.3 1 0 +github.com/dominikbraun/graph/directed.go:233.2,235.34 2 18 +github.com/dominikbraun/graph/directed.go:235.34,237.3 1 94 +github.com/dominikbraun/graph/directed.go:239.2,239.29 1 18 +github.com/dominikbraun/graph/directed.go:239.29,240.35 1 79 +github.com/dominikbraun/graph/directed.go:240.35,242.4 1 0 +github.com/dominikbraun/graph/directed.go:243.3,243.37 1 79 +github.com/dominikbraun/graph/directed.go:246.2,246.15 1 18 +github.com/dominikbraun/graph/directed.go:249.80,251.2 1 298 +github.com/dominikbraun/graph/directed.go:253.55,268.49 3 7 +github.com/dominikbraun/graph/directed.go:268.49,270.3 1 0 +github.com/dominikbraun/graph/directed.go:272.2,272.46 1 7 +github.com/dominikbraun/graph/directed.go:272.46,274.3 1 0 +github.com/dominikbraun/graph/directed.go:276.2,276.19 1 7 +github.com/dominikbraun/graph/directed.go:279.47,281.2 1 27 +github.com/dominikbraun/graph/directed.go:283.46,285.2 1 4 +github.com/dominikbraun/graph/directed.go:287.59,294.2 5 76 +github.com/dominikbraun/graph/directed.go:296.71,300.9 1 3 +github.com/dominikbraun/graph/directed.go:300.9,302.3 1 3 +github.com/dominikbraun/graph/directed.go:305.2,305.53 1 0 +github.com/dominikbraun/graph/directed.go:313.84,314.44 1 119 +github.com/dominikbraun/graph/directed.go:314.44,315.48 1 115 +github.com/dominikbraun/graph/directed.go:315.48,317.4 1 40 +github.com/dominikbraun/graph/directed.go:318.3,319.32 2 115 +github.com/dominikbraun/graph/directed.go:322.2,322.49 1 119 +github.com/dominikbraun/graph/graph.go:263.86,265.2 1 129 +github.com/dominikbraun/graph/graph.go:269.114,272.33 2 129 +github.com/dominikbraun/graph/graph.go:272.33,274.3 1 76 +github.com/dominikbraun/graph/graph.go:276.2,276.18 1 129 +github.com/dominikbraun/graph/graph.go:276.18,278.3 1 70 +github.com/dominikbraun/graph/graph.go:280.2,280.39 1 59 +github.com/dominikbraun/graph/graph.go:291.62,292.32 1 6 +github.com/dominikbraun/graph/graph.go:292.32,298.3 5 6 +github.com/dominikbraun/graph/graph.go:300.2,302.27 2 6 +github.com/dominikbraun/graph/graph.go:302.27,304.3 1 1 +github.com/dominikbraun/graph/graph.go:304.8,306.3 1 5 +github.com/dominikbraun/graph/graph.go:308.2,308.30 1 6 +github.com/dominikbraun/graph/graph.go:313.34,315.2 1 446 +github.com/dominikbraun/graph/graph.go:319.25,321.2 1 759 +github.com/dominikbraun/graph/graph.go:326.51,327.33 1 240 +github.com/dominikbraun/graph/graph.go:327.33,329.3 1 234 +github.com/dominikbraun/graph/graph.go:335.61,336.33 1 3 +github.com/dominikbraun/graph/graph.go:336.33,338.3 1 3 +github.com/dominikbraun/graph/graph.go:344.73,345.33 1 1 +github.com/dominikbraun/graph/graph.go:345.33,347.3 1 1 +github.com/dominikbraun/graph/graph.go:353.47,354.33 1 32 +github.com/dominikbraun/graph/graph.go:354.33,356.3 1 26 +github.com/dominikbraun/graph/graph.go:374.55,375.35 1 22 +github.com/dominikbraun/graph/graph.go:375.35,377.3 1 22 +github.com/dominikbraun/graph/graph.go:383.65,384.35 1 23 +github.com/dominikbraun/graph/graph.go:384.35,386.3 1 23 +github.com/dominikbraun/graph/graph.go:391.77,392.35 1 1 +github.com/dominikbraun/graph/graph.go:392.35,394.3 1 1 +github.com/dominikbraun/graph/paths.go:16.87,17.44 1 9 +github.com/dominikbraun/graph/paths.go:17.44,19.3 1 0 +github.com/dominikbraun/graph/paths.go:21.2,21.44 1 9 +github.com/dominikbraun/graph/paths.go:21.44,23.3 1 0 +github.com/dominikbraun/graph/paths.go:25.2,25.22 1 9 +github.com/dominikbraun/graph/paths.go:25.22,27.3 1 0 +github.com/dominikbraun/graph/paths.go:29.2,30.16 2 9 +github.com/dominikbraun/graph/paths.go:30.16,32.3 1 0 +github.com/dominikbraun/graph/paths.go:34.2,39.23 4 9 +github.com/dominikbraun/graph/paths.go:39.23,42.41 2 31 +github.com/dominikbraun/graph/paths.go:42.41,45.29 1 24 +github.com/dominikbraun/graph/paths.go:45.29,47.5 1 4 +github.com/dominikbraun/graph/paths.go:49.4,51.55 2 20 +github.com/dominikbraun/graph/paths.go:51.55,53.5 1 26 +github.com/dominikbraun/graph/paths.go:57.2,57.19 1 5 +github.com/dominikbraun/graph/paths.go:69.86,78.16 7 12 +github.com/dominikbraun/graph/paths.go:78.16,80.3 1 0 +github.com/dominikbraun/graph/paths.go:82.2,82.33 1 12 +github.com/dominikbraun/graph/paths.go:82.33,83.21 1 59 +github.com/dominikbraun/graph/paths.go:83.21,86.4 2 47 +github.com/dominikbraun/graph/paths.go:88.3,88.34 1 59 +github.com/dominikbraun/graph/paths.go:94.2,96.22 2 12 +github.com/dominikbraun/graph/paths.go:96.22,100.53 3 59 +github.com/dominikbraun/graph/paths.go:100.53,106.30 2 88 +github.com/dominikbraun/graph/paths.go:106.30,108.5 1 23 +github.com/dominikbraun/graph/paths.go:110.4,112.57 2 88 +github.com/dominikbraun/graph/paths.go:112.57,116.5 3 45 +github.com/dominikbraun/graph/paths.go:120.2,123.24 3 12 +github.com/dominikbraun/graph/paths.go:123.24,128.46 1 22 +github.com/dominikbraun/graph/paths.go:128.46,130.4 1 3 +github.com/dominikbraun/graph/paths.go:131.3,132.39 2 19 +github.com/dominikbraun/graph/paths.go:135.2,135.18 1 9 +github.com/dominikbraun/graph/paths.go:153.85,154.28 1 2 +github.com/dominikbraun/graph/paths.go:154.28,156.3 1 1 +github.com/dominikbraun/graph/paths.go:158.2,159.16 2 1 +github.com/dominikbraun/graph/paths.go:159.16,161.3 1 0 +github.com/dominikbraun/graph/paths.go:163.2,172.39 2 1 +github.com/dominikbraun/graph/paths.go:172.39,173.40 1 8 +github.com/dominikbraun/graph/paths.go:173.40,175.4 1 3 +github.com/dominikbraun/graph/paths.go:178.2,178.30 1 1 +github.com/dominikbraun/graph/paths.go:181.62,189.56 6 8 +github.com/dominikbraun/graph/paths.go:189.56,190.45 1 14 +github.com/dominikbraun/graph/paths.go:190.45,198.4 3 5 +github.com/dominikbraun/graph/paths.go:198.9,203.39 1 9 +github.com/dominikbraun/graph/paths.go:203.39,209.5 2 4 +github.com/dominikbraun/graph/paths.go:216.2,216.58 1 8 +github.com/dominikbraun/graph/paths.go:216.58,220.26 3 3 +github.com/dominikbraun/graph/paths.go:220.26,224.4 2 8 +github.com/dominikbraun/graph/paths.go:226.3,226.57 1 3 +github.com/dominikbraun/graph/paths.go:236.87,238.16 2 3 +github.com/dominikbraun/graph/paths.go:238.16,240.3 1 0 +github.com/dominikbraun/graph/paths.go:244.2,247.29 3 3 +github.com/dominikbraun/graph/paths.go:247.29,248.49 1 197 +github.com/dominikbraun/graph/paths.go:248.49,250.4 1 0 +github.com/dominikbraun/graph/paths.go:251.3,251.13 1 197 +github.com/dominikbraun/graph/paths.go:254.2,254.32 1 3 +github.com/dominikbraun/graph/paths.go:254.32,258.40 3 150 +github.com/dominikbraun/graph/paths.go:258.40,260.32 2 354 +github.com/dominikbraun/graph/paths.go:260.32,261.15 1 2105 +github.com/dominikbraun/graph/paths.go:261.15,263.6 1 207 +github.com/dominikbraun/graph/paths.go:265.4,265.16 1 354 +github.com/dominikbraun/graph/paths.go:265.16,266.13 1 207 +github.com/dominikbraun/graph/paths.go:268.4,268.23 1 147 +github.com/dominikbraun/graph/paths.go:270.3,270.30 1 150 +github.com/dominikbraun/graph/paths.go:273.2,273.29 1 3 +github.com/dominikbraun/graph/paths.go:273.29,274.37 1 47 +github.com/dominikbraun/graph/paths.go:274.37,276.4 1 0 +github.com/dominikbraun/graph/paths.go:278.3,280.27 2 47 +github.com/dominikbraun/graph/paths.go:280.27,284.4 3 147 +github.com/dominikbraun/graph/paths.go:286.3,286.13 1 47 +github.com/dominikbraun/graph/paths.go:289.2,289.30 1 3 +github.com/dominikbraun/graph/paths.go:289.30,290.37 1 150 +github.com/dominikbraun/graph/paths.go:290.37,292.4 1 0 +github.com/dominikbraun/graph/paths.go:294.3,294.44 1 150 +github.com/dominikbraun/graph/paths.go:294.44,296.4 1 0 +github.com/dominikbraun/graph/paths.go:298.3,301.13 3 150 +github.com/dominikbraun/graph/paths.go:304.2,308.27 3 3 +github.com/dominikbraun/graph/paths.go:308.27,312.21 3 197 +github.com/dominikbraun/graph/paths.go:312.21,313.16 1 150 +github.com/dominikbraun/graph/paths.go:313.16,315.33 2 25 +github.com/dominikbraun/graph/paths.go:315.33,317.6 1 151 +github.com/dominikbraun/graph/paths.go:318.5,318.38 1 25 +github.com/dominikbraun/graph/paths.go:321.4,322.18 2 150 +github.com/dominikbraun/graph/paths.go:322.18,324.5 1 0 +github.com/dominikbraun/graph/paths.go:325.9,326.38 1 47 +github.com/dominikbraun/graph/paths.go:326.38,328.5 1 0 +github.com/dominikbraun/graph/paths.go:332.2,332.22 1 3 +github.com/dominikbraun/graph/sets.go:12.72,14.16 2 2 +github.com/dominikbraun/graph/sets.go:14.16,16.3 1 0 +github.com/dominikbraun/graph/sets.go:18.2,19.16 2 2 +github.com/dominikbraun/graph/sets.go:19.16,21.3 1 0 +github.com/dominikbraun/graph/sets.go:23.2,25.40 2 2 +github.com/dominikbraun/graph/sets.go:25.40,27.17 2 5 +github.com/dominikbraun/graph/sets.go:27.17,29.4 1 0 +github.com/dominikbraun/graph/sets.go:31.3,32.17 2 5 +github.com/dominikbraun/graph/sets.go:32.17,34.4 1 0 +github.com/dominikbraun/graph/sets.go:37.2,37.43 1 2 +github.com/dominikbraun/graph/sets.go:37.43,38.36 1 5 +github.com/dominikbraun/graph/sets.go:38.36,39.56 1 3 +github.com/dominikbraun/graph/sets.go:39.56,40.70 1 0 +github.com/dominikbraun/graph/sets.go:40.70,43.14 1 0 +github.com/dominikbraun/graph/sets.go:47.4,48.18 2 3 +github.com/dominikbraun/graph/sets.go:48.18,50.5 1 0 +github.com/dominikbraun/graph/sets.go:52.4,52.45 1 3 +github.com/dominikbraun/graph/sets.go:52.45,54.5 1 3 +github.com/dominikbraun/graph/sets.go:55.4,55.53 1 3 +github.com/dominikbraun/graph/sets.go:59.2,59.19 1 2 +github.com/dominikbraun/graph/sets.go:71.62,76.34 2 6 +github.com/dominikbraun/graph/sets.go:76.34,78.3 1 4 +github.com/dominikbraun/graph/sets.go:80.2,80.10 1 6 +github.com/dominikbraun/graph/sets.go:83.38,85.2 1 17 +github.com/dominikbraun/graph/sets.go:87.50,91.20 3 11 +github.com/dominikbraun/graph/sets.go:91.20,93.3 1 0 +github.com/dominikbraun/graph/sets.go:95.2,95.26 1 11 +github.com/dominikbraun/graph/sets.go:98.41,101.30 2 90 +github.com/dominikbraun/graph/sets.go:101.30,103.3 1 37 +github.com/dominikbraun/graph/sets.go:106.2,108.33 2 90 +github.com/dominikbraun/graph/sets.go:108.33,112.3 3 3 +github.com/dominikbraun/graph/sets.go:114.2,114.13 1 90 +github.com/dominikbraun/graph/sets.go:117.76,118.35 1 89 +github.com/dominikbraun/graph/sets.go:118.35,119.39 1 89 +github.com/dominikbraun/graph/sets.go:119.39,121.4 1 30 +github.com/dominikbraun/graph/sets.go:122.3,122.27 1 89 +github.com/dominikbraun/graph/store.go:89.56,96.2 1 196 +github.com/dominikbraun/graph/store.go:98.75,102.32 3 700 +github.com/dominikbraun/graph/store.go:102.32,104.3 1 4 +github.com/dominikbraun/graph/store.go:106.2,109.12 3 696 +github.com/dominikbraun/graph/store.go:112.57,117.28 4 121 +github.com/dominikbraun/graph/store.go:117.28,119.3 1 577 +github.com/dominikbraun/graph/store.go:121.2,121.20 1 121 +github.com/dominikbraun/graph/store.go:124.56,129.2 3 31 +github.com/dominikbraun/graph/store.go:131.70,136.9 4 1317 +github.com/dominikbraun/graph/store.go:136.9,138.3 1 12 +github.com/dominikbraun/graph/store.go:140.2,142.18 2 1305 +github.com/dominikbraun/graph/store.go:145.53,149.33 3 42 +github.com/dominikbraun/graph/store.go:149.33,151.3 1 2 +github.com/dominikbraun/graph/store.go:153.2,153.35 1 40 +github.com/dominikbraun/graph/store.go:153.35,154.21 1 19 +github.com/dominikbraun/graph/store.go:154.21,156.4 1 5 +github.com/dominikbraun/graph/store.go:157.3,157.23 1 14 +github.com/dominikbraun/graph/store.go:160.2,160.36 1 35 +github.com/dominikbraun/graph/store.go:160.36,161.21 1 23 +github.com/dominikbraun/graph/store.go:161.21,163.4 1 2 +github.com/dominikbraun/graph/store.go:164.3,164.24 1 21 +github.com/dominikbraun/graph/store.go:167.2,170.12 3 33 +github.com/dominikbraun/graph/store.go:173.83,177.42 3 788 +github.com/dominikbraun/graph/store.go:177.42,179.3 1 504 +github.com/dominikbraun/graph/store.go:181.2,183.41 2 788 +github.com/dominikbraun/graph/store.go:183.41,185.3 1 514 +github.com/dominikbraun/graph/store.go:187.2,191.12 3 788 +github.com/dominikbraun/graph/store.go:194.86,199.9 4 3 +github.com/dominikbraun/graph/store.go:199.9,201.3 1 0 +github.com/dominikbraun/graph/store.go:203.2,204.9 2 3 +github.com/dominikbraun/graph/store.go:204.9,206.3 1 0 +github.com/dominikbraun/graph/store.go:208.2,211.12 3 3 +github.com/dominikbraun/graph/store.go:214.72,224.2 6 45 +github.com/dominikbraun/graph/store.go:226.77,231.9 4 867 +github.com/dominikbraun/graph/store.go:231.9,233.3 1 503 +github.com/dominikbraun/graph/store.go:235.2,236.9 2 364 +github.com/dominikbraun/graph/store.go:236.9,238.3 1 301 +github.com/dominikbraun/graph/store.go:240.2,240.18 1 63 +github.com/dominikbraun/graph/store.go:243.54,248.2 3 8 +github.com/dominikbraun/graph/store.go:250.60,255.35 4 138 +github.com/dominikbraun/graph/store.go:255.35,256.30 1 480 +github.com/dominikbraun/graph/store.go:256.30,258.4 1 752 +github.com/dominikbraun/graph/store.go:260.2,260.17 1 138 +github.com/dominikbraun/graph/store.go:263.75,269.32 5 2 +github.com/dominikbraun/graph/store.go:269.32,271.3 1 3 +github.com/dominikbraun/graph/store.go:272.2,272.17 1 2 +github.com/dominikbraun/graph/store.go:275.74,281.31 5 2 +github.com/dominikbraun/graph/store.go:281.31,283.3 1 3 +github.com/dominikbraun/graph/store.go:284.2,284.17 1 2 +github.com/dominikbraun/graph/store.go:292.74,296.38 3 3 +github.com/dominikbraun/graph/store.go:296.38,298.3 1 0 +github.com/dominikbraun/graph/store.go:300.2,300.38 1 3 +github.com/dominikbraun/graph/store.go:300.38,302.3 1 0 +github.com/dominikbraun/graph/store.go:304.2,304.22 1 3 +github.com/dominikbraun/graph/store.go:304.22,306.3 1 0 +github.com/dominikbraun/graph/store.go:308.2,313.23 4 3 +github.com/dominikbraun/graph/store.go:313.23,316.41 2 6 +github.com/dominikbraun/graph/store.go:316.41,319.29 1 6 +github.com/dominikbraun/graph/store.go:319.29,321.5 1 1 +github.com/dominikbraun/graph/store.go:323.4,325.50 2 5 +github.com/dominikbraun/graph/store.go:325.50,327.5 1 3 +github.com/dominikbraun/graph/store.go:331.2,331.19 1 2 +github.com/dominikbraun/graph/traits.go:20.31,21.25 1 70 +github.com/dominikbraun/graph/traits.go:21.25,23.3 1 70 +github.com/dominikbraun/graph/traits.go:28.30,29.25 1 3 +github.com/dominikbraun/graph/traits.go:29.25,31.3 1 3 +github.com/dominikbraun/graph/traits.go:35.31,36.25 1 2 +github.com/dominikbraun/graph/traits.go:36.25,38.3 1 2 +github.com/dominikbraun/graph/traits.go:42.29,43.25 1 2 +github.com/dominikbraun/graph/traits.go:43.25,45.3 1 2 +github.com/dominikbraun/graph/traits.go:49.27,50.25 1 1 +github.com/dominikbraun/graph/traits.go:50.25,53.3 2 1 +github.com/dominikbraun/graph/traits.go:58.36,59.25 1 1 +github.com/dominikbraun/graph/traits.go:59.25,62.3 2 1 +github.com/dominikbraun/graph/traversal.go:35.81,37.16 2 10 +github.com/dominikbraun/graph/traversal.go:37.16,39.3 1 0 +github.com/dominikbraun/graph/traversal.go:41.2,41.39 1 10 +github.com/dominikbraun/graph/traversal.go:41.39,43.3 1 0 +github.com/dominikbraun/graph/traversal.go:45.2,50.23 4 10 +github.com/dominikbraun/graph/traversal.go:50.23,53.41 2 53 +github.com/dominikbraun/graph/traversal.go:53.41,55.40 1 37 +github.com/dominikbraun/graph/traversal.go:55.40,56.10 1 4 +github.com/dominikbraun/graph/traversal.go:58.4,60.53 2 33 +github.com/dominikbraun/graph/traversal.go:60.53,62.5 1 55 +github.com/dominikbraun/graph/traversal.go:66.2,66.12 1 10 +github.com/dominikbraun/graph/traversal.go:99.81,100.44 1 6 +github.com/dominikbraun/graph/traversal.go:100.44,102.3 1 19 +github.com/dominikbraun/graph/traversal.go:103.2,103.44 1 6 +github.com/dominikbraun/graph/traversal.go:117.95,119.16 2 9 +github.com/dominikbraun/graph/traversal.go:119.16,121.3 1 0 +github.com/dominikbraun/graph/traversal.go:123.2,123.39 1 9 +github.com/dominikbraun/graph/traversal.go:123.39,125.3 1 0 +github.com/dominikbraun/graph/traversal.go:127.2,134.21 6 9 +github.com/dominikbraun/graph/traversal.go:134.21,141.46 4 29 +github.com/dominikbraun/graph/traversal.go:141.46,142.9 1 3 +github.com/dominikbraun/graph/traversal.go:145.3,145.52 1 26 +github.com/dominikbraun/graph/traversal.go:145.52,146.40 1 29 +github.com/dominikbraun/graph/traversal.go:146.40,149.5 2 24 +github.com/dominikbraun/graph/traversal.go:154.2,154.12 1 9 +github.com/dominikbraun/graph/trees.go:13.83,15.2 1 3 +github.com/dominikbraun/graph/trees.go:21.83,23.2 1 3 +github.com/dominikbraun/graph/trees.go:25.90,26.27 1 6 +github.com/dominikbraun/graph/trees.go:26.27,28.3 1 2 +github.com/dominikbraun/graph/trees.go:30.2,31.16 2 4 +github.com/dominikbraun/graph/trees.go:31.16,33.3 1 0 +github.com/dominikbraun/graph/trees.go:35.2,40.43 4 4 +github.com/dominikbraun/graph/trees.go:40.43,42.17 2 16 +github.com/dominikbraun/graph/trees.go:42.17,44.4 1 0 +github.com/dominikbraun/graph/trees.go:46.3,47.17 2 16 +github.com/dominikbraun/graph/trees.go:47.17,49.4 1 0 +github.com/dominikbraun/graph/trees.go:51.3,53.36 2 16 +github.com/dominikbraun/graph/trees.go:53.36,55.4 1 32 +github.com/dominikbraun/graph/trees.go:58.2,58.13 1 4 +github.com/dominikbraun/graph/trees.go:58.13,59.41 1 2 +github.com/dominikbraun/graph/trees.go:59.41,61.4 1 40 +github.com/dominikbraun/graph/trees.go:62.8,63.41 1 2 +github.com/dominikbraun/graph/trees.go:63.41,65.4 1 35 +github.com/dominikbraun/graph/trees.go:68.2,68.29 1 4 +github.com/dominikbraun/graph/trees.go:68.29,72.31 3 32 +github.com/dominikbraun/graph/trees.go:72.31,75.53 2 10 +github.com/dominikbraun/graph/trees.go:75.53,77.5 1 0 +github.com/dominikbraun/graph/trees.go:81.2,81.17 1 4 +github.com/dominikbraun/graph/undirected.go:14.111,20.2 1 88 +github.com/dominikbraun/graph/undirected.go:22.45,24.2 1 96 +github.com/dominikbraun/graph/undirected.go:26.89,34.33 3 319 +github.com/dominikbraun/graph/undirected.go:34.33,36.3 1 57 +github.com/dominikbraun/graph/undirected.go:38.2,38.45 1 319 +github.com/dominikbraun/graph/undirected.go:41.54,44.2 2 17 +github.com/dominikbraun/graph/undirected.go:46.86,48.16 2 32 +github.com/dominikbraun/graph/undirected.go:48.16,50.3 1 0 +github.com/dominikbraun/graph/undirected.go:52.2,52.26 1 32 +github.com/dominikbraun/graph/undirected.go:55.55,57.2 1 3 +github.com/dominikbraun/graph/undirected.go:59.102,60.57 1 244 +github.com/dominikbraun/graph/undirected.go:60.57,62.3 1 0 +github.com/dominikbraun/graph/undirected.go:64.2,64.57 1 244 +github.com/dominikbraun/graph/undirected.go:64.57,66.3 1 2 +github.com/dominikbraun/graph/undirected.go:69.2,69.80 1 242 +github.com/dominikbraun/graph/undirected.go:69.80,71.3 1 2 +github.com/dominikbraun/graph/undirected.go:74.2,74.28 1 240 +github.com/dominikbraun/graph/undirected.go:74.28,76.17 2 3 +github.com/dominikbraun/graph/undirected.go:76.17,78.4 1 0 +github.com/dominikbraun/graph/undirected.go:79.3,79.19 1 3 +github.com/dominikbraun/graph/undirected.go:79.19,81.4 1 1 +github.com/dominikbraun/graph/undirected.go:84.2,92.33 2 239 +github.com/dominikbraun/graph/undirected.go:92.33,94.3 1 140 +github.com/dominikbraun/graph/undirected.go:96.2,96.64 1 239 +github.com/dominikbraun/graph/undirected.go:96.64,98.3 1 0 +github.com/dominikbraun/graph/undirected.go:100.2,100.12 1 239 +github.com/dominikbraun/graph/undirected.go:103.62,105.16 2 5 +github.com/dominikbraun/graph/undirected.go:105.16,107.3 1 0 +github.com/dominikbraun/graph/undirected.go:109.2,109.29 1 5 +github.com/dominikbraun/graph/undirected.go:109.29,110.51 1 12 +github.com/dominikbraun/graph/undirected.go:110.51,112.4 1 2 +github.com/dominikbraun/graph/undirected.go:115.2,115.12 1 3 +github.com/dominikbraun/graph/undirected.go:118.65,120.16 2 4 +github.com/dominikbraun/graph/undirected.go:120.16,122.3 1 0 +github.com/dominikbraun/graph/undirected.go:124.2,124.33 1 4 +github.com/dominikbraun/graph/undirected.go:124.33,126.17 2 13 +github.com/dominikbraun/graph/undirected.go:126.17,128.4 1 0 +github.com/dominikbraun/graph/undirected.go:130.3,130.78 1 13 +github.com/dominikbraun/graph/undirected.go:130.78,132.4 1 1 +github.com/dominikbraun/graph/undirected.go:135.2,135.12 1 3 +github.com/dominikbraun/graph/undirected.go:138.76,143.37 2 258 +github.com/dominikbraun/graph/undirected.go:143.37,145.3 1 246 +github.com/dominikbraun/graph/undirected.go:147.2,147.16 1 258 +github.com/dominikbraun/graph/undirected.go:147.16,149.3 1 246 +github.com/dominikbraun/graph/undirected.go:151.2,152.16 2 12 +github.com/dominikbraun/graph/undirected.go:152.16,154.3 1 0 +github.com/dominikbraun/graph/undirected.go:156.2,157.16 2 12 +github.com/dominikbraun/graph/undirected.go:157.16,159.3 1 0 +github.com/dominikbraun/graph/undirected.go:161.2,169.8 1 12 +github.com/dominikbraun/graph/undirected.go:176.55,178.16 2 6 +github.com/dominikbraun/graph/undirected.go:178.16,180.3 1 0 +github.com/dominikbraun/graph/undirected.go:193.2,197.41 3 6 +github.com/dominikbraun/graph/undirected.go:197.41,202.39 2 30 +github.com/dominikbraun/graph/undirected.go:202.39,203.12 1 15 +github.com/dominikbraun/graph/undirected.go:206.3,213.32 3 15 +github.com/dominikbraun/graph/undirected.go:216.2,216.19 1 6 +github.com/dominikbraun/graph/undirected.go:219.69,221.2 1 1 +github.com/dominikbraun/graph/undirected.go:223.70,225.2 1 1 +github.com/dominikbraun/graph/undirected.go:227.108,229.16 2 1 +github.com/dominikbraun/graph/undirected.go:229.16,231.3 1 0 +github.com/dominikbraun/graph/undirected.go:233.2,233.33 1 1 +github.com/dominikbraun/graph/undirected.go:233.33,235.3 1 1 +github.com/dominikbraun/graph/undirected.go:237.2,237.73 1 1 +github.com/dominikbraun/graph/undirected.go:237.73,239.3 1 0 +github.com/dominikbraun/graph/undirected.go:241.2,245.57 4 1 +github.com/dominikbraun/graph/undirected.go:248.63,249.50 1 4 +github.com/dominikbraun/graph/undirected.go:249.50,251.3 1 1 +github.com/dominikbraun/graph/undirected.go:253.2,253.59 1 3 +github.com/dominikbraun/graph/undirected.go:253.59,255.3 1 0 +github.com/dominikbraun/graph/undirected.go:257.2,257.59 1 3 +github.com/dominikbraun/graph/undirected.go:257.59,259.3 1 0 +github.com/dominikbraun/graph/undirected.go:261.2,261.12 1 3 +github.com/dominikbraun/graph/undirected.go:264.72,266.16 2 42 +github.com/dominikbraun/graph/undirected.go:266.16,268.3 1 0 +github.com/dominikbraun/graph/undirected.go:270.2,271.16 2 42 +github.com/dominikbraun/graph/undirected.go:271.16,273.3 1 0 +github.com/dominikbraun/graph/undirected.go:275.2,277.34 2 42 +github.com/dominikbraun/graph/undirected.go:277.34,279.3 1 201 +github.com/dominikbraun/graph/undirected.go:281.2,281.29 1 42 +github.com/dominikbraun/graph/undirected.go:281.29,283.3 1 346 +github.com/dominikbraun/graph/undirected.go:285.2,285.15 1 42 +github.com/dominikbraun/graph/undirected.go:288.74,290.2 1 8 +github.com/dominikbraun/graph/undirected.go:292.57,306.49 3 2 +github.com/dominikbraun/graph/undirected.go:306.49,308.3 1 0 +github.com/dominikbraun/graph/undirected.go:310.2,310.46 1 2 +github.com/dominikbraun/graph/undirected.go:310.46,312.3 1 0 +github.com/dominikbraun/graph/undirected.go:314.2,314.19 1 2 +github.com/dominikbraun/graph/undirected.go:317.49,319.2 1 4 +github.com/dominikbraun/graph/undirected.go:321.48,327.2 2 4 +github.com/dominikbraun/graph/undirected.go:329.61,335.62 5 37 +github.com/dominikbraun/graph/undirected.go:335.62,337.3 1 35 +github.com/dominikbraun/graph/undirected.go:339.2,339.26 1 2 +github.com/dominikbraun/graph/undirected.go:339.26,341.3 1 2 +github.com/dominikbraun/graph/undirected.go:343.2,343.14 1 0 +github.com/dominikbraun/graph/undirected.go:346.82,348.16 2 242 +github.com/dominikbraun/graph/undirected.go:348.16,350.3 1 0 +github.com/dominikbraun/graph/undirected.go:352.2,363.16 3 242 +github.com/dominikbraun/graph/undirected.go:363.16,365.3 1 0 +github.com/dominikbraun/graph/undirected.go:367.2,367.12 1 242 +github.com/dominikbraun/graph/draw/draw.go:73.102,75.16 2 0 +github.com/dominikbraun/graph/draw/draw.go:75.16,77.3 1 0 +github.com/dominikbraun/graph/draw/draw.go:79.2,79.27 1 0 +github.com/dominikbraun/graph/draw/draw.go:83.59,84.30 1 1 +github.com/dominikbraun/graph/draw/draw.go:84.30,86.3 1 1 +github.com/dominikbraun/graph/draw/draw.go:89.112,97.33 2 4 +github.com/dominikbraun/graph/draw/draw.go:97.33,99.3 1 0 +github.com/dominikbraun/graph/draw/draw.go:101.2,101.27 1 4 +github.com/dominikbraun/graph/draw/draw.go:101.27,104.3 2 4 +github.com/dominikbraun/graph/draw/draw.go:106.2,107.16 2 4 +github.com/dominikbraun/graph/draw/draw.go:107.16,109.3 1 0 +github.com/dominikbraun/graph/draw/draw.go:111.2,111.48 1 4 +github.com/dominikbraun/graph/draw/draw.go:111.48,113.17 2 10 +github.com/dominikbraun/graph/draw/draw.go:113.17,115.4 1 0 +github.com/dominikbraun/graph/draw/draw.go:117.3,124.44 3 10 +github.com/dominikbraun/graph/draw/draw.go:124.44,132.4 2 6 +github.com/dominikbraun/graph/draw/draw.go:135.2,135.18 1 4 +github.com/dominikbraun/graph/draw/draw.go:138.50,140.16 2 5 +github.com/dominikbraun/graph/draw/draw.go:140.16,142.3 1 0 +github.com/dominikbraun/graph/draw/draw.go:144.2,144.26 1 5 diff --git a/directed.go b/directed.go index a044194..911d3ec 100644 --- a/directed.go +++ b/directed.go @@ -162,6 +162,14 @@ func (d *directed[K, T]) Edges() ([]Edge[K], error) { return d.store.ListEdges() } +func (d *directed[K, T]) InEdges(targetHash K) ([]Edge[K], error) { + return d.store.ListInEdges(targetHash) +} + +func (d *directed[K, T]) OutEdges(sourceHash K) ([]Edge[K], error) { + return d.store.ListOutEdges(sourceHash) +} + func (d *directed[K, T]) UpdateEdge(source, target K, options ...func(properties *EdgeProperties)) error { existingEdge, err := d.store.Edge(source, target) if err != nil { diff --git a/directed_test.go b/directed_test.go index 34a9c8d..3e70d38 100644 --- a/directed_test.go +++ b/directed_test.go @@ -783,6 +783,178 @@ func TestDirected_Edges(t *testing.T) { } } +func TestDirected_OutEdges(t *testing.T) { + tests := map[string]struct { + vertices []int + edges []Edge[int] + expectedEdges []Edge[int] + }{ + "graph with 3 edges": { + vertices: []int{1, 2, 3}, + edges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 2, + Target: 3, + Properties: EdgeProperties{ + Weight: 20, + Attributes: map[string]string{ + "color": "green", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + expectedEdges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + g := New(IntHash, Directed()) + + for _, vertex := range test.vertices { + _ = g.AddVertex(vertex) + } + + for _, edge := range test.edges { + _ = g.AddEdge(copyEdge(edge)) + } + + edges, err := g.OutEdges(test.vertices[0]) + if err != nil { + t.Fatalf("unexpected error: %v", err.Error()) + } + + for _, expectedEdge := range test.expectedEdges { + for _, actualEdge := range edges { + if actualEdge.Source != expectedEdge.Source || actualEdge.Target != expectedEdge.Target { + continue + } + if !edgesAreEqual(expectedEdge, actualEdge, true) { + t.Errorf("%s: expected edge %v, got %v", name, expectedEdge, actualEdge) + } + } + } + }) + } +} + +func TestDirected_InEdges(t *testing.T) { + tests := map[string]struct { + vertices []int + edges []Edge[int] + expectedEdges []Edge[int] + }{ + "graph with 3 edges": { + vertices: []int{1, 2, 3}, + edges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 2, + Target: 3, + Properties: EdgeProperties{ + Weight: 20, + Attributes: map[string]string{ + "color": "green", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + expectedEdges: []Edge[int]{ + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + g := New(IntHash, Directed()) + + for _, vertex := range test.vertices { + _ = g.AddVertex(vertex) + } + + for _, edge := range test.edges { + _ = g.AddEdge(copyEdge(edge)) + } + + edges, err := g.InEdges(test.vertices[0]) + if err != nil { + t.Fatalf("unexpected error: %v", err.Error()) + } + + for _, expectedEdge := range test.expectedEdges { + for _, actualEdge := range edges { + if actualEdge.Source != expectedEdge.Source || actualEdge.Target != expectedEdge.Target { + continue + } + if !edgesAreEqual(expectedEdge, actualEdge, true) { + t.Errorf("%s: expected edge %v, got %v", name, expectedEdge, actualEdge) + } + } + } + }) + } +} + func TestDirected_UpdateEdge(t *testing.T) { tests := map[string]struct { vertices []int diff --git a/graph.go b/graph.go index 9376eb5..7679266 100644 --- a/graph.go +++ b/graph.go @@ -130,6 +130,14 @@ type Graph[K comparable, T any] interface { // Edge[K] and hence will contain the vertex hashes, not the vertex values. Edges() ([]Edge[K], error) + // InEdges returns a slice of all edges in the graph with a specific target vertex. + // These edges are of type Edge[K] and hence will contain the vertex hashes, not the vertex values. + InEdges(targetHash K) ([]Edge[K], error) + + // OutEdges returns a slice of all edges in the graph with a specific source vertex. + // These edges are of type Edge[K] and hence will contain the vertex hashes, not the vertex values. + OutEdges(sourceHash K) ([]Edge[K], error) + // UpdateEdge updates the edge joining the two given vertices with the data // provided in the given functional options. Valid functional options are: // - EdgeWeight: Sets a new weight for the edge properties. diff --git a/store.go b/store.go index e41a750..dc521b3 100644 --- a/store.go +++ b/store.go @@ -63,6 +63,12 @@ type Store[K comparable, T any] interface { // ListEdges should return all edges in the graph in a slice. ListEdges() ([]Edge[K], error) + // ListOutEdges should return all edges of a given source vertex in the graph in a slice. + ListOutEdges(sourceHash K) ([]Edge[K], error) + + // ListInEdges should return all edges of a given target vertex in the graph in a slice. + ListInEdges(targetHash K) ([]Edge[K], error) + // EdgeCount should return the number of edges in the graph. This should be equal to the // length of the slice returned by ListEdges. EdgeCount() (int, error) @@ -75,8 +81,8 @@ type memoryStore[K comparable, T any] struct { // outEdges and inEdges store all outgoing and ingoing edges for all vertices. For O(1) access, // these edges themselves are stored in maps whose keys are the hashes of the target vertices. - outEdges map[K]map[K]Edge[K] // source -> target - inEdges map[K]map[K]Edge[K] // target -> source + outEdges map[K]map[K]Edge[K] // source -> target + inEdges map[K]map[K]Edge[K] // target -> source edgeCount int } @@ -254,6 +260,30 @@ func (s *memoryStore[K, T]) ListEdges() ([]Edge[K], error) { return res, nil } +func (s *memoryStore[K, T]) ListOutEdges(sourceHash K) ([]Edge[K], error) { + s.lock.RLock() + defer s.lock.RUnlock() + + outEdges := s.outEdges[sourceHash] + res := make([]Edge[K], 0, len(outEdges)) + for _, edge := range outEdges { + res = append(res, edge) + } + return res, nil +} + +func (s *memoryStore[K, T]) ListInEdges(targetHash K) ([]Edge[K], error) { + s.lock.RLock() + defer s.lock.RUnlock() + + inEdges := s.inEdges[targetHash] + res := make([]Edge[K], 0, len(inEdges)) + for _, edge := range inEdges { + res = append(res, edge) + } + return res, nil +} + // CreatesCycle is a fastpath version of [CreatesCycle] that avoids calling // [PredecessorMap], which generates large amounts of garbage to collect. // diff --git a/undirected.go b/undirected.go index 519526e..39cd3be 100644 --- a/undirected.go +++ b/undirected.go @@ -216,6 +216,14 @@ func (u *undirected[K, T]) Edges() ([]Edge[K], error) { return edges, nil } +func (d *undirected[K, T]) InEdges(targetHash K) ([]Edge[K], error) { + return d.store.ListInEdges(targetHash) +} + +func (d *undirected[K, T]) OutEdges(sourceHash K) ([]Edge[K], error) { + return d.store.ListOutEdges(sourceHash) +} + func (u *undirected[K, T]) UpdateEdge(source, target K, options ...func(properties *EdgeProperties)) error { existingEdge, err := u.store.Edge(source, target) if err != nil { diff --git a/undirected_test.go b/undirected_test.go index c304eb3..f3b2f65 100644 --- a/undirected_test.go +++ b/undirected_test.go @@ -777,6 +777,198 @@ func TestUndirected_Edges(t *testing.T) { } } +func TestUndirected_OutEdges(t *testing.T) { + tests := map[string]struct { + vertices []int + edges []Edge[int] + expectedEdges []Edge[int] + }{ + "graph with 3 edges": { + vertices: []int{1, 2, 3}, + edges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 2, + Target: 3, + Properties: EdgeProperties{ + Weight: 20, + Attributes: map[string]string{ + "color": "green", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + expectedEdges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + g := New(IntHash) + + for _, vertex := range test.vertices { + _ = g.AddVertex(vertex) + } + + for _, edge := range test.edges { + _ = g.AddEdge(copyEdge(edge)) + } + + edges, err := g.OutEdges(test.vertices[0]) + if err != nil { + t.Fatalf("unexpected error: %v", err.Error()) + } + + for _, expectedEdge := range test.expectedEdges { + for _, actualEdge := range edges { + if actualEdge.Source != expectedEdge.Source || actualEdge.Target != expectedEdge.Target { + continue + } + if !edgesAreEqual(expectedEdge, actualEdge, false) { + t.Errorf("%s: expected edge %v, got %v", name, expectedEdge, actualEdge) + } + } + } + }) + } +} + +func TestUndirected_InEdges(t *testing.T) { + tests := map[string]struct { + vertices []int + edges []Edge[int] + expectedEdges []Edge[int] + }{ + "graph with 3 edges": { + vertices: []int{1, 2, 3}, + edges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 2, + Target: 3, + Properties: EdgeProperties{ + Weight: 20, + Attributes: map[string]string{ + "color": "green", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + expectedEdges: []Edge[int]{ + { + Source: 1, + Target: 2, + Properties: EdgeProperties{ + Weight: 10, + Attributes: map[string]string{ + "color": "red", + }, + }, + }, + { + Source: 3, + Target: 1, + Properties: EdgeProperties{ + Weight: 30, + Attributes: map[string]string{ + "color": "blue", + }, + }, + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + g := New(IntHash) + + for _, vertex := range test.vertices { + _ = g.AddVertex(vertex) + } + + for _, edge := range test.edges { + _ = g.AddEdge(copyEdge(edge)) + } + + edges, err := g.InEdges(test.vertices[0]) + if err != nil { + t.Fatalf("unexpected error: %v", err.Error()) + } + + for _, expectedEdge := range test.expectedEdges { + for _, actualEdge := range edges { + if actualEdge.Source != expectedEdge.Source || actualEdge.Target != expectedEdge.Target { + continue + } + if !edgesAreEqual(expectedEdge, actualEdge, false) { + t.Errorf("%s: expected edge %v, got %v", name, expectedEdge, actualEdge) + } + } + } + }) + } +} + func TestUndirected_UpdateEdge(t *testing.T) { tests := map[string]struct { vertices []int