Files
ortools-clone/examples/tests/gcc_test.cc

146 lines
5.4 KiB
C++

// 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"
#include "util/string_array.h"
DEFINE_int32(vars, 3, "Number of variables");
DEFINE_int32(values, 5, "Number of values");
DEFINE_int32(slack, 1, "Slack in cardinalities");
DEFINE_int32(seed, 1, "Random seed");
DEFINE_int32(offset, 0, "Min value of variables");
namespace operations_research {
extern Constraint* MakeGcc(Solver* const solver,
const std::vector<IntVar*>& vars,
int64 first_domain_value,
const std::vector<int>& min_occurrences,
const std::vector<int>& max_occurrences);
extern Constraint* MakeSoftGcc(Solver* const solver,
const std::vector<IntVar*>& vars,
int64 min_value,
const std::vector<int>& card_mins,
const std::vector<int>& card_max,
IntVar* const violation_var);
static const char* kConstraintName[] = { "Distribute", "Gcc", "SoftGcc" };
int64 TestGcc(int num_vars,
int num_values,
int slack,
int seed,
int type,
int offset) {
ACMRandom rgen(seed); // defines a random generator
std::vector<int> card_min(num_values, 0);
std::vector<int> card_max(num_values, 0);
std::vector<int> values(num_values);
for (int i = 0; i< num_vars - slack; ++i) {
const int index = rgen.Uniform(num_values);
card_min[index]++;
card_max[index]++;
}
for (int i = 0; i < num_values; ++i) {
values[i] = offset + i;
}
for (int i = 0; i < 2 * slack; ++i) {
card_max[rgen.Uniform(num_values)]++;
}
LOG(INFO) << kConstraintName[type] << " constraint";
LOG(INFO) << " - num variables = " << num_vars;
LOG(INFO) << " - num values = " << num_values;
LOG(INFO) << " - slack = " << slack;
LOG(INFO) << " - seed = " << seed;
LOG(INFO) << " - min_cards = [" << IntVectorToString(card_min, " ") << "]";
LOG(INFO) << " - max_cards = [" << IntVectorToString(card_max, " ") << "]";
Solver solver("TestGcc");
std::vector<IntVar*> vars;
solver.MakeIntVarArray(num_vars, offset, offset + num_values - 1, "v", &vars);
switch (type) {
case 0:
solver.AddConstraint(
solver.MakeDistribute(vars, values, card_min, card_max));
break;
case 1:
solver.AddConstraint(MakeGcc(&solver, vars, offset, card_min, card_max));
break;
case 2:
solver.AddConstraint(MakeSoftGcc(&solver,
vars,
offset,
card_min,
card_max,
solver.MakeIntConst(0)));
break;
default:
LOG(FATAL) << "Constraint type not recognized";
}
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) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
const int dis = operations_research::TestGcc(FLAGS_vars,
FLAGS_values,
FLAGS_slack,
FLAGS_seed,
0,
FLAGS_offset);
const int gcc = operations_research::TestGcc(FLAGS_vars,
FLAGS_values,
FLAGS_slack,
FLAGS_seed,
1,
FLAGS_offset);
const int soft = operations_research::TestGcc(FLAGS_vars,
FLAGS_values,
FLAGS_slack,
FLAGS_seed,
2, FLAGS_offset);
if (gcc != dis && gcc != soft && dis == soft) {
LOG(INFO) << "Problem with vars = " << FLAGS_vars
<< ", and values = " << FLAGS_values
<< ", seed = " << FLAGS_seed
<< ", slack = " << FLAGS_slack;
}
return 0;
}