robust fix to issue #4067
This commit is contained in:
@@ -120,7 +120,6 @@ cc_library(
|
||||
"//ortools/graph:cliques",
|
||||
"//ortools/util:logging",
|
||||
"//ortools/util:saturated_arithmetic",
|
||||
"//ortools/util:vector_map",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -989,19 +989,14 @@ bool CheckMinimumInt(const Constraint& ct,
|
||||
}
|
||||
|
||||
bool CheckNetworkFlowConservation(
|
||||
const Argument& arcs, const Argument& balance_input,
|
||||
const Argument& arcs, const Argument& balance_input, int base_node,
|
||||
const Argument& flow_vars,
|
||||
const std::function<int64_t(Variable*)>& evaluator) {
|
||||
std::vector<int64_t> balance(balance_input.values);
|
||||
int min_node = std::numeric_limits<int>::max();
|
||||
for (const int node : arcs.values) {
|
||||
min_node = std::min(min_node, node);
|
||||
}
|
||||
|
||||
const int num_arcs = Size(arcs) / 2;
|
||||
for (int arc = 0; arc < num_arcs; arc++) {
|
||||
const int tail = arcs.values[arc * 2] - min_node;
|
||||
const int head = arcs.values[arc * 2 + 1] - min_node;
|
||||
const int tail = arcs.values[arc * 2] - base_node;
|
||||
const int head = arcs.values[arc * 2 + 1] - base_node;
|
||||
const int64_t flow = EvalAt(flow_vars, arc, evaluator);
|
||||
balance[tail] -= flow;
|
||||
balance[head] += flow;
|
||||
@@ -1017,13 +1012,15 @@ bool CheckNetworkFlowConservation(
|
||||
bool CheckNetworkFlow(const Constraint& ct,
|
||||
const std::function<int64_t(Variable*)>& evaluator) {
|
||||
return CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
|
||||
ct.arguments[2], evaluator);
|
||||
ct.arguments[2].Value(), ct.arguments[3],
|
||||
evaluator);
|
||||
}
|
||||
|
||||
bool CheckNetworkFlowCost(const Constraint& ct,
|
||||
const std::function<int64_t(Variable*)>& evaluator) {
|
||||
if (!CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
|
||||
ct.arguments[3], evaluator)) {
|
||||
ct.arguments[2].Value(), ct.arguments[3],
|
||||
evaluator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1031,11 +1028,11 @@ bool CheckNetworkFlowCost(const Constraint& ct,
|
||||
const int num_arcs = Size(ct.arguments[3]);
|
||||
for (int arc = 0; arc < num_arcs; arc++) {
|
||||
const int64_t flow = EvalAt(ct.arguments[3], arc, evaluator);
|
||||
const int64_t cost = EvalAt(ct.arguments[2], arc, evaluator);
|
||||
total_cost += flow * cost;
|
||||
const int64_t unit_cost = ct.arguments[4].ValueAt(arc);
|
||||
total_cost += flow * unit_cost;
|
||||
}
|
||||
|
||||
return total_cost == Eval(ct.arguments[4], evaluator);
|
||||
return total_cost == Eval(ct.arguments[5], evaluator);
|
||||
}
|
||||
|
||||
bool CheckNvalue(const Constraint& ct,
|
||||
|
||||
@@ -968,20 +968,18 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct,
|
||||
// Note that we leave ct empty here (with just the name set).
|
||||
// We simply do a linear encoding of this constraint.
|
||||
const bool has_cost = fz_ct.type == "ortools_network_flow_cost";
|
||||
const std::vector<int> flow = LookupVars(fz_ct.arguments[has_cost ? 3 : 2]);
|
||||
const std::vector<int> flow = LookupVars(fz_ct.arguments[3]);
|
||||
|
||||
// Flow conservation constraints.
|
||||
const int num_nodes = fz_ct.arguments[1].values.size();
|
||||
const int base_node = fz_ct.arguments[2].Value();
|
||||
std::vector<std::vector<int>> flows_per_node(num_nodes);
|
||||
std::vector<std::vector<int>> coeffs_per_node(num_nodes);
|
||||
int min_node = std::numeric_limits<int>::max();
|
||||
for (const int node : fz_ct.arguments[0].values) {
|
||||
min_node = std::min(min_node, node);
|
||||
}
|
||||
|
||||
const int num_arcs = fz_ct.arguments[0].values.size() / 2;
|
||||
for (int arc = 0; arc < num_arcs; arc++) {
|
||||
const int tail = fz_ct.arguments[0].values[2 * arc] - min_node;
|
||||
const int head = fz_ct.arguments[0].values[2 * arc + 1] - min_node;
|
||||
const int tail = fz_ct.arguments[0].values[2 * arc] - base_node;
|
||||
const int head = fz_ct.arguments[0].values[2 * arc + 1] - base_node;
|
||||
if (tail == head) continue;
|
||||
|
||||
flows_per_node[tail].push_back(flow[arc]);
|
||||
@@ -1004,19 +1002,19 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct,
|
||||
arg->add_domain(0);
|
||||
arg->add_domain(0);
|
||||
for (int arc = 0; arc < num_arcs; arc++) {
|
||||
const int64_t weight = fz_ct.arguments[2].values[arc];
|
||||
const int64_t weight = fz_ct.arguments[4].values[arc];
|
||||
if (weight != 0) {
|
||||
arg->add_vars(flow[arc]);
|
||||
arg->add_coeffs(weight);
|
||||
}
|
||||
}
|
||||
arg->add_vars(LookupVar(fz_ct.arguments[4]));
|
||||
arg->add_vars(LookupVar(fz_ct.arguments[5]));
|
||||
arg->add_coeffs(-1);
|
||||
}
|
||||
} else {
|
||||
LOG(FATAL) << " Not supported " << fz_ct.type;
|
||||
}
|
||||
}
|
||||
} // NOLINT(readability/fn_size)
|
||||
|
||||
void CpModelProtoWithMapping::FillReifOrImpliedConstraint(
|
||||
const fz::Constraint& fz_ct, ConstraintProto* ct) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
predicate ortools_network_flow(array [int] of int: arc,
|
||||
array [int] of int: balance,
|
||||
int: base_node,
|
||||
array [int] of var int: flow);
|
||||
|
||||
predicate fzn_network_flow(array [int,int] of int: arc,
|
||||
array [int] of int: balance,
|
||||
array [int] of var int: flow) =
|
||||
ortools_network_flow(array1d(arc),balance,flow);
|
||||
ortools_network_flow(array1d(arc), balance, min(index_set(balance)), flow);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
predicate ortools_network_flow_cost(array [int] of int: arc,
|
||||
array [int] of int: balance,
|
||||
array [int] of int: weight,
|
||||
int: base_node,
|
||||
array [int] of var int: flow,
|
||||
array [int] of int: weight,
|
||||
var int: cost);
|
||||
|
||||
predicate fzn_network_flow_cost(array [int,int] of int: arc,
|
||||
@@ -9,4 +10,9 @@ predicate fzn_network_flow_cost(array [int,int] of int: arc,
|
||||
array [int] of int: weight,
|
||||
array [int] of var int: flow,
|
||||
var int: cost) =
|
||||
ortools_network_flow_cost(array1d(arc),balance,weight,flow,cost);
|
||||
ortools_network_flow_cost(array1d(arc),
|
||||
balance,
|
||||
min(index_set(balance)),
|
||||
flow,
|
||||
weight,
|
||||
cost);
|
||||
|
||||
Reference in New Issue
Block a user