From e996af75241f54298b75e0370df09744fdace793 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Wed, 30 Dec 2015 00:08:16 +0100 Subject: [PATCH] incomplete version of the slitherlink problem --- examples/cpp/slitherlink.cc | 120 ++++++++++++++++++++++++++++++++++++ makefiles/Makefile.cpp.mk | 6 ++ 2 files changed, 126 insertions(+) create mode 100644 examples/cpp/slitherlink.cc diff --git a/examples/cpp/slitherlink.cc b/examples/cpp/slitherlink.cc new file mode 100644 index 0000000000..82c5422788 --- /dev/null +++ b/examples/cpp/slitherlink.cc @@ -0,0 +1,120 @@ +#include +#include + +#include "constraint_solver/constraint_solver.h" + +namespace operations_research { +const std::vector> data = { { 3, 2, -1, 3 }, + { -1, -1, -1, 2 }, + { 3, -1, -1, -1 }, + { 3, -1, 3, 1 } }; + +const std::vector zero_or_two = { 0, 2 }; + +void PrintSolution(const std::vector>& data, + const std::vector>& h_arcs, + const std::vector>& v_arcs) { + const int num_rows = data.size(); + const int num_columns = data[0].size(); + + for (int i = 0; i < num_rows; ++i) { + std::string first_line; + std::string second_line; + for (int j = 0; j < num_columns; ++j) { + const int h_arc = h_arcs[i][j]->Value(); + const int v_arc = v_arcs[j][i]->Value(); + const int sum = data[i][j]; + first_line += h_arc == 1 ? " -" : " "; + second_line += v_arc == 1 ? "|" : " "; + second_line += sum == -1 ? " " : StringPrintf("%d", sum).c_str(); + } + const int termination = v_arcs[num_columns][i]->Value(); + second_line += termination == 1 ? "|" : " "; + std::cout << first_line << std::endl; + std::cout << second_line << std::endl; + } + std::string last_line; + for (int j = 0; j < num_columns; ++j) { + const int h_arc = h_arcs[num_rows][j]->Value(); + last_line += h_arc == 1 ? " -" : " "; + } + std::cout << last_line << std::endl; +} + +void Solve(const std::vector>& data) { + const int num_rows = data.size(); + const int num_columns = data[0].size(); + + Solver solver("slitherlink"); + std::vector all_vars; + std::vector> h_arcs(num_rows + 1); + for (int i = 0; i < num_rows + 1; ++i) { + solver.MakeBoolVarArray( + num_columns, StringPrintf("h_arc_%i_", i), &h_arcs[i]); + all_vars.insert(all_vars.end(), h_arcs[i].begin(), h_arcs[i].end()); + } + + std::vector> v_arcs(num_columns + 1); + for (int i = 0; i < num_columns + 1; ++i) { + solver.MakeBoolVarArray( + num_rows, StringPrintf("v_arc_%i_", i), &v_arcs[i]); + all_vars.insert(all_vars.end(), v_arcs[i].begin(), v_arcs[i].end()); + } + + // Constraint on the sum of arcs. + for (int i = 0; i < num_rows; ++i) { + for (int j = 0; j < num_columns; ++j) { + const int value = data[i][j]; + if (value != -1) { + std::vector square = { h_arcs[i][j], + h_arcs[i + 1][j], + v_arcs[j][i], + v_arcs[j + 1][i] }; + solver.AddConstraint(solver.MakeSumEquality(square, value)); + } + } + } + + // Hamiltonian path: each node has a degree 0 or 2. + for (int i = 0; i < num_rows + 1; ++i) { + for (int j = 0; j < num_columns + 1; ++j) { + std::vector tmp; + if (j > 0) { + tmp.push_back(h_arcs[i][j - 1]); + } + if (j < num_columns) { + tmp.push_back(h_arcs[i][j]); + } + if (i > 0) { + tmp.push_back(v_arcs[j][i - 1]); + } + if (i < num_rows) { + tmp.push_back(v_arcs[j][i]); + } + solver.AddConstraint( + solver.MakeMemberCt(solver.MakeSum(tmp), zero_or_two)); + } + } + + // Hamiltonian path: add single path constraint. + + // Search. + DecisionBuilder* const db = + solver.MakePhase(all_vars, + Solver::CHOOSE_FIRST_UNBOUND, + Solver::ASSIGN_MAX_VALUE); + + SearchMonitor* const log = solver.MakeSearchLog(1000000); + + solver.NewSearch(db, log); + while (solver.NextSolution()) { + PrintSolution(data, h_arcs, v_arcs); + } + solver.EndSearch(); +} +} // namespace operations_research + +int main() { + operations_research::Solve(operations_research::data); + return 0; +} diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk index 8c3ce25474..456e20c839 100644 --- a/makefiles/Makefile.cpp.mk +++ b/makefiles/Makefile.cpp.mk @@ -1352,6 +1352,12 @@ $(OBJ_DIR)/pdptw.$O: $(EX_DIR)/cpp/pdptw.cc $(SRC_DIR)/constraint_solver/constra $(BIN_DIR)/pdptw$E: $(DYNAMIC_ROUTING_DEPS) $(OBJ_DIR)/pdptw.$O $(CCC) $(CFLAGS) $(OBJ_DIR)/pdptw.$O $(DYNAMIC_ROUTING_LNK) $(DYNAMIC_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Spdptw$E +$(OBJ_DIR)/slitherlink.$O:$(EX_DIR)/cpp/slitherlink.cc $(SRC_DIR)/constraint_solver/constraint_solver.h + $(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/slitherlink.cc $(OBJ_OUT)$(OBJ_DIR)$Sslitherlink.$O + +$(BIN_DIR)/slitherlink$E: $(DYNAMIC_CP_DEPS) $(OBJ_DIR)/slitherlink.$O + $(CCC) $(CFLAGS) $(OBJ_DIR)/slitherlink.$O $(DYNAMIC_CP_LNK) $(DYNAMIC_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Sslitherlink$E + $(OBJ_DIR)/sports_scheduling.$O:$(EX_DIR)/cpp/sports_scheduling.cc $(SRC_DIR)/constraint_solver/constraint_solver.h $(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/sports_scheduling.cc $(OBJ_OUT)$(OBJ_DIR)$Ssports_scheduling.$O