Skip to content

Commit fdd9f75

Browse files
committed
(edgeDisjointPaths) using the new shortestPath process & driver
1 parent 6fcb2a7 commit fdd9f75

4 files changed

Lines changed: 120 additions & 93 deletions

File tree

include/max_flow/maxflow.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ class PgrFlowGraph {
198198
};
199199

200200
} // namespace graph
201+
202+
namespace functions {
203+
204+
std::vector<Path_rt> edgeDisjoint(std::vector<Edge_t>, const std::map<int64_t, std::set<int64_t>>&, bool);
205+
206+
} // namespace functions
201207
} // namespace pgrouting
202208

203209
#endif // INCLUDE_MAX_FLOW_MAXFLOW_HPP_

src/max_flow/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ ADD_LIBRARY(max_flow OBJECT
1111
maxFlow_process.cpp
1212

1313
maximum_cardinality_matching_driver.cpp
14-
edge_disjoint_paths_driver.cpp
1514
minCostMaxFlow_driver.cpp
1615

1716
maximumcardinalitymatching.cpp
1817
maxflow.cpp
1918
flowgraph.cpp
2019
minCostMaxFlow.cpp
21-
)
20+
)

src/max_flow/edge_disjoint_paths.c

Lines changed: 64 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -28,102 +28,77 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2828
********************************************************************PGR-GNU*/
2929

3030
#include <stdbool.h>
31-
3231
#include "c_common/postgres_connection.h"
33-
3432
#include "c_types/path_rt.h"
35-
#include "c_common/debug_macro.h"
36-
#include "c_common/e_report.h"
37-
#include "c_common/time_msg.h"
38-
#include "drivers/max_flow/edge_disjoint_paths_driver.h"
33+
#include "process/shortestPath_process.h"
3934

4035
PGDLLEXPORT Datum
4136
_pgr_edgedisjointpaths(PG_FUNCTION_ARGS);
42-
43-
static
44-
void
45-
process(
46-
char *edges_sql,
47-
char *combinations_sql,
48-
ArrayType *starts,
49-
ArrayType *ends,
50-
51-
bool directed,
52-
Path_rt **result_tuples,
53-
size_t *result_count) {
54-
pgr_SPI_connect();
55-
char* log_msg = NULL;
56-
char* notice_msg = NULL;
57-
char* err_msg = NULL;
58-
59-
clock_t start_t = clock();
60-
pgr_do_edge_disjoint_paths(
61-
edges_sql,
62-
combinations_sql,
63-
starts, ends,
64-
directed,
65-
66-
result_tuples, result_count,
67-
68-
&log_msg,
69-
&notice_msg,
70-
&err_msg);
71-
time_msg("pgr_edgeDisjointPaths(many to many)", start_t, clock());
72-
73-
if (err_msg && (*result_tuples)) {
74-
pfree(*result_tuples);
75-
(*result_tuples) = NULL;
76-
(*result_count) = 0;
77-
}
78-
79-
pgr_global_report(&log_msg, &notice_msg, &err_msg);
80-
81-
pgr_SPI_finish();
82-
}
83-
8437
PG_FUNCTION_INFO_V1(_pgr_edgedisjointpaths);
38+
8539
PGDLLEXPORT Datum
8640
_pgr_edgedisjointpaths(PG_FUNCTION_ARGS) {
87-
FuncCallContext *funcctx;
88-
TupleDesc tuple_desc;
41+
FuncCallContext *funcctx;
42+
TupleDesc tuple_desc;
8943

90-
Path_rt *result_tuples = NULL;
44+
Path_rt *result_tuples = NULL;
9145
size_t result_count = 0;
9246

9347
if (SRF_IS_FIRSTCALL()) {
94-
MemoryContext oldcontext;
48+
MemoryContext oldcontext;
9549
funcctx = SRF_FIRSTCALL_INIT();
9650
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
9751

98-
9952
if (PG_NARGS() == 4) {
10053
/*
10154
* many to many
10255
*/
103-
process(
56+
pgr_process_shortestPath(
10457
text_to_cstring(PG_GETARG_TEXT_P(0)),
10558
NULL,
59+
NULL,
60+
10661
PG_GETARG_ARRAYTYPE_P(1),
10762
PG_GETARG_ARRAYTYPE_P(2),
63+
10864
PG_GETARG_BOOL(3),
65+
false,
66+
true,
67+
68+
0,
69+
true,
70+
' ',
71+
true,
72+
73+
EDGEDISJOINT,
10974
&result_tuples,
11075
&result_count);
11176

11277
} else if (PG_NARGS() == 3) {
11378
/*
114-
* combinations
79+
* Combinations
11580
*/
116-
process(
81+
pgr_process_shortestPath(
11782
text_to_cstring(PG_GETARG_TEXT_P(0)),
118-
text_to_cstring(PG_GETARG_TEXT_P(1)),
119-
NULL,
12083
NULL,
84+
text_to_cstring(PG_GETARG_TEXT_P(1)),
85+
86+
NULL, NULL,
87+
12188
PG_GETARG_BOOL(2),
89+
false,
90+
true,
91+
92+
0,
93+
true,
94+
' ',
95+
true,
96+
97+
EDGEDISJOINT,
12298
&result_tuples,
12399
&result_count);
124100
}
125101

126-
127102
funcctx->max_calls = result_count;
128103
funcctx->user_fctx = result_tuples;
129104
if (get_call_result_type(fcinfo, NULL, &tuple_desc)
@@ -140,50 +115,50 @@ _pgr_edgedisjointpaths(PG_FUNCTION_ARGS) {
140115

141116
funcctx = SRF_PERCALL_SETUP();
142117
tuple_desc = funcctx->tuple_desc;
143-
result_tuples = (Path_rt *) funcctx->user_fctx;
118+
result_tuples = (Path_rt*) funcctx->user_fctx;
144119

145120
if (funcctx->call_cntr < funcctx->max_calls) {
146-
HeapTuple tuple;
147-
Datum result;
148-
Datum *values;
149-
bool *nulls;
150-
121+
HeapTuple tuple;
122+
Datum result;
123+
Datum *values;
124+
bool* nulls;
125+
size_t call_cntr = funcctx->call_cntr;
151126

152-
values = palloc(9 * sizeof(Datum));
153-
nulls = palloc(9 * sizeof(bool));
127+
size_t numb = 9;
128+
values = palloc(numb * sizeof(Datum));
129+
nulls = palloc(numb * sizeof(bool));
154130

155131
size_t i;
156-
for (i = 0; i < 9; ++i) {
132+
for (i = 0; i < numb; ++i) {
157133
nulls[i] = false;
158134
}
159135

160-
int64_t path_id = 1;
161-
int64_t seq = 1;
162-
if (funcctx->call_cntr != 0) {
163-
if (result_tuples[funcctx->call_cntr - 1].edge == -1) {
164-
path_id = result_tuples[funcctx->call_cntr - 1].start_id + 1;
165-
seq = 1;
166-
} else {
167-
path_id = result_tuples[funcctx->call_cntr - 1].start_id;
168-
seq = result_tuples[funcctx->call_cntr - 1].end_id + 1;
169-
}
170-
}
171136

172-
values[0] = Int32GetDatum((int32_t)funcctx->call_cntr + 1);
137+
/* from previous record:
138+
* end_id has the sequence of this record
139+
* start_id has the path_id of this record
140+
* cost has the agg_cost of this record
141+
*/
142+
int64_t path_id = call_cntr == 0? 1 : result_tuples[call_cntr - 1].start_id;
143+
int64_t seq = call_cntr == 0? 1 : result_tuples[call_cntr - 1].end_id;
144+
double agg_cost = call_cntr == 0? 0 : result_tuples[call_cntr - 1].cost;
145+
146+
values[0] = Int32GetDatum((int32_t)call_cntr + 1);
173147
values[1] = Int32GetDatum((int32_t)path_id);
174148
values[2] = Int32GetDatum((int32_t)seq);
175-
values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].start_id);
176-
values[4] = Int64GetDatum(result_tuples[funcctx->call_cntr].end_id);
177-
values[5] = Int64GetDatum(result_tuples[funcctx->call_cntr].node);
178-
values[6] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge);
179-
values[7] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost);
180-
values[8] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost);
149+
values[3] = Int64GetDatum(result_tuples[call_cntr].start_id);
150+
values[4] = Int64GetDatum(result_tuples[call_cntr].end_id);
151+
values[5] = Int64GetDatum(result_tuples[call_cntr].node);
152+
values[6] = Int64GetDatum(result_tuples[call_cntr].edge);
153+
values[7] = Float8GetDatum(result_tuples[call_cntr].cost);
154+
values[8] = Float8GetDatum(agg_cost);
181155

182156
/*
183-
* storing in the previous record values to use on the next record
157+
* storing in this record values to use on the next record
184158
*/
185-
result_tuples[funcctx->call_cntr].start_id = path_id;
186-
result_tuples[funcctx->call_cntr].end_id = seq;
159+
result_tuples[call_cntr].start_id = result_tuples[call_cntr].edge == -1? path_id + 1 : path_id;
160+
result_tuples[call_cntr].end_id = result_tuples[call_cntr].edge == -1? 1 : seq + 1;
161+
result_tuples[call_cntr].cost = result_tuples[call_cntr].edge == -1? 0 : agg_cost + result_tuples[call_cntr].cost;
187162

188163
tuple = heap_form_tuple(tuple_desc, values, nulls);
189164
result = HeapTupleGetDatum(tuple);

src/max_flow/maxflow.cpp

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,31 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3232
#include <vector>
3333
#include <set>
3434

35+
36+
namespace {
37+
38+
std::vector<Path_rt>
39+
single_execution(
40+
std::vector<Edge_t> edges,
41+
int64_t source,
42+
int64_t target,
43+
bool directed) {
44+
std::set<int64_t> set_source_vertices;
45+
std::set<int64_t> set_sink_vertices;
46+
set_source_vertices.insert(source);
47+
set_sink_vertices.insert(target);
48+
pgrouting::graph::PgrFlowGraph G(
49+
edges,
50+
set_source_vertices,
51+
set_sink_vertices, directed);
52+
53+
/*
54+
* boykov_kolmogorov is only for directed graphs
55+
*/
56+
return G.edge_disjoint_paths();
57+
}
58+
} // namespace
59+
3560
namespace pgrouting {
3661
namespace graph {
3762

@@ -309,8 +334,30 @@ PgrFlowGraph::get_edge_disjoint_paths(
309334
return path_elements;
310335
}
311336

337+
} // namespace graph
312338

313339

314-
} // namespace graph
315-
} // namespace pgrouting
316340

341+
namespace functions {
342+
std::vector<Path_rt>
343+
edgeDisjoint(
344+
std::vector<Edge_t> edges,
345+
const std::map<int64_t, std::set<int64_t>> & combinations,
346+
bool directed) {
347+
std::vector<Path_rt> results;
348+
for (const auto &c : combinations) {
349+
for (const auto &t : c.second) {
350+
/*
351+
* a source can not be a sink
352+
* aka there is no path
353+
*/
354+
if (c.first == t) continue;
355+
auto result = single_execution(edges, c.first, t, directed);
356+
results.insert(results.end(), result.begin(), result.end());
357+
}
358+
}
359+
360+
return results;
361+
}
362+
} // namespace functions
363+
} // namespace pgrouting

0 commit comments

Comments
 (0)