(svn r25885) -Codechange: Keep paths sorted so that the ones with flow == 0 are in the back and don't have to be iterated over so often.

This commit is contained in:
fonsinchen 2013-10-19 17:15:19 +00:00
parent c08259fe92
commit b3b460cae2
4 changed files with 28 additions and 7 deletions

View File

@ -28,7 +28,7 @@ void FlowMapper::Run(LinkGraphJob &job) const
for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) { for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) {
Path *path = *i; Path *path = *i;
uint flow = path->GetFlow(); uint flow = path->GetFlow();
if (flow == 0) continue; if (flow == 0) break;
/* compress to monthly value */ /* compress to monthly value */
flow = max(1U, flow * 30 / runtime); flow = max(1U, flow * 30 / runtime);
Node node = job[path->GetNode()]; Node node = job[path->GetNode()];

View File

@ -181,7 +181,7 @@ uint Path::AddFlow(uint new_flow, LinkGraphJob &job, uint max_saturation)
} }
new_flow = this->parent->AddFlow(new_flow, job, max_saturation); new_flow = this->parent->AddFlow(new_flow, job, max_saturation);
if (this->flow == 0 && new_flow > 0) { if (this->flow == 0 && new_flow > 0) {
job[this->parent->node].Paths().push_back(this); job[this->parent->node].Paths().push_front(this);
} }
edge.AddFlow(new_flow); edge.AddFlow(new_flow);
} }

View File

@ -45,7 +45,7 @@ private:
*/ */
struct NodeAnnotation { struct NodeAnnotation {
uint undelivered_supply; ///< Amount of supply that hasn't been distributed yet. uint undelivered_supply; ///< Amount of supply that hasn't been distributed yet.
PathList paths; ///< Paths through this node. PathList paths; ///< Paths through this node, sorted so that those with flow == 0 are in the back.
FlowStatMap flows; ///< Planned flows to other nodes. FlowStatMap flows; ///< Planned flows to other nodes.
void Init(uint supply); void Init(uint supply);
}; };
@ -234,7 +234,8 @@ public:
const FlowStatMap &Flows() const { return this->node_anno.flows; } const FlowStatMap &Flows() const { return this->node_anno.flows; }
/** /**
* Get the paths this node is part of. * Get the paths this node is part of. Paths are always expected to be
* sorted so that those with flow == 0 are in the back of the list.
* @return Paths. * @return Paths.
*/ */
PathList &Paths() { return this->node_anno.paths; } PathList &Paths() { return this->node_anno.paths; }

View File

@ -351,7 +351,17 @@ void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
do { do {
NodeID prev = cycle_begin->GetNode(); NodeID prev = cycle_begin->GetNode();
cycle_begin->ReduceFlow(flow); cycle_begin->ReduceFlow(flow);
cycle_begin = path[cycle_begin->GetNode()]; if (cycle_begin->GetFlow() == 0) {
PathList &node_paths = this->job[cycle_begin->GetParent()->GetNode()].Paths();
for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
if (*i == cycle_begin) {
node_paths.erase(i);
node_paths.push_back(cycle_begin);
break;
}
}
}
cycle_begin = path[prev];
Edge edge = this->job[prev][cycle_begin->GetNode()]; Edge edge = this->job[prev][cycle_begin->GetNode()];
edge.RemoveFlow(flow); edge.RemoveFlow(flow);
} while (cycle_begin != cycle_end); } while (cycle_begin != cycle_end);
@ -379,18 +389,28 @@ bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next
* in one path each. */ * in one path each. */
PathList &paths = this->job[next_id].Paths(); PathList &paths = this->job[next_id].Paths();
PathViaMap next_hops; PathViaMap next_hops;
for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) { for (PathList::iterator i = paths.begin(); i != paths.end();) {
Path *new_child = *i; Path *new_child = *i;
uint new_flow = new_child->GetFlow();
if (new_flow == 0) break;
if (new_child->GetOrigin() == origin_id) { if (new_child->GetOrigin() == origin_id) {
PathViaMap::iterator via_it = next_hops.find(new_child->GetNode()); PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
if (via_it == next_hops.end()) { if (via_it == next_hops.end()) {
next_hops[new_child->GetNode()] = new_child; next_hops[new_child->GetNode()] = new_child;
++i;
} else { } else {
Path *child = via_it->second; Path *child = via_it->second;
uint new_flow = new_child->GetFlow();
child->AddFlow(new_flow); child->AddFlow(new_flow);
new_child->ReduceFlow(new_flow); new_child->ReduceFlow(new_flow);
/* We might hit end() with with the ++ here and skip the
* newly push_back'ed path. That's good as the flow of that
* path is 0 anyway. */
paths.erase(i++);
paths.push_back(new_child);
} }
} else {
++i;
} }
} }
bool found = false; bool found = false;