fix examples
This commit is contained in:
@@ -43,7 +43,8 @@ void RunConstraintProgrammingExample() {
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
LOG(INFO) << "Solution" << ": x = " << x->Value() << "; y = " << y->Value()
|
||||
LOG(INFO) << "Solution"
|
||||
<< ": x = " << x->Value() << "; y = " << y->Value()
|
||||
<< "; z = " << z->Value();
|
||||
}
|
||||
solver.EndSearch();
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "absl/random/random.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "ortools/base/commandlineflags.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/map_util.h"
|
||||
@@ -549,7 +550,7 @@ class DobbleFilter : public IntVarLocalSearchFilter {
|
||||
// For each touched card, compare against all others to compute the
|
||||
// delta in term of cost. We use a bitset to avoid counting twice
|
||||
// between two cards appearing in the local search move.
|
||||
int ComputeNewCost(const std::vector<int>& touched_cards) {
|
||||
int ComputeNewCost(absl::Span<const int> touched_cards) {
|
||||
ClearBitset();
|
||||
int cost_delta = 0;
|
||||
for (int i = 0; i < touched_cards.size(); ++i) {
|
||||
|
||||
@@ -15,12 +15,18 @@
|
||||
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/graph/ebert_graph.h"
|
||||
#include "ortools/graph/max_flow.h"
|
||||
#include "ortools/graph/generic_max_flow.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
#include "ortools/graph/min_cost_flow.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
using Graph = ::util::ReverseArcListGraph<>;
|
||||
using NodeIndex = Graph::NodeIndex;
|
||||
using ArcIndex = Graph::ArcIndex;
|
||||
using CostValue = GenericMinCostFlow<Graph>::CostValue;
|
||||
using FlowQuantity = GenericMinCostFlow<Graph>::FlowQuantity;
|
||||
|
||||
// ----- Min Cost Flow -----
|
||||
|
||||
// Test on a 4x4 matrix. Example taken from
|
||||
@@ -34,8 +40,8 @@ void MinCostFlowOn4x4Matrix() {
|
||||
{125, 95, 90, 105},
|
||||
{45, 110, 95, 115}};
|
||||
const CostValue kExpectedCost = 275;
|
||||
StarGraph graph(kNumSources + kNumTargets, kNumSources * kNumTargets);
|
||||
MinCostFlow min_cost_flow(&graph);
|
||||
Graph graph(kNumSources + kNumTargets, kNumSources * kNumTargets);
|
||||
GenericMinCostFlow<Graph> min_cost_flow(&graph);
|
||||
for (NodeIndex source = 0; source < kNumSources; ++source) {
|
||||
for (NodeIndex target = 0; target < kNumTargets; ++target) {
|
||||
ArcIndex arc = graph.AddArc(source, kNumSources + target);
|
||||
@@ -66,14 +72,14 @@ void MaxFeasibleFlow() {
|
||||
const FlowQuantity kCapacity[kNumArcs] = {5, 8, 5, 3, 4, 5, 6, 6, 4};
|
||||
const FlowQuantity kExpectedFlow[kNumArcs] = {1, 1, 5, 3, 1, 1, 0, 6, 4};
|
||||
const FlowQuantity kExpectedTotalFlow = 10;
|
||||
StarGraph graph(kNumNodes, kNumArcs);
|
||||
MaxFlow max_flow(&graph, 0, kNumNodes - 1);
|
||||
Graph graph(kNumNodes, kNumArcs);
|
||||
GenericMaxFlow<Graph> max_flow(&graph, 0, kNumNodes - 1);
|
||||
for (int i = 0; i < kNumArcs; ++i) {
|
||||
ArcIndex arc = graph.AddArc(kTail[i], kHead[i]);
|
||||
max_flow.SetArcCapacity(arc, kCapacity[i]);
|
||||
}
|
||||
CHECK(max_flow.Solve());
|
||||
CHECK_EQ(MaxFlow::OPTIMAL, max_flow.status());
|
||||
CHECK_EQ(MaxFlowStatusClass::OPTIMAL, max_flow.status());
|
||||
FlowQuantity total_flow = max_flow.GetOptimalFlow();
|
||||
CHECK_EQ(total_flow, kExpectedTotalFlow);
|
||||
for (int i = 0; i < kNumArcs; ++i) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
@@ -88,6 +89,7 @@ void RunAllExamples() {
|
||||
RunIntegerProgrammingExample("GLPK");
|
||||
RunIntegerProgrammingExample("CPLEX");
|
||||
RunIntegerProgrammingExample("XPRESS");
|
||||
RunIntegerProgrammingExample("HIGHS");
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
|
||||
@@ -11,16 +11,22 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/graph/ebert_graph.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
#include "ortools/graph/linear_assignment.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
using NodeIndex = int32_t;
|
||||
using ArcIndex = int32_t;
|
||||
using CostValue = int64_t;
|
||||
using Graph = ::util::ListGraph<NodeIndex, ArcIndex>;
|
||||
|
||||
// Test assignment on a 4x4 matrix. Example taken from
|
||||
// http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1]
|
||||
// modified so the optimum solution is unique.
|
||||
@@ -34,8 +40,8 @@ void AssignmentOn4x4Matrix() {
|
||||
{45, 110, 95, 115}};
|
||||
const CostValue kExpectedCost =
|
||||
kCost[0][3] + kCost[1][2] + kCost[2][1] + kCost[3][0];
|
||||
ForwardStarGraph graph(kNumSources + kNumTargets, kNumSources * kNumTargets);
|
||||
LinearSumAssignment<ForwardStarGraph> assignment(graph, kNumSources);
|
||||
Graph graph(kNumSources + kNumTargets, kNumSources * kNumTargets);
|
||||
LinearSumAssignment<Graph, CostValue> assignment(graph, kNumSources);
|
||||
for (NodeIndex source = 0; source < kNumSources; ++source) {
|
||||
for (NodeIndex target = 0; target < kNumTargets; ++target) {
|
||||
ArcIndex arc = graph.AddArc(source, kNumSources + target);
|
||||
@@ -52,8 +58,8 @@ void AnotherAssignment() {
|
||||
std::vector<std::vector<int>> matrice(
|
||||
{{8, 7, 9, 9}, {5, 2, 7, 8}, {6, 1, 4, 9}, {2, 3, 2, 6}});
|
||||
const int kSize = matrice.size();
|
||||
ForwardStarGraph graph(2 * kSize, kSize * kSize);
|
||||
LinearSumAssignment<ForwardStarGraph> assignment(graph, kSize);
|
||||
Graph graph(2 * kSize, kSize * kSize);
|
||||
LinearSumAssignment<Graph, CostValue> assignment(graph, kSize);
|
||||
for (int i = 0; i < kSize; ++i) {
|
||||
CHECK_EQ(kSize, matrice[i].size());
|
||||
for (int j = 0; j < kSize; ++j) {
|
||||
|
||||
@@ -117,7 +117,7 @@ void RunAllExamples() {
|
||||
RunLinearProgrammingExample("GLPK_LP");
|
||||
RunLinearProgrammingExample("XPRESS_LP");
|
||||
RunLinearProgrammingExample("PDLP");
|
||||
RunLinearProgrammingExample("HIGHS");
|
||||
RunLinearProgrammingExample("HIGHS_LP");
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
|
||||
@@ -11,16 +11,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ortools/graph/max_flow.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/flags/flag.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/graph/generic_max_flow.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
using Graph = ::util::ReverseArcListGraph<>;
|
||||
using NodeIndex = Graph::NodeIndex;
|
||||
using ArcIndex = Graph::ArcIndex;
|
||||
using MaxFlowT = GenericMaxFlow<Graph>;
|
||||
using FlowQuantity = MaxFlow::FlowQuantityT;
|
||||
|
||||
void SolveMaxFlow() {
|
||||
const int num_nodes = 5;
|
||||
// Add each arc
|
||||
@@ -30,8 +37,8 @@ void SolveMaxFlow() {
|
||||
std::vector<std::pair<std::pair<NodeIndex, NodeIndex>, FlowQuantity> > arcs =
|
||||
{{{0, 1}, 20}, {{0, 2}, 30}, {{0, 3}, 10}, {{1, 2}, 40}, {{1, 4}, 30},
|
||||
{{2, 3}, 10}, {{2, 4}, 20}, {{3, 2}, 5}, {{3, 4}, 20}};
|
||||
StarGraph graph(num_nodes, arcs.size());
|
||||
MaxFlow max_flow(&graph, 0, num_nodes - 1);
|
||||
Graph graph(num_nodes, arcs.size());
|
||||
MaxFlowT max_flow(&graph, 0, num_nodes - 1);
|
||||
for (const auto& it : arcs) {
|
||||
ArcIndex arc = graph.AddArc(it.first.first, it.first.second);
|
||||
max_flow.SetArcCapacity(arc, it.second);
|
||||
@@ -42,7 +49,7 @@ void SolveMaxFlow() {
|
||||
|
||||
// Find the maximum flow between node 0 and node 4.
|
||||
max_flow.Solve();
|
||||
if (MaxFlow::OPTIMAL != max_flow.status()) {
|
||||
if (MaxFlowStatusClass::OPTIMAL != max_flow.status()) {
|
||||
LOG(FATAL) << "Solving the max flow is not optimal!";
|
||||
}
|
||||
FlowQuantity total_flow = max_flow.GetOptimalFlow();
|
||||
|
||||
@@ -41,33 +41,32 @@ void SolveMinCostFlow() {
|
||||
{{1, 3}, 4, 2}, {{1, 4}, 10, 6}, {{2, 3}, 15, 1},
|
||||
{{2, 4}, 4, 3}, {{3, 4}, 20, 2}, {{4, 2}, 5, 3}};
|
||||
|
||||
StarGraph graph(supplies.size(), arcs.size());
|
||||
MinCostFlow min_cost_flow(&graph);
|
||||
SimpleMinCostFlow min_cost_flow;
|
||||
for (const auto& it : arcs) {
|
||||
ArcIndex arc = graph.AddArc(it.nodes.first, it.nodes.second);
|
||||
min_cost_flow.SetArcCapacity(arc, it.capacity);
|
||||
min_cost_flow.SetArcUnitCost(arc, it.unit_cost);
|
||||
min_cost_flow.AddArcWithCapacityAndUnitCost(it.nodes.first, it.nodes.second,
|
||||
it.capacity, it.unit_cost);
|
||||
}
|
||||
for (const auto& it : supplies) {
|
||||
min_cost_flow.SetNodeSupply(it.first, it.second);
|
||||
}
|
||||
|
||||
LOG(INFO) << "Solving min cost flow with: " << graph.num_nodes()
|
||||
<< " nodes, and " << graph.num_arcs() << " arcs.";
|
||||
LOG(INFO) << "Solving min cost flow with: " << min_cost_flow.NumNodes()
|
||||
<< " nodes, and " << min_cost_flow.NumArcs() << " arcs.";
|
||||
|
||||
// Find the maximum flow between node 0 and node 4.
|
||||
min_cost_flow.Solve();
|
||||
if (MinCostFlow::OPTIMAL != min_cost_flow.status()) {
|
||||
const auto status = min_cost_flow.Solve();
|
||||
if (status != SimpleMinCostFlow::OPTIMAL) {
|
||||
LOG(FATAL) << "Solving the max flow is not optimal!";
|
||||
}
|
||||
FlowQuantity total_flow_cost = min_cost_flow.GetOptimalCost();
|
||||
FlowQuantity total_flow_cost = min_cost_flow.OptimalCost();
|
||||
LOG(INFO) << "Minimum cost flow: " << total_flow_cost;
|
||||
LOG(INFO) << "";
|
||||
LOG(INFO) << "Arc : Flow / Capacity / Cost";
|
||||
for (int i = 0; i < arcs.size(); ++i) {
|
||||
LOG(INFO) << graph.Tail(i) << " -> " << graph.Head(i) << ": "
|
||||
<< min_cost_flow.Flow(i) << " / " << min_cost_flow.Capacity(i)
|
||||
<< " / " << min_cost_flow.UnitCost(i);
|
||||
LOG(INFO) << min_cost_flow.Tail(i) << " -> " << min_cost_flow.Head(i)
|
||||
<< ": " << min_cost_flow.Flow(i) << " / "
|
||||
<< min_cost_flow.Capacity(i) << " / "
|
||||
<< min_cost_flow.UnitCost(i);
|
||||
}
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
@@ -30,25 +30,23 @@
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/graph/ebert_graph.h"
|
||||
#include "ortools/graph/linear_assignment.h"
|
||||
#include "ortools/util/filelineiter.h"
|
||||
|
||||
ABSL_FLAG(bool, assignment_maximize_cost, false,
|
||||
"Negate costs so a max-cost assignment is found.");
|
||||
ABSL_FLAG(bool, assignment_optimize_layout, true,
|
||||
"Optimize graph layout for speed.");
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
template <typename GraphType>
|
||||
class LinearSumAssignment;
|
||||
|
||||
template <typename GraphType>
|
||||
class DimacsAssignmentParser {
|
||||
public:
|
||||
using NodeIndex = GraphType::NodeIndex;
|
||||
using ArcIndex = GraphType::ArcIndex;
|
||||
using CostValue = LinearSumAssignment<GraphType>::CostValueT;
|
||||
|
||||
explicit DimacsAssignmentParser(absl::string_view filename)
|
||||
: filename_(filename), graph_builder_(nullptr), assignment_(nullptr) {}
|
||||
: filename_(filename), graph_(nullptr), assignment_(nullptr) {}
|
||||
|
||||
// Reads an assignment problem description from the given file in
|
||||
// DIMACS format and returns a LinearSumAssignment object representing
|
||||
@@ -95,7 +93,7 @@ class DimacsAssignmentParser {
|
||||
|
||||
ErrorTrackingState state_;
|
||||
|
||||
AnnotatedGraphBuildManager<GraphType>* graph_builder_;
|
||||
std::unique_ptr<GraphType> graph_;
|
||||
|
||||
LinearSumAssignment<GraphType>* assignment_;
|
||||
};
|
||||
@@ -122,8 +120,7 @@ void DimacsAssignmentParser<GraphType>::ParseProblemLine(
|
||||
}
|
||||
|
||||
state_.num_arcs = num_arcs;
|
||||
graph_builder_ = new AnnotatedGraphBuildManager<GraphType>(
|
||||
num_nodes, num_arcs, absl::GetFlag(FLAGS_assignment_optimize_layout));
|
||||
graph_ = std::make_unique<GraphType>(num_nodes, num_arcs);
|
||||
}
|
||||
|
||||
template <typename GraphType>
|
||||
@@ -146,7 +143,7 @@ void DimacsAssignmentParser<GraphType>::ParseNodeLine(const std::string& line) {
|
||||
|
||||
template <typename GraphType>
|
||||
void DimacsAssignmentParser<GraphType>::ParseArcLine(const std::string& line) {
|
||||
if (graph_builder_ == nullptr) {
|
||||
if (graph_ == nullptr) {
|
||||
state_.bad = true;
|
||||
state_.reason =
|
||||
"Problem specification line must precede any arc specification.";
|
||||
@@ -167,7 +164,7 @@ void DimacsAssignmentParser<GraphType>::ParseArcLine(const std::string& line) {
|
||||
state_.reason = "Syntax error in arc descriptor.";
|
||||
state_.bad_line.reset(new std::string(line));
|
||||
}
|
||||
ArcIndex arc = graph_builder_->AddArc(tail - 1, head - 1);
|
||||
ArcIndex arc = graph_->AddArc(tail - 1, head - 1);
|
||||
assignment_->SetArcCost(
|
||||
arc, absl::GetFlag(FLAGS_assignment_maximize_cost) ? -cost : cost);
|
||||
}
|
||||
@@ -241,23 +238,17 @@ LinearSumAssignment<GraphType>* DimacsAssignmentParser<GraphType>::Parse(
|
||||
*error_message = *error_message + ": \"" + *state_.bad_line + "\"";
|
||||
return nullptr;
|
||||
}
|
||||
if (graph_builder_ == nullptr) {
|
||||
if (graph_ == nullptr) {
|
||||
*error_message = "empty graph description";
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<PermutationCycleHandler<ArcIndex> > cycle_handler(
|
||||
assignment_->ArcAnnotationCycleHandler());
|
||||
GraphType* graph = graph_builder_->Graph(cycle_handler.get());
|
||||
if (graph == nullptr) {
|
||||
*error_message = "unable to create compact static graph";
|
||||
return nullptr;
|
||||
}
|
||||
assignment_->SetGraph(graph);
|
||||
graph_->Build();
|
||||
assignment_->SetGraph(graph_.get());
|
||||
*error_message = "";
|
||||
// Return a handle on the graph to the caller so the caller can free
|
||||
// the graph's memory, because the LinearSumAssignment object does
|
||||
// not take ownership of the graph and hence will not free it.
|
||||
*graph_handle = graph;
|
||||
*graph_handle = graph_.release();
|
||||
return assignment_;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ void Solve(const std::string& input, absl::string_view params_str,
|
||||
absl::StrAppend(
|
||||
&sol_string, "=obj= ",
|
||||
RoundTripDoubleFormat(convergence_information->primal_objective()),
|
||||
"\n");
|
||||
"\n");
|
||||
for (int64_t i = 0; i < result.primal_solution.size(); ++i) {
|
||||
std::string name;
|
||||
if (qp.variable_names.has_value()) {
|
||||
|
||||
@@ -21,20 +21,16 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "ortools/base/file.h"
|
||||
#include "ortools/base/helpers.h"
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/graph/ebert_graph.h"
|
||||
#include "ortools/base/options.h"
|
||||
#include "ortools/graph/linear_assignment.h"
|
||||
|
||||
namespace operations_research {
|
||||
|
||||
template <typename GraphType>
|
||||
class LinearSumAssignment;
|
||||
|
||||
// Given a LinearSumAssignment object representing an assignment problem
|
||||
// description, outputs the problem in DIMACS format in the output file.
|
||||
// For a description of the format, see
|
||||
@@ -42,13 +38,6 @@ class LinearSumAssignment;
|
||||
template <typename GraphType>
|
||||
void PrintDimacsAssignmentProblem(
|
||||
const LinearSumAssignment<GraphType>& assignment,
|
||||
const TailArrayManager<GraphType>& tail_array_manager,
|
||||
absl::string_view output_filename);
|
||||
|
||||
template <typename GraphType>
|
||||
void PrintDimacsAssignmentProblem(
|
||||
const LinearSumAssignment<GraphType>& assignment,
|
||||
const TailArrayManager<GraphType>& tail_array_manager,
|
||||
absl::string_view output_filename) {
|
||||
File* output;
|
||||
CHECK_OK(file::Open(output_filename, "w", &output, file::Defaults()));
|
||||
@@ -64,11 +53,7 @@ void PrintDimacsAssignmentProblem(
|
||||
CHECK_OK(file::WriteString(output, output_line, file::Defaults()));
|
||||
}
|
||||
|
||||
tail_array_manager.BuildTailArrayFromAdjacencyListsIfForwardGraph();
|
||||
|
||||
for (typename GraphType::ArcIterator arc_it(assignment.Graph()); arc_it.Ok();
|
||||
arc_it.Next()) {
|
||||
ArcIndex arc = arc_it.Index();
|
||||
for (const auto& arc : graph.AllForwardArcs()) {
|
||||
output_line = absl::StrFormat("a %d %d %d\n", graph.Tail(arc) + 1,
|
||||
graph.Head(arc) + 1, assignment.ArcCost(arc));
|
||||
CHECK_OK(file::WriteString(output, output_line, file::Defaults()));
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#from ortools.constraint_solver import pywrapcp
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
model = cp_model.CpModel()
|
||||
y = model.NewIntVar(0, 3, 'y')
|
||||
y == None
|
||||
|
||||
#solver = pywrapcp.Solver('my solver')
|
||||
#x = solver.IntVar(0, 3, 'var_name')
|
||||
#x == None
|
||||
Reference in New Issue
Block a user