00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <cstdio>
00027
00028 #include "base/commandlineflags.h"
00029 #include "base/commandlineflags.h"
00030 #include "base/integral_types.h"
00031 #include "base/logging.h"
00032 #include "base/scoped_ptr.h"
00033 #include "base/stringprintf.h"
00034 #include "constraint_solver/constraint_solver.h"
00035
00036 DEFINE_bool(print, false, "If true, print the minimal solution.");
00037 DEFINE_int32(size, 0,
00038 "Size of the problem. If equal to 0, will test several increasing sizes.");
00039
00040 static const int kBestSolutions[] = {
00041 0, 1, 3, 6, 11, 17, 25, 34, 44, 55, 72, 85,
00042
00043 106, 127, 151, 177, 199, 216, 246
00044 };
00045
00046 static const int kKnownSolutions = 19;
00047
00048 namespace operations_research {
00049
00050 void GolombRuler(int size) {
00051 CHECK_GE(size, 1);
00052 Solver s("golomb");
00053
00054
00055 std::vector<IntVar*> ticks(size);
00056 ticks[0] = s.MakeIntConst(0);
00057 const int64 max = 1 + size * size * size;
00058 for (int i = 1; i < size; ++i) {
00059 ticks[i] = s.MakeIntVar(1, max, StringPrintf("X%02d", i));
00060 }
00061 std::vector<IntVar*> diffs;
00062 for (int i = 0; i < size; ++i) {
00063 for (int j = i + 1; j < size; ++j) {
00064 IntVar* const diff = s.MakeDifference(ticks[j], ticks[i])->Var();
00065 diffs.push_back(diff);
00066 diff->SetMin(1);
00067 }
00068 }
00069 s.AddConstraint(s.MakeAllDifferent(diffs));
00070
00071 OptimizeVar* const length = s.MakeMinimize(ticks[size-1], 1);
00072 SolutionCollector* const collector = s.MakeLastSolutionCollector();
00073 collector->Add(ticks);
00074 DecisionBuilder* const db = s.MakePhase(ticks,
00075 Solver::CHOOSE_FIRST_UNBOUND,
00076 Solver::ASSIGN_MIN_VALUE);
00077 s.Solve(db, collector, length);
00078 CHECK_EQ(collector->solution_count(), 1);
00079 const int64 result = collector->Value(0, ticks[size-1]);
00080 const int num_failures = collector->failures(0);
00081 printf("N = %d, optimal length = %d (fails:%d)\n",
00082 size, static_cast<int>(result), num_failures);
00083 if (size - 1 < kKnownSolutions) {
00084 CHECK_EQ(result, kBestSolutions[size - 1]);
00085 }
00086 if (FLAGS_print) {
00087 for (int i = 0; i < size; ++i) {
00088 const int64 tick = collector->Value(0, ticks[i]);
00089 printf("%d ", static_cast<int>(tick));
00090 }
00091 printf("\n");
00092 }
00093 }
00094
00095 }
00096
00097 int main(int argc, char **argv) {
00098 google::ParseCommandLineFlags(&argc, &argv, true);
00099 if (FLAGS_size != 0) {
00100 operations_research::GolombRuler(FLAGS_size);
00101 } else {
00102 for (int n = 1; n < 11; ++n) {
00103 operations_research::GolombRuler(n);
00104 }
00105 }
00106 return 0;
00107 }