From 7669beb5b65d6db84e491b08000f4d0b39aa6843 Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Thu, 10 May 2012 14:24:50 +0000 Subject: [PATCH] test new GCC --- examples/tests/gcc_test.cc | 98 +++++++++++++++++++++++++++++ makefiles/Makefile.cpp.mk | 6 ++ src/constraint_solver/gcc.cc | 117 ++++++++++++++++++++++++++++++++++- 3 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 examples/tests/gcc_test.cc diff --git a/examples/tests/gcc_test.cc b/examples/tests/gcc_test.cc new file mode 100644 index 0000000000..e22693d0b6 --- /dev/null +++ b/examples/tests/gcc_test.cc @@ -0,0 +1,98 @@ +// Copyright 2011-2012 Google +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "base/hash.h" +#include "base/map-util.h" +#include "base/stl_util.h" +#include "base/random.h" +#include "constraint_solver/constraint_solveri.h" +#include "constraint_solver/constraint_solver.h" + +DEFINE_int32(vsize, 5, "Number of variables"); +DEFINE_int32(csize, 5, "Number of variables"); +DEFINE_int32(slack, 4, "Slack in cardinalities"); +DEFINE_int32(seed, 1, "Random seed"); + +namespace operations_research { +extern Constraint* Gcc(Solver* const solver, + const std::vector& vars, + int64 first_domain_value, + const std::vector& min_occurrences, + const std::vector& max_occurrences); + +int64 TestGcc(int vsize, int csize, int slack, int seed, bool use_gcc) { + if (vsize > csize + slack) { + LOG(INFO) << "Cannot create problem"; + return 0; + } + ACMRandom rgen(seed); // defines a random generator + + std::vector card_min(csize, 0); + std::vector card_max(csize, 0); + for (int i = 0; i< vsize - slack; ++i) { + const int index = rgen.Uniform(csize); + card_min[index]++; + card_max[index]++; + } + for (int i = 0; i < slack; ++i) { + const int index = rgen.Uniform(csize); + card_max[index]++; + } + + LOG(INFO) << (use_gcc ? "Gcc constraint:" : "Distribute constraint:"); + LOG(INFO) << " - num variables = " << vsize; + LOG(INFO) << " - num values = " << csize; + LOG(INFO) << " - slack = " << slack; + LOG(INFO) << " - seed = " << seed; + Solver solver("TestGcc"); + std::vector vars; + solver.MakeIntVarArray(vsize, 0, csize - 1, &vars); + Constraint* const gcc = use_gcc ? + Gcc(&solver, vars, 0, card_min, card_max) : + solver.MakeDistribute(vars, card_min, card_max); + solver.AddConstraint(gcc); + DecisionBuilder* const db = solver.MakePhase(vars, + Solver::CHOOSE_FIRST_UNBOUND, + Solver::ASSIGN_MIN_VALUE); + + LOG(INFO) << "Start search"; + CycleTimer t; + t.Start(); + solver.NewSearch(db); + int counter = 0; + while(solver.NextSolution()) { + counter++; + } + solver.EndSearch(); + t.Stop(); + + LOG(INFO) << "test time : " << t.GetInUsec() << " micro seconds"; + LOG(INFO) << "Found " << counter << " solutions"; + return counter; +} +} // namespace operations_research + +int main(int argc, char** argv) { + google::ParseCommandLineFlags(&argc, &argv, true); + CHECK_EQ(operations_research::TestGcc(FLAGS_vsize, + FLAGS_csize, + FLAGS_slack, + FLAGS_seed, + false), + operations_research::TestGcc(FLAGS_vsize, + FLAGS_csize, + FLAGS_slack, + FLAGS_seed, + true)); + return 0; +} diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk index 5f51714af9..f568d34021 100644 --- a/makefiles/Makefile.cpp.mk +++ b/makefiles/Makefile.cpp.mk @@ -650,6 +650,12 @@ $(OBJ_DIR)/bucket_table_test.$O:$(EX_DIR)/tests/bucket_table_test.cc $(SRC_DIR)/ $(BIN_DIR)/bucket_table_test$E: $(CP_DEPS) $(OBJ_DIR)/bucket_table_test.$O $(CCC) $(CFLAGS) $(OBJ_DIR)/bucket_table_test.$O $(CP_LNK) $(LDFLAGS) $(EXEOUT)bucket_table_test$E +$(OBJ_DIR)/gcc_test.$O:$(EX_DIR)/tests/gcc_test.cc $(SRC_DIR)/constraint_solver/constraint_solver.h + $(CCC) $(CFLAGS) -c $(EX_DIR)$Stests/gcc_test.cc $(OBJ_OUT)gcc_test.$O + +$(BIN_DIR)/gcc_test$E: $(CP_DEPS) $(OBJ_DIR)/gcc_test.$O + $(CCC) $(CFLAGS) $(OBJ_DIR)/gcc_test.$O $(CP_LNK) $(LDFLAGS) $(EXEOUT)gcc_test$E + # Linear Programming Examples $(OBJ_DIR)/strawberry_fields_with_column_generation.$O: $(EX_DIR)/cpp/strawberry_fields_with_column_generation.cc $(SRC_DIR)/linear_solver/linear_solver.h diff --git a/src/constraint_solver/gcc.cc b/src/constraint_solver/gcc.cc index 53f3c8283e..be1d745d3b 100644 --- a/src/constraint_solver/gcc.cc +++ b/src/constraint_solver/gcc.cc @@ -66,13 +66,42 @@ class GccConstraint : public Constraint { // Two elements before and after the element list will be added // with a weight of 1. PartialSum(int64 offset, - int count, + int64 count, const std::vector& elements) : offset_(offset - 3), last_value_(offset + count + 1), sum_(count + 5), ds_(count + 5) { - int i, j; + int64 i, j; + sum_[0] = 0; + sum_[1] = 1; + sum_[2] = 2; + for (i = 2; i < count + 2; i++) { + sum_[i + 1] = sum_[i] + elements[i - 2]; + } + sum_[i + 1] = sum_[i] + 1; + sum_[i + 2] = sum_[i + 1] + 1; + + i = count + 3; + j = i; + while (i > 0) { + while (sum_[i] == sum_[i-1]) { + ds_[i--] = j; + } + ds_[j] = i--; + j = ds_[j]; + } + ds_[j] = 0; + } + + PartialSum(int64 offset, + int64 count, + const std::vector& elements) : + offset_(offset - 3), + last_value_(offset + count + 1), + sum_(count + 5), + ds_(count + 5) { + int64 i, j; sum_[0] = 0; sum_[1] = 1; sum_[2] = 2; @@ -191,6 +220,57 @@ class GccConstraint : public Constraint { } } + GccConstraint(Solver* const solver, + const std::vector& vars, + bool propagate_value, + int64 first_domain_value, + int64 last_domain_value, + const std::vector& min_occurrences, + const std::vector& max_occurrences) + : Constraint(solver), + variables_(vars), + size_(vars.size()), + current_level_(1), + last_level_(0), + propagate_value_(propagate_value), + max_occurrences_(last_domain_value - first_domain_value + 1, 0), + tree_(2 * size_ + 2), + diffs_(2 * size_ + 2), + hall_(2 * size_ + 2), + stable_intervals_(2 * size_ + 2), + potential_stable_sets_(2 * size_ + 2), + new_min_(size_), + intervals_(size_), + sorted_by_min_(size_), + sorted_by_max_(size_), + bounds_(2 * size_ + 2), + active_size_(0), + lower_sum_(first_domain_value, + last_domain_value - first_domain_value + 1, + min_occurrences), + upper_sum_(first_domain_value, + last_domain_value - first_domain_value + 1, + max_occurrences) { + int64 i, range; + + range = last_domain_value - first_domain_value + 1; + + last_level_ = -1; + + if (propagate_value_) { + for(i = 0; i < range; i++) { + max_occurrences_.SetValue(solver, + i, + max_occurrences[i]); + } + } + + for(Index i(0); i < size_; i++) { + sorted_by_min_[i.value()] = &intervals_[i]; + sorted_by_max_[i.value()] = &intervals_[i]; + } + } + virtual ~GccConstraint() {} void Post() { @@ -706,5 +786,36 @@ Constraint* NewGCC(Solver* const solver, min_occurrences, max_occurrences)); } -} // namespace operations_research +Constraint* Gcc(Solver* const solver, + const std::vector& vars, + int64 first_domain_value, + const std::vector& min_occurrences, + const std::vector& max_occurrences) { + return solver->RevAlloc( + new GccConstraint( + solver, + vars, + true, + first_domain_value, + first_domain_value + min_occurrences.size(), + min_occurrences, + max_occurrences)); +} + +Constraint* Gcc(Solver* const solver, + const std::vector& vars, + int64 first_domain_value, + const std::vector& min_occurrences, + const std::vector& max_occurrences) { + return solver->RevAlloc( + new GccConstraint( + solver, + vars, + true, + first_domain_value, + first_domain_value + min_occurrences.size(), + min_occurrences, + max_occurrences)); +} +} // namespace operations_research