@@ -134,6 +134,24 @@ class ArenaDiGraph {
134
134
inline bool directed () const noexcept {
135
135
return true ;
136
136
}
137
+
138
+ /* *
139
+ * Set the number of vertices in the graph.
140
+ * @param n new number of vertices
141
+ * @note This is used for internal purposes only.
142
+ */
143
+ inline void setOrder (size_t n) noexcept {
144
+ N = n;
145
+ }
146
+
147
+ /* *
148
+ * Set the number of edges in the graph.
149
+ * @param m new number of edges
150
+ * @note This is used for internal purposes only.
151
+ */
152
+ inline void setSize (size_t m) noexcept {
153
+ M = m;
154
+ }
137
155
#pragma endregion
138
156
139
157
@@ -793,13 +811,15 @@ class ArenaDiGraph {
793
811
* @param ie end iterator of edge keys to remove
794
812
* @param fl comparison function for edge keys
795
813
* @note [ib, ie) must be sorted and unique.
814
+ * @returns number of edges removed
796
815
*/
797
816
template <class I , class FL >
798
- inline void removeEdges (K u, I ib, I ie, FL fl) {
799
- if (!hasVertex (u)) return ;
817
+ inline size_t removeEdges (K u, I ib, I ie, FL fl) {
818
+ if (!hasVertex (u)) return 0 ;
800
819
auto *eb = edges[u], *ee = edges[u] + degrees[u];
801
820
auto it = set_difference (eb, ee, ib, ie, eb, fl);
802
821
degrees[u] = it - eb;
822
+ return ee - it;
803
823
}
804
824
805
825
@@ -809,11 +829,12 @@ class ArenaDiGraph {
809
829
* @param ib begin iterator of edge keys to remove
810
830
* @param ie end iterator of edge keys to remove
811
831
* @note [ib, ie) must be sorted and unique.
832
+ * @returns number of edges removed
812
833
*/
813
834
template <class I >
814
- inline void removeEdges (K u, I ib, I ie) {
835
+ inline size_t removeEdges (K u, I ib, I ie) {
815
836
auto fl = [](const auto & a, const auto & b) { return a.first < b; };
816
- removeEdges (u, ib, ie, fl);
837
+ return removeEdges (u, ib, ie, fl);
817
838
}
818
839
819
840
@@ -823,10 +844,11 @@ class ArenaDiGraph {
823
844
* @param ib begin iterator of edges to add
824
845
* @param ie end iterator of edges to add
825
846
* @note [ib, ie) must be sorted and unique.
847
+ * @returns number of edges added
826
848
*/
827
849
template <class I >
828
- inline void addEdges (K u, I ib, I ie) {
829
- if (!hasVertex (u) || ib==ie) return ;
850
+ inline size_t addEdges (K u, I ib, I ie) {
851
+ if (!hasVertex (u) || ib==ie) return 0 ;
830
852
auto *eb = edges[u], *ee = edges[u] + degrees[u];
831
853
size_t deg = degrees[u] + distance (ib, ie);
832
854
size_t cap = allocationCapacity (deg);
@@ -837,6 +859,7 @@ class ArenaDiGraph {
837
859
edges[u] = ptr;
838
860
degrees[u] = it - ptr;
839
861
capacities[u] = cap;
862
+ return (it - ptr) - (ee - eb);
840
863
}
841
864
842
865
@@ -1559,36 +1582,43 @@ class DiGraphCsr {
1559
1582
* Subtract a graph's edges from another graph.
1560
1583
* @param a graph to subtract from (updated)
1561
1584
* @param y graph to subtract
1585
+ * @returns number of edges removed
1562
1586
*/
1563
1587
template <class H , class G >
1564
- inline void subtractGraphEdgesU (H& a, const G& y) {
1588
+ inline size_t subtractGraphEdgesU (H& a, const G& y) {
1589
+ size_t dM = 0 ;
1565
1590
y.forEachVertexKey ([&](auto u) {
1566
1591
if (!a.hasVertex (u)) return ;
1567
1592
auto yb = y.beginEdges (u), ye = y.endEdges (u);
1568
1593
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1569
- a.removeEdges (u, yb, ye, fl);
1594
+ dM += a.removeEdges (u, yb, ye, fl);
1570
1595
});
1571
- a.update (true , true );
1596
+ // Update the number of edges.
1597
+ a.setSize (a.size () - dM);
1598
+ return dM;
1572
1599
}
1573
1600
1574
1601
1575
1602
/* *
1576
1603
* Subtract a graph's edges from another graph [parallel].
1577
1604
* @param a graph to subtract from (updated)
1578
1605
* @param y graph to subtract
1606
+ * @returns number of edges removed
1579
1607
*/
1580
1608
template <int CHUNK=1024 , class H , class G >
1581
- inline void subtractGraphOmpU (H& a, const G& y) {
1609
+ inline size_t subtractGraphOmpU (H& a, const G& y) {
1582
1610
using K = typename H::key_type;
1583
- size_t S = y.span ();
1584
- #pragma omp parallel for schedule(dynamic, CHUNK)
1611
+ size_t S = y.span (), dM = 0 ;
1612
+ #pragma omp parallel for schedule(dynamic, CHUNK) reduction(+:dM)
1585
1613
for (K u=0 ; u<S; ++u) {
1586
1614
if (!y.hasVertex (u) || !a.hasVertex (u)) continue ;
1587
1615
auto yb = y.beginEdges (u), ye = y.endEdges (u);
1588
1616
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1589
- a.removeEdges (u, yb, ye, fl);
1617
+ dM += a.removeEdges (u, yb, ye, fl);
1590
1618
}
1591
- a.updateOmp (true , true );
1619
+ // Update the number of edges.
1620
+ a.setSize (a.size () - dM);
1621
+ return dM;
1592
1622
}
1593
1623
1594
1624
@@ -1597,10 +1627,11 @@ inline void subtractGraphOmpU(H& a, const G& y) {
1597
1627
* @param a output graph (output)
1598
1628
* @param x graph to subtract from
1599
1629
* @param y graph to subtract
1630
+ * @returns number of edges removed
1600
1631
*/
1601
1632
template <class H , class GX , class GY >
1602
- inline void subtractGraphW (H& a, const GX& x, const GY& y) {
1603
- size_t S = x.span ();
1633
+ inline size_t subtractGraphW (H& a, const GX& x, const GY& y) {
1634
+ size_t S = x.span (), dM = 0 ;
1604
1635
a.clear ();
1605
1636
a.reserve (S);
1606
1637
// Add the vertices.
@@ -1628,8 +1659,11 @@ inline void subtractGraphW(H& a, const GX& x, const GY& y) {
1628
1659
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1629
1660
auto it = set_difference (xb, xe, yb, ye, ab, fl);
1630
1661
a.setDegreeUnsafe (u, it - ab);
1662
+ dM += (xe - xb) - (it - ab);
1631
1663
});
1664
+ // Update the number of edges.
1632
1665
a.update (true , true );
1666
+ return dM;
1633
1667
}
1634
1668
1635
1669
@@ -1639,11 +1673,12 @@ inline void subtractGraphW(H& a, const GX& x, const GY& y) {
1639
1673
* @param a output graph (output)
1640
1674
* @param x graph to subtract from
1641
1675
* @param y graph to subtract
1676
+ * @returns number of edges removed
1642
1677
*/
1643
1678
template <int CHUNK=1024 , class H , class GX , class GY >
1644
- inline void subtractGraphOmpW (H& a, const GX& x, const GY& y) {
1679
+ inline size_t subtractGraphOmpW (H& a, const GX& x, const GY& y) {
1645
1680
using K = typename H::key_type;
1646
- size_t S = x.span ();
1681
+ size_t S = x.span (), dM = 0 ;
1647
1682
a.clearOmp ();
1648
1683
a.reserveOmp (S);
1649
1684
// Add the vertices.
@@ -1668,7 +1703,7 @@ inline void subtractGraphOmpW(H& a, const GX& x, const GY& y) {
1668
1703
a.setDegreeUnsafe (u, it - ab);
1669
1704
}
1670
1705
// Now add edges of vertices that are touched.
1671
- #pragma omp parallel for schedule(dynamic, CHUNK)
1706
+ #pragma omp parallel for schedule(dynamic, CHUNK) reduction(+:dM)
1672
1707
for (K u=0 ; u<S; ++u) {
1673
1708
if (!x.hasVertex (u) || !y.hasVertex (u)) continue ;
1674
1709
auto xb = x.beginEdges (u), xe = x.endEdges (u);
@@ -1677,8 +1712,11 @@ inline void subtractGraphOmpW(H& a, const GX& x, const GY& y) {
1677
1712
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1678
1713
auto it = set_difference (xb, xe, yb, ye, ab, fl);
1679
1714
a.setDegreeUnsafe (u, it - ab);
1715
+ dM += (xe - xb) - (it - ab);
1680
1716
}
1717
+ // Update the number of edges.
1681
1718
a.updateOmp (true , true );
1719
+ return dM;
1682
1720
}
1683
1721
#endif
1684
1722
@@ -1687,11 +1725,12 @@ inline void subtractGraphOmpW(H& a, const GX& x, const GY& y) {
1687
1725
* Add a graph's edges to another graph.
1688
1726
* @param a graph to add to (updated)
1689
1727
* @param y graph to add
1728
+ * @returns number of edges added
1690
1729
*/
1691
1730
template <class H , class G >
1692
- inline void addGraphU (H& a, const G& y) {
1693
- size_t A = a.span (), Y = y.span ();
1694
- size_t S = max (A, Y);
1731
+ inline size_t addGraphU (H& a, const G& y) {
1732
+ size_t A = a.span (), Y = y.span ();
1733
+ size_t S = max (A, Y), dM = 0 ;
1695
1734
if (S!=A) a.respan (S);
1696
1735
// Add new vertices.
1697
1736
y.forEachVertex ([&](auto u, auto d) {
@@ -1700,9 +1739,11 @@ inline void addGraphU(H& a, const G& y) {
1700
1739
// Add new edges.
1701
1740
y.forEachVertex ([&](auto u, auto d) {
1702
1741
auto yb = y.beginEdges (u), ye = y.endEdges (u);
1703
- a.addEdges (u, yb, ye);
1742
+ dM += a.addEdges (u, yb, ye);
1704
1743
});
1705
- a.update (true , true );
1744
+ // Update the number of edges.
1745
+ a.setSize (a.size () + dM);
1746
+ return dM;
1706
1747
}
1707
1748
1708
1749
@@ -1711,12 +1752,13 @@ inline void addGraphU(H& a, const G& y) {
1711
1752
* Add a graph's edges to another graph [parallel].
1712
1753
* @param a graph to add to (updated)
1713
1754
* @param y graph to add
1755
+ * @returns number of edges added
1714
1756
*/
1715
1757
template <int CHUNK=512 , class H , class G >
1716
- inline void addGraphOmpU (H& a, const G& y) {
1758
+ inline size_t addGraphOmpU (H& a, const G& y) {
1717
1759
using K = typename H::key_type;
1718
- size_t A = a.span (), Y = y.span ();
1719
- size_t S = max (A, Y);
1760
+ size_t A = a.span (), Y = y.span ();
1761
+ size_t S = max (A, Y), dM = 0 ;
1720
1762
if (S!=A) a.respan (S);
1721
1763
// Add new vertices.
1722
1764
#pragma omp parallel for schedule(static, 2048)
@@ -1725,13 +1767,15 @@ inline void addGraphOmpU(H& a, const G& y) {
1725
1767
a.addVertex (u, y.vertexValue (u));
1726
1768
}
1727
1769
// Add new edges.
1728
- #pragma omp parallel for schedule(dynamic, CHUNK)
1770
+ #pragma omp parallel for schedule(dynamic, CHUNK) reduction(+:dM)
1729
1771
for (K u=0 ; u<Y; ++u) {
1730
1772
if (!y.hasVertex (u)) continue ;
1731
1773
auto yb = y.beginEdges (u), ye = y.endEdges (u);
1732
- a.addEdges (u, yb, ye);
1774
+ dM += a.addEdges (u, yb, ye);
1733
1775
}
1734
- a.updateOmp (true , true );
1776
+ // Update the number of edges.
1777
+ a.setSize (a.size () + dM);
1778
+ return dM;
1735
1779
}
1736
1780
#endif
1737
1781
@@ -1741,12 +1785,13 @@ inline void addGraphOmpU(H& a, const G& y) {
1741
1785
* @param a output graph (output)
1742
1786
* @param x graph to add from
1743
1787
* @param y graph to add
1788
+ * @returns number of edges added
1744
1789
*/
1745
1790
template <class H , class GX , class GY >
1746
- inline void addGraphW (H& a, const GX& x, const GY& y) {
1791
+ inline size_t addGraphW (H& a, const GX& x, const GY& y) {
1747
1792
using K = typename H::key_type;
1748
- size_t X = x.span (), Y = y.span ();
1749
- size_t S = max (X, Y);
1793
+ size_t X = x.span (), Y = y.span ();
1794
+ size_t S = max (X, Y), dM = 0 ;
1750
1795
a.clear ();
1751
1796
a.reserve (S);
1752
1797
// Add the vertices.
@@ -1766,8 +1811,11 @@ inline void addGraphW(H& a, const GX& x, const GY& y) {
1766
1811
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1767
1812
auto it = set_union (xb, xe, yb, ye, ab, fl);
1768
1813
a.setDegreeUnsafe (u, it - ab);
1814
+ dM += (it - ab) - (xe - xb);
1769
1815
}
1816
+ // Update the number of edges.
1770
1817
a.update (true , true );
1818
+ return dM;
1771
1819
}
1772
1820
1773
1821
@@ -1779,10 +1827,10 @@ inline void addGraphW(H& a, const GX& x, const GY& y) {
1779
1827
* @param y graph to add
1780
1828
*/
1781
1829
template <int CHUNK=512 , class H , class GX , class GY >
1782
- inline void addGraphOmpW (H& a, const GX& x, const GY& y) {
1830
+ inline size_t addGraphOmpW (H& a, const GX& x, const GY& y) {
1783
1831
using K = typename H::key_type;
1784
- size_t X = x.span (), Y = y.span ();
1785
- size_t S = max (X, Y);
1832
+ size_t X = x.span (), Y = y.span ();
1833
+ size_t S = max (X, Y), dM = 0 ;
1786
1834
a.clearOmp ();
1787
1835
a.reserveOmp (S);
1788
1836
// Add the vertices.
@@ -1798,7 +1846,7 @@ inline void addGraphOmpW(H& a, const GX& x, const GY& y) {
1798
1846
a.allocateEdges (u, x.degree (u) + y.degree (u));
1799
1847
}
1800
1848
// Now add edges of vertices that are touched.
1801
- #pragma omp parallel for schedule(dynamic, CHUNK)
1849
+ #pragma omp parallel for schedule(dynamic, CHUNK) reduction(+:dM)
1802
1850
for (K u=0 ; u<S; ++u) {
1803
1851
if (!x.hasVertex (u) && !y.hasVertex (u)) continue ;
1804
1852
auto xb = x.beginEdges (u), xe = x.endEdges (u);
@@ -1807,8 +1855,11 @@ inline void addGraphOmpW(H& a, const GX& x, const GY& y) {
1807
1855
auto fl = [](const auto & a, const auto & b) { return a.first < b.first ; };
1808
1856
auto it = set_union (xb, xe, yb, ye, ab, fl);
1809
1857
a.setDegreeUnsafe (u, it - ab);
1858
+ dM += (it - ab) - (xe - xb);
1810
1859
}
1860
+ // Update the number of edges.
1811
1861
a.updateOmp (true , true );
1862
+ return dM;
1812
1863
}
1813
1864
#endif
1814
1865
#pragma endregion
0 commit comments