00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "base/commandlineflags.h"
00022 #include "base/commandlineflags.h"
00023 #include "base/integral_types.h"
00024 #include "base/logging.h"
00025 #include "base/stringprintf.h"
00026 #include "constraint_solver/constraint_solver.h"
00027
00028 DEFINE_int32(size, 0, "Size of the magic square.");
00029 DEFINE_bool(impact, false, "Use impact search.");
00030 DEFINE_int32(restart, -1, "Parameter for constant restart monitor.");
00031 DEFINE_bool(luby, false,
00032 "Use luby restart monitor instead of constant restart monitor.");
00033 DEFINE_bool(run_all_heuristics, false, "Run all heuristics.");
00034 DEFINE_int32(heuristics_period, 200, "Frequency to run all heuristics.");
00035 DEFINE_int32(choose_var_strategy, 0,
00036 "Selection strategy for variable: 0 = max sum impact, "
00037 "1 = max average impact, "
00038 "2 = max individual impact.");
00039 DEFINE_bool(select_max_impact_value, false,
00040 "Select the value with max impact instead of min impact.");
00041 DEFINE_double(restart_log_size, -1.0,
00042 "Threshold for automatic restarting the search in default"
00043 " phase.");
00044 DEFINE_bool(verbose_impact, false, "Verbose output of impact search.");
00045 DEFINE_bool(use_nogoods, false, "Use no goods in automatic restart.");
00046
00047 namespace operations_research {
00048
00049 void MagicSquare(int grid_size) {
00050 Solver solver("magicsquare");
00051 const int total_size = grid_size * grid_size;
00052 const int sum = grid_size * (total_size + 1) / 2;
00053
00054 std::vector<IntVar*> vars;
00055 solver.MakeIntVarArray(total_size, 1, total_size, "", &vars);
00056 solver.AddConstraint(solver.MakeAllDifferent(vars));
00057
00058
00059 std::vector<IntVar*> diag1(grid_size);
00060 std::vector<IntVar*> diag2(grid_size);
00061 for (int n = 0; n < grid_size; ++n) {
00062 std::vector<IntVar *> sub_set(grid_size);
00063
00064 for (int m = 0; m < grid_size; ++m) {
00065 sub_set[m] = vars[m + n * grid_size];
00066 }
00067 solver.AddConstraint(solver.MakeSumEquality(sub_set, sum));
00068
00069 for (int m = 0; m < grid_size; ++m) {
00070 sub_set[m] = vars[m * grid_size + n];
00071 }
00072 solver.AddConstraint(solver.MakeSumEquality(sub_set, sum));
00073 diag1[n] = vars[n + n * grid_size];
00074 diag2[n] = vars[(grid_size - 1 - n) + n * grid_size];
00075 }
00076 solver.AddConstraint(solver.MakeSumEquality(diag1, sum));
00077 solver.AddConstraint(solver.MakeSumEquality(diag2, sum));
00078
00079
00080
00081 solver.AddConstraint(solver.MakeLess(vars[grid_size - 1],
00082 vars[(grid_size - 1) * grid_size]));
00083
00084
00085 DefaultPhaseParameters parameters;
00086 parameters.run_all_heuristics = FLAGS_run_all_heuristics;
00087 parameters.heuristic_period = FLAGS_heuristics_period;
00088 parameters.restart_log_size = FLAGS_restart_log_size;
00089 parameters.display_level = FLAGS_verbose_impact ?
00090 DefaultPhaseParameters::VERBOSE :
00091 DefaultPhaseParameters::NORMAL;
00092 parameters.use_no_goods = FLAGS_use_nogoods;
00093 switch (FLAGS_choose_var_strategy) {
00094 case 0: {
00095 parameters.var_selection_schema =
00096 DefaultPhaseParameters::CHOOSE_MAX_SUM_IMPACT;
00097 break;
00098 }
00099 case 1: {
00100 parameters.var_selection_schema =
00101 DefaultPhaseParameters::CHOOSE_MAX_AVERAGE_IMPACT;
00102 break;
00103 }
00104 case 2: {
00105 parameters.var_selection_schema =
00106 DefaultPhaseParameters::CHOOSE_MAX_VALUE_IMPACT;
00107 break;
00108 }
00109 default: {
00110 LOG(FATAL) << "Should not be here";
00111 }
00112 }
00113 parameters.value_selection_schema = FLAGS_select_max_impact_value?
00114 DefaultPhaseParameters::SELECT_MAX_IMPACT:
00115 DefaultPhaseParameters::SELECT_MIN_IMPACT;
00116
00117 DecisionBuilder* const db = FLAGS_impact?
00118 solver.MakeDefaultPhase(vars, parameters):
00119 solver.MakePhase(vars,
00120 Solver::CHOOSE_FIRST_UNBOUND,
00121 Solver::ASSIGN_MIN_VALUE);
00122
00123 std::vector<SearchMonitor*> monitors;
00124 SearchMonitor* const log = solver.MakeSearchLog(100000);
00125 monitors.push_back(log);
00126 SearchMonitor* const restart = FLAGS_restart != -1?
00127 (FLAGS_luby?
00128 solver.MakeLubyRestart(FLAGS_restart):
00129 solver.MakeConstantRestart(FLAGS_restart)):
00130 NULL;
00131 if (restart) {
00132 monitors.push_back(restart);
00133 }
00134 solver.NewSearch(db, monitors);
00135 if (solver.NextSolution()) {
00136 for (int n = 0; n < grid_size; ++n) {
00137 string output;
00138 for (int m = 0; m < grid_size; ++m) {
00139 int64 v = vars[n * grid_size + m]->Value();
00140 StringAppendF(&output, "%3lld ", v);
00141 }
00142 LG << output;
00143 }
00144 LG << "";
00145 } else {
00146 LG << "No solution found!";
00147 }
00148 solver.EndSearch();
00149 }
00150
00151 }
00152
00153 int main(int argc, char **argv) {
00154 google::ParseCommandLineFlags(&argc, &argv, true);
00155 if (FLAGS_size != 0) {
00156 operations_research::MagicSquare(FLAGS_size);
00157 } else {
00158 for (int n = 3; n < 6; ++n) {
00159 operations_research::MagicSquare(n);
00160 }
00161 }
00162 return 0;
00163 }