OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::MaxFlowSolver Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/GCode/ToolOrderUtils.hpp>

Collaboration diagram for Slic3r::MaxFlowSolver:

Public Member Functions

 MaxFlowSolver (const std::vector< int > &u_nodes, const std::vector< int > &v_nodes, const std::unordered_map< int, std::vector< int > > &uv_link_limits={}, const std::unordered_map< int, std::vector< int > > &uv_unlink_limits={}, const std::vector< int > &u_capacity={}, const std::vector< int > &v_capacity={}, const std::vector< std::pair< std::set< int >, int > > &v_group_capacity={})
std::vector< int > solve ()

Private Member Functions

void add_edge (int from, int to, int capacity)

Private Attributes

int total_nodes
int source_id
int sink_id
std::vector< Edge > edges
std::vector< int > l_nodes
std::vector< int > r_nodes
std::vector< std::vector< int > > adj

Detailed Description

Constructor & Destructor Documentation

◆ MaxFlowSolver()

Slic3r::MaxFlowSolver::MaxFlowSolver ( const std::vector< int > & u_nodes,
const std::vector< int > & v_nodes,
const std::unordered_map< int, std::vector< int > > & uv_link_limits = {},
const std::unordered_map< int, std::vector< int > > & uv_unlink_limits = {},
const std::vector< int > & u_capacity = {},
const std::vector< int > & v_capacity = {},
const std::vector< std::pair< std::set< int >, int > > & v_group_capacity = {} )
224 {
225 assert(u_capacity.empty() || u_capacity.size() == u_nodes.size());
226 assert(v_capacity.empty() || v_capacity.size() == v_nodes.size());
227 l_nodes = u_nodes;
228 r_nodes = v_nodes;
229 total_nodes = u_nodes.size() + v_nodes.size() + v_group_capacity.size() + 2;
231 sink_id = total_nodes - 1;
232
233 adj.resize(total_nodes);
234
235 std::vector<int>v_node_to(v_nodes.size(), sink_id);
236 for (size_t gid = 0; gid < v_group_capacity.size(); ++gid) {
237 for (auto vid : v_group_capacity[gid].first)
238 v_node_to[vid] = l_nodes.size() + r_nodes.size() + gid;
239 }
240
241 // add edge from source to left nodes
242 for (int idx = 0; idx < l_nodes.size(); ++idx) {
243 int capacity = u_capacity.empty() ? 1 : u_capacity[idx];
244 add_edge(source_id, idx, capacity);
245 }
246 // add edge from right nodes to v_node_to(sink node or temp group node)
247 for (int idx = 0; idx < r_nodes.size(); ++idx) {
248 int capacity = v_capacity.empty() ? 1 : v_capacity[idx];
249 add_edge(l_nodes.size() + idx, v_node_to[idx], capacity);
250 }
251
252 // add edge from temp group node to sink node
253 for (int idx = 0; idx < v_group_capacity.size(); ++idx) {
254 int capacity = v_group_capacity[idx].second;
255 add_edge(l_nodes.size() + r_nodes.size() + idx, sink_id, capacity);
256 }
257
258 // add edge from left nodes to right nodes
259 for (int i = 0; i < l_nodes.size(); ++i) {
260 int from_idx = i;
261 // process link limits , i can only link to uv_link_limits
262 if (auto iter = uv_link_limits.find(i); iter != uv_link_limits.end()) {
263 for (auto r_id : iter->second)
264 add_edge(from_idx, l_nodes.size() + r_id, 1);
265 continue;
266 }
267 // process unlink limits
268 std::optional<std::vector<int>> unlink_limits;
269 if (auto iter = uv_unlink_limits.find(i); iter != uv_unlink_limits.end())
270 unlink_limits = iter->second;
271
272 for (int j = 0; j < r_nodes.size(); ++j) {
273 // check whether i can link to j
274 if (unlink_limits.has_value() && std::find(unlink_limits->begin(), unlink_limits->end(), j) != unlink_limits->end())
275 continue;
276 add_edge(from_idx, l_nodes.size() + j, 1);
277 }
278 }
279 }
std::vector< int > l_nodes
Definition ToolOrderUtils.hpp:53
void add_edge(int from, int to, int capacity)
Definition ToolOrderUtils.cpp:281
int source_id
Definition ToolOrderUtils.hpp:50
std::vector< int > r_nodes
Definition ToolOrderUtils.hpp:54
int total_nodes
Definition ToolOrderUtils.hpp:49
int sink_id
Definition ToolOrderUtils.hpp:51
std::vector< std::vector< int > > adj
Definition ToolOrderUtils.hpp:55

References add_edge(), adj, l_nodes, r_nodes, sink_id, source_id, and total_nodes.

Here is the call graph for this function:

Member Function Documentation

◆ add_edge()

void Slic3r::MaxFlowSolver::add_edge ( int from,
int to,
int capacity )
private
282 {
283 adj[from].emplace_back(edges.size());
284 edges.emplace_back(from, to, capacity);
285 //also add reverse edge ,set capacity to zero
286 adj[to].emplace_back(edges.size());
287 edges.emplace_back(to, from, 0);
288 }
std::vector< Edge > edges
Definition ToolOrderUtils.hpp:52

References adj, and edges.

Referenced by MaxFlowSolver().

Here is the caller graph for this function:

◆ solve()

std::vector< int > Slic3r::MaxFlowSolver::solve ( )
290 {
291 std::vector<int> augment;
292 std::vector<int> previous(total_nodes, 0);
293 while (1) {
294 std::vector<int>(total_nodes, 0).swap(augment);
295 std::queue<int> travel;
296 travel.push(source_id);
297 augment[source_id] = MaxFlowGraph::INF;
298 while (!travel.empty()) {
299 int from = travel.front();
300 travel.pop();
301
302 // traverse all linked edges
303 for (int i = 0; i < adj[from].size(); ++i) {
304 int eid = adj[from][i];
305 Edge& tmp = edges[eid];
306 if (augment[tmp.to] == 0 && tmp.capacity > tmp.flow) {
307 previous[tmp.to] = eid;
308 augment[tmp.to] = std::min(augment[from], tmp.capacity - tmp.flow);
309 travel.push(tmp.to);
310 }
311 }
312
313 // already find an extend path, stop and do update
314 if (augment[sink_id] != 0)
315 break;
316 }
317 // no longer have extend path
318 if (augment[sink_id] == 0)
319 break;
320
321 for (int i = sink_id; i != source_id; i = edges[previous[i]].from) {
322 edges[previous[i]].flow += augment[sink_id];
323 edges[previous[i] ^ 1].flow -= augment[sink_id];
324 }
325 }
326
327 std::vector<int> matching(l_nodes.size(), MaxFlowGraph::INVALID_ID);
328 // to get the match info, just traverse the left nodes and
329 // check the edge with flow > 0 and linked to right nodes
330 for (int u = 0; u < l_nodes.size(); ++u) {
331 for (int eid : adj[u]) {
332 Edge& e = edges[eid];
333 if (e.flow > 0 && e.to >= l_nodes.size() && e.to < l_nodes.size() + r_nodes.size())
334 matching[e.from] = r_nodes[e.to - l_nodes.size()];
335 }
336 }
337 return matching;
338 }
const int INF
Definition ToolOrderUtils.hpp:20
const int INVALID_ID
Definition ToolOrderUtils.hpp:21
@ Edge
Definition Measure.hpp:26

References adj, Slic3r::Edge::capacity, edges, Slic3r::Edge::flow, Slic3r::Edge::from, Slic3r::MaxFlowGraph::INF, Slic3r::MaxFlowGraph::INVALID_ID, l_nodes, r_nodes, sink_id, source_id, Slic3r::Edge::to, and total_nodes.

Referenced by Slic3r::KMediods::init_cluster_center().

Here is the caller graph for this function:

Member Data Documentation

◆ adj

std::vector<std::vector<int> > Slic3r::MaxFlowSolver::adj
private

Referenced by MaxFlowSolver(), add_edge(), and solve().

◆ edges

std::vector<Edge> Slic3r::MaxFlowSolver::edges
private

Referenced by add_edge(), and solve().

◆ l_nodes

std::vector<int> Slic3r::MaxFlowSolver::l_nodes
private

Referenced by MaxFlowSolver(), and solve().

◆ r_nodes

std::vector<int> Slic3r::MaxFlowSolver::r_nodes
private

Referenced by MaxFlowSolver(), and solve().

◆ sink_id

int Slic3r::MaxFlowSolver::sink_id
private

Referenced by MaxFlowSolver(), and solve().

◆ source_id

int Slic3r::MaxFlowSolver::source_id
private

Referenced by MaxFlowSolver(), and solve().

◆ total_nodes

int Slic3r::MaxFlowSolver::total_nodes
private

Referenced by MaxFlowSolver(), and solve().


The documentation for this class was generated from the following files: