diff --git a/examples/cpp/fap_model_printer.cc b/examples/cpp/fap_model_printer.cc deleted file mode 100644 index b179203171..0000000000 --- a/examples/cpp/fap_model_printer.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2010-2018 Google LLC -// 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 "examples/cpp/fap_model_printer.h" - -#include -#include -#include -#include "ortools/base/stringprintf.h" - -namespace operations_research { - -FapModelPrinter::FapModelPrinter(const std::map& variables, - const std::vector& constraints, - const std::string& objective, - const std::vector& values) - : variables_(variables), - constraints_(constraints), - objective_(objective), - values_(values) {} - -FapModelPrinter::~FapModelPrinter() {} - -void FapModelPrinter::PrintFapVariables() { - LOG(INFO) << "Variable File:"; - for (const auto& it : variables_) { - std::string domain = "{"; - for (const int value : it.second.domain) { - StringAppendF(&domain, "%d ", value); - } - domain.append("}"); - - std::string hard = " "; - if (it.second.hard) { - hard = " hard"; - } - - LOG(INFO) << "Variable " << StringPrintf("%3d: ", it.first) - << StringPrintf("(degree: %2d) ", it.second.degree) - << StringPrintf("%3d", it.second.domain_index) - << StringPrintf("%3d", it.second.initial_position) - << StringPrintf("%3d", it.second.mobility_index) - << StringPrintf("%8d", it.second.mobility_cost) - << StringPrintf(" (%2d) ", it.second.domain_size) << domain - << hard; - } -} - -void FapModelPrinter::PrintFapConstraints() { - LOG(INFO) << "Constraint File:"; - for (const FapConstraint& ct : constraints_) { - std::string hard = " "; - if (ct.hard) { - hard = " hard"; - } - - LOG(INFO) << StringPrintf("%3d ", ct.variable1) - << StringPrintf("%3d ", ct.variable2) << ct.type << " " - << ct.operation << " " << StringPrintf("%3d", ct.value) - << StringPrintf("%3d", ct.weight_index) - << StringPrintf("%8d", ct.weight_cost) << hard; - } -} - -void FapModelPrinter::PrintFapObjective() { - LOG(INFO) << "Objective: " << objective_; -} - -void FapModelPrinter::PrintFapValues() { - LOG(INFO) << StringPrintf("Values(%d): ", static_cast(values_.size())); - std::string domain = " "; - for (const int value : values_) { - StringAppendF(&domain, "%d ", value); - } - LOG(INFO) << domain; -} - -} // namespace operations_research diff --git a/examples/cpp/fap_model_printer.h b/examples/cpp/fap_model_printer.h index 09764a35af..b7eb997312 100644 --- a/examples/cpp/fap_model_printer.h +++ b/examples/cpp/fap_model_printer.h @@ -20,9 +20,11 @@ #define OR_TOOLS_EXAMPLES_FAP_MODEL_PRINTER_H_ #include +#include #include #include "examples/cpp/fap_parser.h" +#include "ortools/base/stringprintf.h" namespace operations_research { @@ -47,5 +49,70 @@ class FapModelPrinter { DISALLOW_COPY_AND_ASSIGN(FapModelPrinter); }; +FapModelPrinter::FapModelPrinter(const std::map& variables, + const std::vector& constraints, + const std::string& objective, + const std::vector& values) + : variables_(variables), + constraints_(constraints), + objective_(objective), + values_(values) {} + +FapModelPrinter::~FapModelPrinter() {} + +void FapModelPrinter::PrintFapVariables() { + LOG(INFO) << "Variable File:"; + for (const auto& it : variables_) { + std::string domain = "{"; + for (const int value : it.second.domain) { + StringAppendF(&domain, "%d ", value); + } + domain.append("}"); + + std::string hard = " "; + if (it.second.hard) { + hard = " hard"; + } + + LOG(INFO) << "Variable " << StringPrintf("%3d: ", it.first) + << StringPrintf("(degree: %2d) ", it.second.degree) + << StringPrintf("%3d", it.second.domain_index) + << StringPrintf("%3d", it.second.initial_position) + << StringPrintf("%3d", it.second.mobility_index) + << StringPrintf("%8d", it.second.mobility_cost) + << StringPrintf(" (%2d) ", it.second.domain_size) << domain + << hard; + } +} + +void FapModelPrinter::PrintFapConstraints() { + LOG(INFO) << "Constraint File:"; + for (const FapConstraint& ct : constraints_) { + std::string hard = " "; + if (ct.hard) { + hard = " hard"; + } + + LOG(INFO) << StringPrintf("%3d ", ct.variable1) + << StringPrintf("%3d ", ct.variable2) << ct.type << " " + << ct.operation << " " << StringPrintf("%3d", ct.value) + << StringPrintf("%3d", ct.weight_index) + << StringPrintf("%8d", ct.weight_cost) << hard; + } +} + +void FapModelPrinter::PrintFapObjective() { + LOG(INFO) << "Objective: " << objective_; +} + +void FapModelPrinter::PrintFapValues() { + LOG(INFO) << StringPrintf("Values(%d): ", static_cast(values_.size())); + std::string domain = " "; + for (const int value : values_) { + StringAppendF(&domain, "%d ", value); + } + LOG(INFO) << domain; +} + } // namespace operations_research #endif // OR_TOOLS_EXAMPLES_FAP_MODEL_PRINTER_H_ diff --git a/examples/cpp/fap_parser.cc b/examples/cpp/fap_parser.cc deleted file mode 100644 index c3f9e01622..0000000000 --- a/examples/cpp/fap_parser.cc +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2010-2018 Google LLC -// 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 "examples/cpp/fap_parser.h" -#include -#include -#include -#include "ortools/base/file.h" -#include "ortools/base/map_util.h" -#include "ortools/base/split.h" - -namespace operations_research { - -void ParseFileByLines(const std::string& filename, - std::vector* lines) { - CHECK(lines != nullptr); - std::string result; - CHECK_OK(file::GetContents(filename, &result, file::Defaults())); - *lines = absl::StrSplit(result, '\n', absl::SkipEmpty()); -} - -// VariableParser Implementation -VariableParser::VariableParser(const std::string& data_directory) - : filename_(data_directory + "/var.txt") {} - -VariableParser::~VariableParser() {} - -void VariableParser::Parse() { - std::vector lines; - ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { - std::vector tokens = - absl::StrSplit(line, ' ', absl::SkipEmpty()); - if (tokens.empty()) { - continue; - } - CHECK_GE(tokens.size(), 2); - - FapVariable variable; - variable.domain_index = atoi32(tokens[1].c_str()); - if (tokens.size() > 3) { - variable.initial_position = atoi32(tokens[2].c_str()); - variable.mobility_index = atoi32(tokens[3].c_str()); - } - gtl::InsertOrUpdate(&variables_, atoi32(tokens[0].c_str()), variable); - } -} - -// DomainParser Implementation -DomainParser::DomainParser(const std::string& data_directory) - : filename_(data_directory + "/dom.txt") {} - -DomainParser::~DomainParser() {} - -void DomainParser::Parse() { - std::vector lines; - ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { - std::vector tokens = - absl::StrSplit(line, ' ', absl::SkipEmpty()); - if (tokens.empty()) { - continue; - } - CHECK_GE(tokens.size(), 2); - - const int key = atoi32(tokens[0].c_str()); - - std::vector domain; - domain.clear(); - for (int i = 2; i < tokens.size(); ++i) { - domain.push_back(atoi32(tokens[i].c_str())); - } - - if (!domain.empty()) { - gtl::InsertOrUpdate(&domains_, key, domain); - } - } -} - -// ConstraintParser Implementation -ConstraintParser::ConstraintParser(const std::string& data_directory) - : filename_(data_directory + "/ctr.txt") {} - -ConstraintParser::~ConstraintParser() {} - -void ConstraintParser::Parse() { - std::vector lines; - ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { - std::vector tokens = - absl::StrSplit(line, ' ', absl::SkipEmpty()); - if (tokens.empty()) { - continue; - } - CHECK_GE(tokens.size(), 5); - - FapConstraint constraint; - constraint.variable1 = atoi32(tokens[0].c_str()); - constraint.variable2 = atoi32(tokens[1].c_str()); - constraint.type = tokens[2]; - constraint.operation = tokens[3]; - constraint.value = atoi32(tokens[4].c_str()); - - if (tokens.size() > 5) { - constraint.weight_index = atoi32(tokens[5].c_str()); - } - constraints_.push_back(constraint); - } -} - -// ParametersParser Implementation -const int ParametersParser::constraint_coefficient_no_; -const int ParametersParser::variable_coefficient_no_; -const int ParametersParser::coefficient_no_; - -ParametersParser::ParametersParser(const std::string& data_directory) - : filename_(data_directory + "/cst.txt"), - objective_(""), - constraint_weights_(constraint_coefficient_no_, 0), - variable_weights_(variable_coefficient_no_, 0) {} - -ParametersParser::~ParametersParser() {} - -void ParametersParser::Parse() { - bool objective = true; - bool largest_token = false; - bool value_token = false; - bool number_token = false; - bool values_token = false; - bool coefficient = false; - std::vector coefficients; - std::vector lines; - - ParseFileByLines(filename_, &lines); - for (const std::string& line : lines) { - if (objective) { - largest_token = - largest_token || (line.find("largest") != std::string::npos); - value_token = value_token || (line.find("value") != std::string::npos); - number_token = number_token || (line.find("number") != std::string::npos); - values_token = values_token || (line.find("values") != std::string::npos); - coefficient = - coefficient || (line.find("coefficient") != std::string::npos); - } - - if (coefficient) { - CHECK_EQ(coefficient_no_, - constraint_coefficient_no_ + variable_coefficient_no_); - objective = false; - if (line.find("=") != std::string::npos) { - std::vector tokens = - absl::StrSplit(line, ' ', absl::SkipEmpty()); - CHECK_GE(tokens.size(), 3); - coefficients.push_back(atoi32(tokens[2].c_str())); - } - } - } - - if (coefficient) { - CHECK_EQ(coefficient_no_, coefficients.size()); - for (int i = 0; i < coefficient_no_; i++) { - if (i < constraint_coefficient_no_) { - constraint_weights_[i] = coefficients[i]; - } else { - variable_weights_[i - constraint_coefficient_no_] = coefficients[i]; - } - } - } - - if (largest_token && value_token) { - objective_ = "Minimize the largest assigned value."; - } else if (number_token && values_token) { - objective_ = "Minimize the number of assigned values."; - } else { - // Should not reach this point. - LOG(WARNING) << "Cannot read the objective of the instance."; - } -} - -// TODO(user): Make FindComponents linear instead of quadratic. -void FindComponents(const std::vector& constraints, - const std::map& variables, - const int maximum_variable_id, - std::unordered_map* components) { - std::vector in_component(maximum_variable_id + 1, -1); - int constraint_index = 0; - for (const FapConstraint& constraint : constraints) { - const int variable_id1 = constraint.variable1; - const int variable_id2 = constraint.variable2; - const FapVariable& variable1 = gtl::FindOrDie(variables, variable_id1); - const FapVariable& variable2 = gtl::FindOrDie(variables, variable_id2); - CHECK_LT(variable_id1, in_component.size()); - CHECK_LT(variable_id2, in_component.size()); - if (in_component[variable_id1] < 0 && in_component[variable_id2] < 0) { - // None of the variables belong to an existing component. - // Create a new one. - FapComponent component; - const int component_index = constraint_index; - gtl::InsertOrUpdate(&(component.variables), variable_id1, variable1); - gtl::InsertOrUpdate(&(component.variables), variable_id2, variable2); - in_component[variable_id1] = component_index; - in_component[variable_id2] = component_index; - component.constraints.push_back(constraint); - gtl::InsertOrUpdate(components, component_index, component); - } else if (in_component[variable_id1] >= 0 && - in_component[variable_id2] < 0) { - // If variable1 belongs to an existing component, variable2 should - // also be included in the same component. - const int component_index = in_component[variable_id1]; - CHECK(gtl::ContainsKey(*components, component_index)); - gtl::InsertOrUpdate(&((*components)[component_index].variables), - variable_id2, variable2); - in_component[variable_id2] = component_index; - (*components)[component_index].constraints.push_back(constraint); - } else if (in_component[variable_id1] < 0 && - in_component[variable_id2] >= 0) { - // If variable2 belongs to an existing component, variable1 should - // also be included in the same component. - const int component_index = in_component[variable_id2]; - CHECK(gtl::ContainsKey(*components, component_index)); - gtl::InsertOrUpdate(&((*components)[component_index].variables), - variable_id1, variable1); - in_component[variable_id1] = component_index; - (*components)[component_index].constraints.push_back(constraint); - } else { - // The current constraint connects two different components. - const int component_index1 = in_component[variable_id1]; - const int component_index2 = in_component[variable_id2]; - const int min_component_index = - std::min(component_index1, component_index2); - const int max_component_index = - std::max(component_index1, component_index2); - CHECK(gtl::ContainsKey(*components, min_component_index)); - CHECK(gtl::ContainsKey(*components, max_component_index)); - if (min_component_index != max_component_index) { - // Update the component_index of maximum indexed component's variables. - for (const auto& variable : - (*components)[max_component_index].variables) { - int variable_id = variable.first; - in_component[variable_id] = min_component_index; - } - // Insert all the variables of the maximum indexed component to the - // variables of the minimum indexed component. - ((*components)[min_component_index]) - .variables.insert( - ((*components)[max_component_index]).variables.begin(), - ((*components)[max_component_index]).variables.end()); - // Insert all the constraints of the maximum indexed component to the - // constraints of the minimum indexed component. - ((*components)[min_component_index]) - .constraints.insert( - ((*components)[min_component_index]).constraints.end(), - ((*components)[max_component_index]).constraints.begin(), - ((*components)[max_component_index]).constraints.end()); - (*components)[min_component_index].constraints.push_back(constraint); - // Delete the maximum indexed component from the components set. - components->erase(max_component_index); - } else { - // Both variables belong to the same component, just add the constraint. - (*components)[min_component_index].constraints.push_back(constraint); - } - } - constraint_index++; - } -} - -int EvaluateConstraintImpact(const std::map& variables, - const int max_weight_cost, - const FapConstraint constraint) { - const FapVariable& variable1 = - gtl::FindOrDie(variables, constraint.variable1); - const FapVariable& variable2 = - gtl::FindOrDie(variables, constraint.variable2); - const int degree1 = variable1.degree; - const int degree2 = variable2.degree; - const int max_degree = std::max(degree1, degree2); - const int min_degree = std::min(degree1, degree2); - const int operator_impact = - constraint.operation == "=" ? max_degree : min_degree; - const int kHardnessBias = 10; - int hardness_impact = 0; - if (constraint.hard) { - hardness_impact = max_weight_cost > 0 ? kHardnessBias * max_weight_cost : 0; - } else { - hardness_impact = constraint.weight_cost; - } - return max_degree + min_degree + operator_impact + hardness_impact; -} - -void ParseInstance(const std::string& data_directory, bool find_components, - std::map* variables, - std::vector* constraints, - std::string* objective, std::vector* frequencies, - std::unordered_map* components) { - CHECK(variables != nullptr); - CHECK(constraints != nullptr); - CHECK(objective != nullptr); - CHECK(frequencies != nullptr); - - // Parse the data files. - VariableParser var(data_directory); - var.Parse(); - *variables = var.variables(); - const int maximum_variable_id = variables->rbegin()->first; - - ConstraintParser ctr(data_directory); - ctr.Parse(); - *constraints = ctr.constraints(); - - DomainParser dom(data_directory); - dom.Parse(); - - ParametersParser cst(data_directory); - cst.Parse(); - const int maximum_weight_cost = *std::max_element( - (cst.constraint_weights()).begin(), (cst.constraint_weights()).end()); - - // Make the variables of the instance. - for (auto& it : *variables) { - it.second.domain = gtl::FindOrDie(dom.domains(), it.second.domain_index); - it.second.domain_size = it.second.domain.size(); - - if ((it.second.mobility_index == -1) || (it.second.mobility_index == 0)) { - it.second.mobility_cost = -1; - if (it.second.initial_position != -1) { - it.second.hard = true; - } - } else { - it.second.mobility_cost = - (cst.variable_weights())[it.second.mobility_index - 1]; - } - } - // Make the constraints of the instance. - for (FapConstraint& ct : *constraints) { - if ((ct.weight_index == -1) || (ct.weight_index == 0)) { - ct.weight_cost = -1; - ct.hard = true; - } else { - ct.weight_cost = (cst.constraint_weights())[ct.weight_index - 1]; - ct.hard = false; - } - ++((*variables)[ct.variable1]).degree; - ++((*variables)[ct.variable2]).degree; - } - // Make the available frequencies of the instance. - *frequencies = gtl::FindOrDie(dom.domains(), 0); - // Make the objective of the instance. - *objective = cst.objective(); - - if (find_components) { - CHECK(components != nullptr); - FindComponents(*constraints, *variables, maximum_variable_id, components); - // Evaluate each components's constraints impacts. - for (auto& component : *components) { - for (auto& constraint : component.second.constraints) { - constraint.impact = EvaluateConstraintImpact( - *variables, maximum_weight_cost, constraint); - } - } - } else { - for (FapConstraint& constraint : *constraints) { - constraint.impact = - EvaluateConstraintImpact(*variables, maximum_weight_cost, constraint); - } - } -} -} // namespace operations_research diff --git a/examples/cpp/fap_parser.h b/examples/cpp/fap_parser.h index 4c188995fb..92e50b7705 100644 --- a/examples/cpp/fap_parser.h +++ b/examples/cpp/fap_parser.h @@ -23,6 +23,7 @@ #include #include #include +#include "ortools/base/file.h" #include "ortools/base/logging.h" #include "ortools/base/map_util.h" #include "ortools/base/split.h" @@ -248,5 +249,359 @@ void ParseInstance(const std::string& data_directory, bool find_components, std::vector* constraints, std::string* objective, std::vector* frequencies, std::unordered_map* components); + +void ParseFileByLines(const std::string& filename, + std::vector* lines) { + CHECK(lines != nullptr); + std::string result; + CHECK_OK(file::GetContents(filename, &result, file::Defaults())); + *lines = absl::StrSplit(result, '\n', absl::SkipEmpty()); +} + +// VariableParser Implementation +VariableParser::VariableParser(const std::string& data_directory) + : filename_(data_directory + "/var.txt") {} + +VariableParser::~VariableParser() {} + +void VariableParser::Parse() { + std::vector lines; + ParseFileByLines(filename_, &lines); + for (const std::string& line : lines) { + std::vector tokens = + absl::StrSplit(line, ' ', absl::SkipEmpty()); + if (tokens.empty()) { + continue; + } + CHECK_GE(tokens.size(), 2); + + FapVariable variable; + variable.domain_index = atoi32(tokens[1].c_str()); + if (tokens.size() > 3) { + variable.initial_position = atoi32(tokens[2].c_str()); + variable.mobility_index = atoi32(tokens[3].c_str()); + } + gtl::InsertOrUpdate(&variables_, atoi32(tokens[0].c_str()), variable); + } +} + +// DomainParser Implementation +DomainParser::DomainParser(const std::string& data_directory) + : filename_(data_directory + "/dom.txt") {} + +DomainParser::~DomainParser() {} + +void DomainParser::Parse() { + std::vector lines; + ParseFileByLines(filename_, &lines); + for (const std::string& line : lines) { + std::vector tokens = + absl::StrSplit(line, ' ', absl::SkipEmpty()); + if (tokens.empty()) { + continue; + } + CHECK_GE(tokens.size(), 2); + + const int key = atoi32(tokens[0].c_str()); + + std::vector domain; + domain.clear(); + for (int i = 2; i < tokens.size(); ++i) { + domain.push_back(atoi32(tokens[i].c_str())); + } + + if (!domain.empty()) { + gtl::InsertOrUpdate(&domains_, key, domain); + } + } +} + +// ConstraintParser Implementation +ConstraintParser::ConstraintParser(const std::string& data_directory) + : filename_(data_directory + "/ctr.txt") {} + +ConstraintParser::~ConstraintParser() {} + +void ConstraintParser::Parse() { + std::vector lines; + ParseFileByLines(filename_, &lines); + for (const std::string& line : lines) { + std::vector tokens = + absl::StrSplit(line, ' ', absl::SkipEmpty()); + if (tokens.empty()) { + continue; + } + CHECK_GE(tokens.size(), 5); + + FapConstraint constraint; + constraint.variable1 = atoi32(tokens[0].c_str()); + constraint.variable2 = atoi32(tokens[1].c_str()); + constraint.type = tokens[2]; + constraint.operation = tokens[3]; + constraint.value = atoi32(tokens[4].c_str()); + + if (tokens.size() > 5) { + constraint.weight_index = atoi32(tokens[5].c_str()); + } + constraints_.push_back(constraint); + } +} + +// ParametersParser Implementation +const int ParametersParser::constraint_coefficient_no_; +const int ParametersParser::variable_coefficient_no_; +const int ParametersParser::coefficient_no_; + +ParametersParser::ParametersParser(const std::string& data_directory) + : filename_(data_directory + "/cst.txt"), + objective_(""), + constraint_weights_(constraint_coefficient_no_, 0), + variable_weights_(variable_coefficient_no_, 0) {} + +ParametersParser::~ParametersParser() {} + +void ParametersParser::Parse() { + bool objective = true; + bool largest_token = false; + bool value_token = false; + bool number_token = false; + bool values_token = false; + bool coefficient = false; + std::vector coefficients; + std::vector lines; + + ParseFileByLines(filename_, &lines); + for (const std::string& line : lines) { + if (objective) { + largest_token = + largest_token || (line.find("largest") != std::string::npos); + value_token = value_token || (line.find("value") != std::string::npos); + number_token = number_token || (line.find("number") != std::string::npos); + values_token = values_token || (line.find("values") != std::string::npos); + coefficient = + coefficient || (line.find("coefficient") != std::string::npos); + } + + if (coefficient) { + CHECK_EQ(coefficient_no_, + constraint_coefficient_no_ + variable_coefficient_no_); + objective = false; + if (line.find("=") != std::string::npos) { + std::vector tokens = + absl::StrSplit(line, ' ', absl::SkipEmpty()); + CHECK_GE(tokens.size(), 3); + coefficients.push_back(atoi32(tokens[2].c_str())); + } + } + } + + if (coefficient) { + CHECK_EQ(coefficient_no_, coefficients.size()); + for (int i = 0; i < coefficient_no_; i++) { + if (i < constraint_coefficient_no_) { + constraint_weights_[i] = coefficients[i]; + } else { + variable_weights_[i - constraint_coefficient_no_] = coefficients[i]; + } + } + } + + if (largest_token && value_token) { + objective_ = "Minimize the largest assigned value."; + } else if (number_token && values_token) { + objective_ = "Minimize the number of assigned values."; + } else { + // Should not reach this point. + LOG(WARNING) << "Cannot read the objective of the instance."; + } +} + +// TODO(user): Make FindComponents linear instead of quadratic. +void FindComponents(const std::vector& constraints, + const std::map& variables, + const int maximum_variable_id, + std::unordered_map* components) { + std::vector in_component(maximum_variable_id + 1, -1); + int constraint_index = 0; + for (const FapConstraint& constraint : constraints) { + const int variable_id1 = constraint.variable1; + const int variable_id2 = constraint.variable2; + const FapVariable& variable1 = gtl::FindOrDie(variables, variable_id1); + const FapVariable& variable2 = gtl::FindOrDie(variables, variable_id2); + CHECK_LT(variable_id1, in_component.size()); + CHECK_LT(variable_id2, in_component.size()); + if (in_component[variable_id1] < 0 && in_component[variable_id2] < 0) { + // None of the variables belong to an existing component. + // Create a new one. + FapComponent component; + const int component_index = constraint_index; + gtl::InsertOrUpdate(&(component.variables), variable_id1, variable1); + gtl::InsertOrUpdate(&(component.variables), variable_id2, variable2); + in_component[variable_id1] = component_index; + in_component[variable_id2] = component_index; + component.constraints.push_back(constraint); + gtl::InsertOrUpdate(components, component_index, component); + } else if (in_component[variable_id1] >= 0 && + in_component[variable_id2] < 0) { + // If variable1 belongs to an existing component, variable2 should + // also be included in the same component. + const int component_index = in_component[variable_id1]; + CHECK(gtl::ContainsKey(*components, component_index)); + gtl::InsertOrUpdate(&((*components)[component_index].variables), + variable_id2, variable2); + in_component[variable_id2] = component_index; + (*components)[component_index].constraints.push_back(constraint); + } else if (in_component[variable_id1] < 0 && + in_component[variable_id2] >= 0) { + // If variable2 belongs to an existing component, variable1 should + // also be included in the same component. + const int component_index = in_component[variable_id2]; + CHECK(gtl::ContainsKey(*components, component_index)); + gtl::InsertOrUpdate(&((*components)[component_index].variables), + variable_id1, variable1); + in_component[variable_id1] = component_index; + (*components)[component_index].constraints.push_back(constraint); + } else { + // The current constraint connects two different components. + const int component_index1 = in_component[variable_id1]; + const int component_index2 = in_component[variable_id2]; + const int min_component_index = + std::min(component_index1, component_index2); + const int max_component_index = + std::max(component_index1, component_index2); + CHECK(gtl::ContainsKey(*components, min_component_index)); + CHECK(gtl::ContainsKey(*components, max_component_index)); + if (min_component_index != max_component_index) { + // Update the component_index of maximum indexed component's variables. + for (const auto& variable : + (*components)[max_component_index].variables) { + int variable_id = variable.first; + in_component[variable_id] = min_component_index; + } + // Insert all the variables of the maximum indexed component to the + // variables of the minimum indexed component. + ((*components)[min_component_index]) + .variables.insert( + ((*components)[max_component_index]).variables.begin(), + ((*components)[max_component_index]).variables.end()); + // Insert all the constraints of the maximum indexed component to the + // constraints of the minimum indexed component. + ((*components)[min_component_index]) + .constraints.insert( + ((*components)[min_component_index]).constraints.end(), + ((*components)[max_component_index]).constraints.begin(), + ((*components)[max_component_index]).constraints.end()); + (*components)[min_component_index].constraints.push_back(constraint); + // Delete the maximum indexed component from the components set. + components->erase(max_component_index); + } else { + // Both variables belong to the same component, just add the constraint. + (*components)[min_component_index].constraints.push_back(constraint); + } + } + constraint_index++; + } +} + +int EvaluateConstraintImpact(const std::map& variables, + const int max_weight_cost, + const FapConstraint constraint) { + const FapVariable& variable1 = + gtl::FindOrDie(variables, constraint.variable1); + const FapVariable& variable2 = + gtl::FindOrDie(variables, constraint.variable2); + const int degree1 = variable1.degree; + const int degree2 = variable2.degree; + const int max_degree = std::max(degree1, degree2); + const int min_degree = std::min(degree1, degree2); + const int operator_impact = + constraint.operation == "=" ? max_degree : min_degree; + const int kHardnessBias = 10; + int hardness_impact = 0; + if (constraint.hard) { + hardness_impact = max_weight_cost > 0 ? kHardnessBias * max_weight_cost : 0; + } else { + hardness_impact = constraint.weight_cost; + } + return max_degree + min_degree + operator_impact + hardness_impact; +} + +void ParseInstance(const std::string& data_directory, bool find_components, + std::map* variables, + std::vector* constraints, + std::string* objective, std::vector* frequencies, + std::unordered_map* components) { + CHECK(variables != nullptr); + CHECK(constraints != nullptr); + CHECK(objective != nullptr); + CHECK(frequencies != nullptr); + + // Parse the data files. + VariableParser var(data_directory); + var.Parse(); + *variables = var.variables(); + const int maximum_variable_id = variables->rbegin()->first; + + ConstraintParser ctr(data_directory); + ctr.Parse(); + *constraints = ctr.constraints(); + + DomainParser dom(data_directory); + dom.Parse(); + + ParametersParser cst(data_directory); + cst.Parse(); + const int maximum_weight_cost = *std::max_element( + (cst.constraint_weights()).begin(), (cst.constraint_weights()).end()); + + // Make the variables of the instance. + for (auto& it : *variables) { + it.second.domain = gtl::FindOrDie(dom.domains(), it.second.domain_index); + it.second.domain_size = it.second.domain.size(); + + if ((it.second.mobility_index == -1) || (it.second.mobility_index == 0)) { + it.second.mobility_cost = -1; + if (it.second.initial_position != -1) { + it.second.hard = true; + } + } else { + it.second.mobility_cost = + (cst.variable_weights())[it.second.mobility_index - 1]; + } + } + // Make the constraints of the instance. + for (FapConstraint& ct : *constraints) { + if ((ct.weight_index == -1) || (ct.weight_index == 0)) { + ct.weight_cost = -1; + ct.hard = true; + } else { + ct.weight_cost = (cst.constraint_weights())[ct.weight_index - 1]; + ct.hard = false; + } + ++((*variables)[ct.variable1]).degree; + ++((*variables)[ct.variable2]).degree; + } + // Make the available frequencies of the instance. + *frequencies = gtl::FindOrDie(dom.domains(), 0); + // Make the objective of the instance. + *objective = cst.objective(); + + if (find_components) { + CHECK(components != nullptr); + FindComponents(*constraints, *variables, maximum_variable_id, components); + // Evaluate each components's constraints impacts. + for (auto& component : *components) { + for (auto& constraint : component.second.constraints) { + constraint.impact = EvaluateConstraintImpact( + *variables, maximum_weight_cost, constraint); + } + } + } else { + for (FapConstraint& constraint : *constraints) { + constraint.impact = + EvaluateConstraintImpact(*variables, maximum_weight_cost, constraint); + } + } +} } // namespace operations_research #endif // OR_TOOLS_EXAMPLES_FAP_PARSER_H_ diff --git a/examples/cpp/fap_utilities.cc b/examples/cpp/fap_utilities.cc deleted file mode 100644 index 1ad54ef355..0000000000 --- a/examples/cpp/fap_utilities.cc +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2010-2018 Google LLC -// 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 "examples/cpp/fap_utilities.h" - -#include -#include -#include - -#include "ortools/base/logging.h" -#include "ortools/base/map_util.h" -#include "ortools/base/stringprintf.h" - -namespace operations_research { - -bool CheckConstraintSatisfaction( - const std::vector& data_constraints, - const std::vector& variables, - const std::map& index_from_key) { - bool status = true; - for (const FapConstraint& ct : data_constraints) { - const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); - const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); - CHECK_LT(index1, variables.size()); - CHECK_LT(index2, variables.size()); - const int var1 = variables[index1]; - const int var2 = variables[index2]; - const int absolute_difference = abs(var1 - var2); - - if ((ct.operation == ">") && (absolute_difference <= ct.value)) { - LOG(INFO) << " Violation of contraint between variable " << ct.variable1 - << " and variable " << ct.variable2 << "."; - LOG(INFO) << " Expected |" << var1 << " - " << var2 - << "| (= " << absolute_difference << ") > " << ct.value << "."; - status = false; - } else if ((ct.operation == "=") && (absolute_difference != ct.value)) { - LOG(INFO) << " Violation of contraint between variable " << ct.variable1 - << " and variable " << ct.variable2 << "."; - LOG(INFO) << " Expected |" << var1 << " - " << var2 - << "| (= " << absolute_difference << ") = " << ct.value << "."; - status = false; - } - } - return status; -} - -bool CheckVariablePosition(const std::map& data_variables, - const std::vector& variables, - const std::map& index_from_key) { - bool status = true; - for (const auto& it : data_variables) { - const int index = gtl::FindOrDie(index_from_key, it.first); - CHECK_LT(index, variables.size()); - const int var = variables[index]; - - if (it.second.hard && (it.second.initial_position != -1) && - (var != it.second.initial_position)) { - LOG(INFO) << " Change of position of hard variable " << it.first << "."; - LOG(INFO) << " Expected " << it.second.initial_position - << " instead of given " << var << "."; - status = false; - } - } - return status; -} - -int NumberOfAssignedValues(const std::vector& variables) { - std::set assigned(variables.begin(), variables.end()); - return static_cast(assigned.size()); -} - -void PrintElapsedTime(const int64 time1, const int64 time2) { - LOG(INFO) << "End of solving process."; - LOG(INFO) << "The Solve method took " << (time2 - time1) / 1000.0 - << " seconds."; -} - -void PrintResultsHard(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const objective_var, - const std::map& data_variables, - const std::vector& data_constraints, - const std::map& index_from_key, - const std::vector& key_from_index) { - LOG(INFO) << "Printing..."; - LOG(INFO) << "Number of Solutions: " << collector->solution_count(); - for (int solution_index = 0; solution_index < collector->solution_count(); - ++solution_index) { - Assignment* const solution = collector->solution(solution_index); - std::vector results(variables.size()); - LOG(INFO) << "------------------------------------------------------------"; - LOG(INFO) << "Solution " << solution_index + 1; - LOG(INFO) << "Cost: " << solution->Value(objective_var); - for (int i = 0; i < variables.size(); ++i) { - results[i] = solution->Value(variables[i]); - LOG(INFO) << " Variable " << key_from_index[i] << ": " << results[i]; - } - if (CheckConstraintSatisfaction(data_constraints, results, - index_from_key)) { - LOG(INFO) << "All hard constraints satisfied."; - } else { - LOG(INFO) << "Warning! Hard constraint violation detected."; - } - if (CheckVariablePosition(data_variables, results, index_from_key)) { - LOG(INFO) << "All hard variables stayed unharmed."; - } else { - LOG(INFO) << "Warning! Hard variable modification detected."; - } - - LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); - LOG(INFO) << "Maximum value used: " - << *std::max_element(results.begin(), results.end()); - LOG(INFO) << " Failures: " << collector->failures(solution_index); - } - LOG(INFO) << " ============================================================"; -} - -void PrintResultsSoft(SolutionCollector* const collector, - const std::vector& variables, - IntVar* const total_cost, - const std::map& hard_variables, - const std::vector& hard_constraints, - const std::map& soft_variables, - const std::vector& soft_constraints, - const std::map& index_from_key, - const std::vector& key_from_index) { - LOG(INFO) << "Printing..."; - LOG(INFO) << "Number of Solutions: " << collector->solution_count(); - for (int solution_index = 0; solution_index < collector->solution_count(); - ++solution_index) { - Assignment* const solution = collector->solution(solution_index); - std::vector results(variables.size()); - LOG(INFO) << "------------------------------------------------------------"; - LOG(INFO) << "Solution"; - for (int i = 0; i < variables.size(); ++i) { - results[i] = solution->Value(variables[i]); - LOG(INFO) << " Variable " << key_from_index[i] << ": " << results[i]; - } - if (CheckConstraintSatisfaction(hard_constraints, results, - index_from_key)) { - LOG(INFO) << "All hard constraints satisfied."; - } else { - LOG(INFO) << "Warning! Hard constraint violation detected."; - } - if (CheckVariablePosition(hard_variables, results, index_from_key)) { - LOG(INFO) << "All hard variables stayed unharmed."; - } else { - LOG(INFO) << "Warning! Hard constraint violation detected."; - } - - if (CheckConstraintSatisfaction(soft_constraints, results, - index_from_key) && - CheckVariablePosition(soft_variables, results, index_from_key)) { - LOG(INFO) << "Problem feasible: " - "Soft constraints and soft variables satisfied."; - LOG(INFO) << " Weighted Sum: " << solution->Value(total_cost); - } else { - LOG(INFO) << "Problem unfeasible. Optimized weighted sum of violations."; - LOG(INFO) << " Weighted Sum: " << solution->Value(total_cost); - } - - LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); - LOG(INFO) << "Maximum value used: " - << *std::max_element(results.begin(), results.end()); - LOG(INFO) << " Failures: " << collector->failures(solution_index); - } - LOG(INFO) << " ============================================================"; -} - -} // namespace operations_research diff --git a/examples/cpp/fap_utilities.h b/examples/cpp/fap_utilities.h index e858877b96..fd68e59d01 100644 --- a/examples/cpp/fap_utilities.h +++ b/examples/cpp/fap_utilities.h @@ -19,10 +19,14 @@ #define OR_TOOLS_EXAMPLES_FAP_UTILITIES_H_ #include +#include #include #include "examples/cpp/fap_parser.h" #include "ortools/constraint_solver/constraint_solver.h" +#include "ortools/base/logging.h" +#include "ortools/base/map_util.h" +#include "ortools/base/stringprintf.h" namespace operations_research { @@ -65,5 +69,159 @@ void PrintResultsSoft(SolutionCollector* const collector, const std::map& index_from_key, const std::vector& key_from_index); +bool CheckConstraintSatisfaction( + const std::vector& data_constraints, + const std::vector& variables, + const std::map& index_from_key) { + bool status = true; + for (const FapConstraint& ct : data_constraints) { + const int index1 = gtl::FindOrDie(index_from_key, ct.variable1); + const int index2 = gtl::FindOrDie(index_from_key, ct.variable2); + CHECK_LT(index1, variables.size()); + CHECK_LT(index2, variables.size()); + const int var1 = variables[index1]; + const int var2 = variables[index2]; + const int absolute_difference = abs(var1 - var2); + + if ((ct.operation == ">") && (absolute_difference <= ct.value)) { + LOG(INFO) << " Violation of contraint between variable " << ct.variable1 + << " and variable " << ct.variable2 << "."; + LOG(INFO) << " Expected |" << var1 << " - " << var2 + << "| (= " << absolute_difference << ") > " << ct.value << "."; + status = false; + } else if ((ct.operation == "=") && (absolute_difference != ct.value)) { + LOG(INFO) << " Violation of contraint between variable " << ct.variable1 + << " and variable " << ct.variable2 << "."; + LOG(INFO) << " Expected |" << var1 << " - " << var2 + << "| (= " << absolute_difference << ") = " << ct.value << "."; + status = false; + } + } + return status; +} + +bool CheckVariablePosition(const std::map& data_variables, + const std::vector& variables, + const std::map& index_from_key) { + bool status = true; + for (const auto& it : data_variables) { + const int index = gtl::FindOrDie(index_from_key, it.first); + CHECK_LT(index, variables.size()); + const int var = variables[index]; + + if (it.second.hard && (it.second.initial_position != -1) && + (var != it.second.initial_position)) { + LOG(INFO) << " Change of position of hard variable " << it.first << "."; + LOG(INFO) << " Expected " << it.second.initial_position + << " instead of given " << var << "."; + status = false; + } + } + return status; +} + +int NumberOfAssignedValues(const std::vector& variables) { + std::set assigned(variables.begin(), variables.end()); + return static_cast(assigned.size()); +} + +void PrintElapsedTime(const int64 time1, const int64 time2) { + LOG(INFO) << "End of solving process."; + LOG(INFO) << "The Solve method took " << (time2 - time1) / 1000.0 + << " seconds."; +} + +void PrintResultsHard(SolutionCollector* const collector, + const std::vector& variables, + IntVar* const objective_var, + const std::map& data_variables, + const std::vector& data_constraints, + const std::map& index_from_key, + const std::vector& key_from_index) { + LOG(INFO) << "Printing..."; + LOG(INFO) << "Number of Solutions: " << collector->solution_count(); + for (int solution_index = 0; solution_index < collector->solution_count(); + ++solution_index) { + Assignment* const solution = collector->solution(solution_index); + std::vector results(variables.size()); + LOG(INFO) << "------------------------------------------------------------"; + LOG(INFO) << "Solution " << solution_index + 1; + LOG(INFO) << "Cost: " << solution->Value(objective_var); + for (int i = 0; i < variables.size(); ++i) { + results[i] = solution->Value(variables[i]); + LOG(INFO) << " Variable " << key_from_index[i] << ": " << results[i]; + } + if (CheckConstraintSatisfaction(data_constraints, results, + index_from_key)) { + LOG(INFO) << "All hard constraints satisfied."; + } else { + LOG(INFO) << "Warning! Hard constraint violation detected."; + } + if (CheckVariablePosition(data_variables, results, index_from_key)) { + LOG(INFO) << "All hard variables stayed unharmed."; + } else { + LOG(INFO) << "Warning! Hard variable modification detected."; + } + + LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); + LOG(INFO) << "Maximum value used: " + << *std::max_element(results.begin(), results.end()); + LOG(INFO) << " Failures: " << collector->failures(solution_index); + } + LOG(INFO) << " ============================================================"; +} + +void PrintResultsSoft(SolutionCollector* const collector, + const std::vector& variables, + IntVar* const total_cost, + const std::map& hard_variables, + const std::vector& hard_constraints, + const std::map& soft_variables, + const std::vector& soft_constraints, + const std::map& index_from_key, + const std::vector& key_from_index) { + LOG(INFO) << "Printing..."; + LOG(INFO) << "Number of Solutions: " << collector->solution_count(); + for (int solution_index = 0; solution_index < collector->solution_count(); + ++solution_index) { + Assignment* const solution = collector->solution(solution_index); + std::vector results(variables.size()); + LOG(INFO) << "------------------------------------------------------------"; + LOG(INFO) << "Solution"; + for (int i = 0; i < variables.size(); ++i) { + results[i] = solution->Value(variables[i]); + LOG(INFO) << " Variable " << key_from_index[i] << ": " << results[i]; + } + if (CheckConstraintSatisfaction(hard_constraints, results, + index_from_key)) { + LOG(INFO) << "All hard constraints satisfied."; + } else { + LOG(INFO) << "Warning! Hard constraint violation detected."; + } + if (CheckVariablePosition(hard_variables, results, index_from_key)) { + LOG(INFO) << "All hard variables stayed unharmed."; + } else { + LOG(INFO) << "Warning! Hard constraint violation detected."; + } + + if (CheckConstraintSatisfaction(soft_constraints, results, + index_from_key) && + CheckVariablePosition(soft_variables, results, index_from_key)) { + LOG(INFO) << "Problem feasible: " + "Soft constraints and soft variables satisfied."; + LOG(INFO) << " Weighted Sum: " << solution->Value(total_cost); + } else { + LOG(INFO) << "Problem unfeasible. Optimized weighted sum of violations."; + LOG(INFO) << " Weighted Sum: " << solution->Value(total_cost); + } + + LOG(INFO) << "Values used: " << NumberOfAssignedValues(results); + LOG(INFO) << "Maximum value used: " + << *std::max_element(results.begin(), results.end()); + LOG(INFO) << " Failures: " << collector->failures(solution_index); + } + LOG(INFO) << " ============================================================"; +} + } // namespace operations_research #endif // OR_TOOLS_EXAMPLES_FAP_UTILITIES_H_ diff --git a/makefiles/Makefile.archive.mk b/makefiles/Makefile.archive.mk index aab2d49b39..e469bd1549 100644 --- a/makefiles/Makefile.archive.mk +++ b/makefiles/Makefile.archive.mk @@ -53,11 +53,8 @@ endif # -$(DELREC) $(TEMP_ARCHIVE_DIR) .PHONY: archive_cc # Add C++ OR-Tools to archive. -archive_cc: cc $(CVRPTW_LIBS) $(DIMACS_LIBS) $(FAP_LIBS) | $(TEMP_ARCHIVE_DIR) +archive_cc: cc | $(TEMP_ARCHIVE_DIR) $(MAKE) install_cc prefix=$(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR) - $(COPY) $(CVRPTW_PATH) $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Slib - $(COPY) $(DIMACS_PATH) $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Slib - $(COPY) $(FAP_PATH) $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Slib -$(MKDIR_P) $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Sexamples$Scpp -$(COPY) $(CC_EX_PATH)$S*.h $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Sexamples$Scpp -$(COPY) $(CC_EX_PATH)$S*.cc $(TEMP_ARCHIVE_DIR)$S$(INSTALL_DIR)$Sexamples$Scpp diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk index dd0a6706d1..8b5f056545 100755 --- a/makefiles/Makefile.cpp.mk +++ b/makefiles/Makefile.cpp.mk @@ -292,41 +292,6 @@ endif ################################## ## CPP Tests/Examples/Samples ## ################################## -# Frequency Assignment Problem (FAP) challenge problem format library -FAP_LIBS = $(LIB_DIR)/$(LIB_PREFIX)fap.$L -FAP_PATH = $(subst /,$S,$(FAP_LIBS)) -FAP_DEPS = \ - $(CC_EX_DIR)/fap_model_printer.h \ - $(CC_EX_DIR)/fap_parser.h \ - $(CC_EX_DIR)/fap_utilities.h \ - $(CP_DEPS) \ - $(LP_DEPS) -FAP_LNK = $(PRE_LIB)fap$(POST_LIB) $(OR_TOOLS_LNK) -ifeq ($(PLATFORM),MACOSX) -FAP_LDFLAGS = -install_name @rpath/$(LIB_PREFIX)fap.$L # -endif -faplibs: $(FAP_LIBS) - -FAP_OBJS = \ - $(OBJ_DIR)/fap_model_printer.$O \ - $(OBJ_DIR)/fap_parser.$O \ - $(OBJ_DIR)/fap_utilities.$O - -$(FAP_LIBS): $(OR_TOOLS_LIBS) $(FAP_OBJS) | $(LIB_DIR) - $(LINK_CMD) \ - $(FAP_LDFLAGS) \ - $(LD_OUT)$(LIB_DIR)$S$(LIB_PREFIX)fap.$L \ - $(FAP_OBJS) \ - $(OR_TOOLS_LNK) \ - $(OR_TOOLS_LDFLAGS) - -# FAP examples -$(OBJ_DIR)/frequency_assignment_problem.$O: $(CC_EX_DIR)/frequency_assignment_problem.cc $(OR_TOOLS_LIBS) | $(OBJ_DIR) - $(CCC) $(CFLAGS) -c $(CC_EX_PATH)$Sfrequency_assignment_problem.cc $(OBJ_OUT)$(OBJ_DIR)$Sfrequency_assignment_problem.$O - -$(BIN_DIR)/frequency_assignment_problem$E: $(OBJ_DIR)/frequency_assignment_problem.$O $(FAP_LIBS) | $(BIN_DIR) - $(CCC) $(CFLAGS) $(OBJ_DIR)/frequency_assignment_problem.$O $(FAP_LNK) $(OR_TOOLS_LDFLAGS) $(EXE_OUT)$(BIN_DIR)$Sfrequency_assignment_problem$E - # Generic Command $(OBJ_DIR)/%.$O: $(TEST_DIR)/%.cc $(OR_TOOLS_LIBS) | $(OBJ_DIR) $(CCC) $(CFLAGS) -c $(TEST_PATH)$S$*.cc $(OBJ_OUT)$(OBJ_DIR)$S$*.$O diff --git a/tools/Makefile.cc.java.dotnet b/tools/Makefile.cc.java.dotnet index c45fc8b68d..c86826e162 100644 --- a/tools/Makefile.cc.java.dotnet +++ b/tools/Makefile.cc.java.dotnet @@ -69,7 +69,6 @@ ifeq ($(SYSTEM),unix) PRE_LIB = -Llib -Llib64 CBC_LNK = -lCbcSolver -lCbc -lOsiCbc -lCgl -lClpSolver -lClp -lOsiClp -lOsi -lCoinUtils OR_TOOLS_LNK = $(PRE_LIB) -lprotobuf -lglog -lgflags $(CBC_LNK) -lortools - FAP_LNK = $(PRE_LIB) -lfap -lglog -lgflags $(CBC_LNK) -lortools OBJ_OUT = -o # EXE_OUT = -o # O = .o @@ -126,7 +125,6 @@ ifeq ($(SYSTEM),win) LDFLAGS = psapi.lib ws2_32.lib LIB_PREFIX = OR_TOOLS_LNK = lib\\ortools.lib - FAP_LNK = lib\\fap.lib lib\\ortools.lib OBJ_OUT = /Fo EXE_OUT = /Fe O = .obj @@ -151,7 +149,6 @@ ifeq ($(SYSTEM),win) endif # SYSTEM == win OR_TOOLS_LIBS = $(LIB_DIR)/$(LIB_PREFIX)ortools$L -FAP_LIBS = $(LIB_DIR)/$(LIB_PREFIX)fap$L .PHONY: all all: detect cc java dotnet test @@ -313,9 +310,6 @@ $(OBJ_DIR)/%$O: $(CPP_EX_DIR)/%.cc | $(OBJ_DIR) $(BIN_DIR)/%$E: $(OBJ_DIR)/%$O $(CXX) $(CXXFLAGS) $(OBJ_DIR)$S$*$O $(OR_TOOLS_LNK) $(LDFLAGS) $(EXE_OUT)$(BIN_DIR)$S$*$E -$(BIN_DIR)/frequency_assignment_problem$E: $(OBJ_DIR)/frequency_assignment_problem$O - $(CXX) $(CXXFLAGS) $(OBJ_DIR)$Sfrequency_assignment_problem$O $(FAP_LNK) $(LDFLAGS) $(EXE_OUT)$(BIN_DIR)$Sfrequency_assignment_problem$E - .PHONY: detect_cc detect_cc: @echo CXX = $(CXX) @@ -323,7 +317,6 @@ detect_cc: @echo CXXFLAGS = $(CXXFLAGS) @echo LDFLAGS = $(LDFLAGS) @echo OR_TOOLS_LNK = $(OR_TOOLS_LNK) - @echo FAP_LNK = $(FAP_LNK) ifeq ($(SYSTEM),win) @echo off & echo( else