NULL -> nullptr

This commit is contained in:
Laurent Perron
2022-02-15 17:58:24 +01:00
parent 921db208ba
commit d14eb216cd
5 changed files with 74 additions and 46 deletions

View File

@@ -22,6 +22,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "ortools/base/map_util.h"
#include "ortools/base/stl_util.h"
#include "ortools/util/logging.h"
@@ -761,7 +762,7 @@ int Argument::Size() const {
// ----- Variable -----
Variable::Variable(const std::string& name_, const Domain& domain_,
Variable::Variable(absl::string_view name_, const Domain& domain_,
bool temporary_)
: name(name_), domain(domain_), temporary(temporary_), active(true) {
if (!domain.is_interval) {
@@ -769,7 +770,7 @@ Variable::Variable(const std::string& name_, const Domain& domain_,
}
}
bool Variable::Merge(const std::string& other_name, const Domain& other_domain,
bool Variable::Merge(absl::string_view other_name, const Domain& other_domain,
bool other_temporary) {
if (temporary && !other_temporary) {
temporary = false;
@@ -834,7 +835,7 @@ Annotation Annotation::AnnotationList(std::vector<Annotation> list) {
return result;
}
Annotation Annotation::Identifier(const std::string& id) {
Annotation Annotation::Identifier(absl::string_view id) {
Annotation result;
result.type = IDENTIFIER;
result.interval_min = 0;
@@ -843,7 +844,7 @@ Annotation Annotation::Identifier(const std::string& id) {
return result;
}
Annotation Annotation::FunctionCallWithArguments(const std::string& id,
Annotation Annotation::FunctionCallWithArguments(absl::string_view id,
std::vector<Annotation> args) {
Annotation result;
result.type = FUNCTION_CALL;
@@ -854,7 +855,7 @@ Annotation Annotation::FunctionCallWithArguments(const std::string& id,
return result;
}
Annotation Annotation::FunctionCall(const std::string& id) {
Annotation Annotation::FunctionCall(absl::string_view id) {
Annotation result;
result.type = FUNCTION_CALL;
result.interval_min = 0;
@@ -896,7 +897,7 @@ Annotation Annotation::VarRefArray(std::vector<Variable*> variables) {
return result;
}
Annotation Annotation::String(const std::string& str) {
Annotation Annotation::String(absl::string_view str) {
Annotation result;
result.type = STRING_VALUE;
result.interval_min = 0;
@@ -957,7 +958,7 @@ std::string SolutionOutputSpecs::Bounds::DebugString() const {
}
SolutionOutputSpecs SolutionOutputSpecs::SingleVariable(
const std::string& name, Variable* variable, bool display_as_boolean) {
absl::string_view name, Variable* variable, bool display_as_boolean) {
SolutionOutputSpecs result;
result.name = name;
result.variable = variable;
@@ -966,7 +967,7 @@ SolutionOutputSpecs SolutionOutputSpecs::SingleVariable(
}
SolutionOutputSpecs SolutionOutputSpecs::MultiDimensionalArray(
const std::string& name, std::vector<Bounds> bounds,
absl::string_view name, std::vector<Bounds> bounds,
std::vector<Variable*> flat_variables, bool display_as_boolean) {
SolutionOutputSpecs result;
result.variable = nullptr;
@@ -1001,7 +1002,7 @@ Model::~Model() {
gtl::STLDeleteElements(&constraints_);
}
Variable* Model::AddVariable(const std::string& name, const Domain& domain,
Variable* Model::AddVariable(absl::string_view name, const Domain& domain,
bool defined) {
Variable* const var = new Variable(name, domain, defined);
variables_.push_back(var);
@@ -1023,8 +1024,8 @@ Variable* Model::AddFloatConstant(double value) {
return var;
}
void Model::AddConstraint(const std::string& id,
std::vector<Argument> arguments, bool is_domain) {
void Model::AddConstraint(absl::string_view id, std::vector<Argument> arguments,
bool is_domain) {
Constraint* const constraint =
new Constraint(id, std::move(arguments), is_domain);
constraints_.push_back(constraint);

View File

@@ -19,6 +19,7 @@
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "ortools/base/integral_types.h"
#include "ortools/base/logging.h"
#include "ortools/graph/iterators.h"
@@ -127,7 +128,7 @@ struct Variable {
// - if one variable is temporary, the name is the name of the other
// variable. If both variables are temporary or both variables are not
// temporary, the name is chosen arbitrarily between the two names.
bool Merge(const std::string& other_name, const Domain& other_domain,
bool Merge(absl::string_view other_name, const Domain& other_domain,
bool other_temporary);
std::string DebugString() const;
@@ -146,7 +147,7 @@ struct Variable {
private:
friend class Model;
Variable(const std::string& name_, const Domain& domain_, bool temporary_);
Variable(absl::string_view name_, const Domain& domain_, bool temporary_);
};
// An argument is either an integer value, an integer domain, a
@@ -216,7 +217,7 @@ struct Argument {
// A constraint has a type, some arguments, and a few tags. Typically, a
// Constraint is on the heap, and owned by the global Model object.
struct Constraint {
Constraint(const std::string& t, std::vector<Argument> args,
Constraint(absl::string_view t, std::vector<Argument> args,
bool strong_propag)
: type(t),
arguments(std::move(args)),
@@ -271,18 +272,18 @@ struct Annotation {
static Annotation Empty();
static Annotation AnnotationList(std::vector<Annotation> list);
static Annotation Identifier(const std::string& id);
static Annotation FunctionCallWithArguments(const std::string& id,
static Annotation Identifier(absl::string_view id);
static Annotation FunctionCallWithArguments(absl::string_view id,
std::vector<Annotation> args);
static Annotation FunctionCall(const std::string& id);
static Annotation FunctionCall(absl::string_view id);
static Annotation Interval(int64_t interval_min, int64_t interval_max);
static Annotation IntegerValue(int64_t value);
static Annotation VarRef(Variable* const var);
static Annotation VarRefArray(std::vector<Variable*> variables);
static Annotation String(const std::string& str);
static Annotation String(absl::string_view str);
std::string DebugString() const;
bool IsFunctionCallWithIdentifier(const std::string& identifier) const {
bool IsFunctionCallWithIdentifier(absl::string_view identifier) const {
return type == FUNCTION_CALL && id == identifier;
}
// Copy all the variable references contained in this annotation (and its
@@ -311,14 +312,14 @@ struct SolutionOutputSpecs {
};
// Will output: name = <variable value>.
static SolutionOutputSpecs SingleVariable(const std::string& name,
static SolutionOutputSpecs SingleVariable(absl::string_view name,
Variable* variable,
bool display_as_boolean);
// Will output (for example):
// name = array2d(min1..max1, min2..max2, [list of variable values])
// for a 2d array (bounds.size() == 2).
static SolutionOutputSpecs MultiDimensionalArray(
const std::string& name, std::vector<Bounds> bounds,
absl::string_view name, std::vector<Bounds> bounds,
std::vector<Variable*> flat_variables, bool display_as_boolean);
// Empty output.
static SolutionOutputSpecs VoidOutput();
@@ -336,7 +337,7 @@ struct SolutionOutputSpecs {
class Model {
public:
explicit Model(const std::string& name)
explicit Model(absl::string_view name)
: name_(name), objective_(nullptr), maximize_(true) {}
~Model();
@@ -344,12 +345,12 @@ class Model {
// The objects returned by AddVariable(), AddConstant(), and AddConstraint()
// are owned by the model and will remain live for its lifetime.
Variable* AddVariable(const std::string& name, const Domain& domain,
Variable* AddVariable(absl::string_view name, const Domain& domain,
bool defined);
Variable* AddConstant(int64_t value);
Variable* AddFloatConstant(double value);
// Creates and add a constraint to the model.
void AddConstraint(const std::string& id, std::vector<Argument> arguments,
void AddConstraint(absl::string_view id, std::vector<Argument> arguments,
bool is_domain);
void AddConstraint(const std::string& id, std::vector<Argument> arguments);
void AddOutput(SolutionOutputSpecs output);

View File

@@ -68,6 +68,7 @@ cc_library(
"//ortools/linear_solver:scip_helper_macros",
"//ortools/linear_solver:scip_with_glop",
"//ortools/port:proto_utils",
"//ortools/util:status_macros",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status",

View File

@@ -40,6 +40,7 @@
#include "ortools/gscip/legacy_scip_params.h"
#include "ortools/linear_solver/scip_helper_macros.h"
#include "ortools/port/proto_utils.h"
#include "ortools/util/status_macros.h"
#include "scip/cons_linear.h"
#include "scip/cons_quadratic.h"
#include "scip/scip.h"
@@ -326,8 +327,8 @@ absl::StatusOr<SCIP_VAR*> GScip::AddVariable(
double lb, double ub, double obj_coef, GScipVarType var_type,
const std::string& var_name, const GScipVariableOptions& options) {
SCIP_VAR* var = nullptr;
lb = ScipInfClamp(lb);
ub = ScipInfClamp(ub);
OR_ASSIGN_OR_RETURN3(lb, ScipInfClamp(lb), _ << "invalid lower bound");
OR_ASSIGN_OR_RETURN3(ub, ScipInfClamp(ub), _ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPcreateVarBasic(scip_, /*var=*/&var,
/*name=*/var_name.c_str(),
/*lb=*/lb, /*ub=*/ub,
@@ -360,11 +361,15 @@ absl::StatusOr<SCIP_CONS*> GScip::AddLinearConstraint(
SCIP_CONS* constraint = nullptr;
RETURN_ERROR_UNLESS(range.variables.size() == range.coefficients.size())
<< "Error adding constraint: " << name << ".";
OR_ASSIGN_OR_RETURN3(const double lb, ScipInfClamp(range.lower_bound),
_ << "invalid lower bound");
OR_ASSIGN_OR_RETURN3(const double ub, ScipInfClamp(range.upper_bound),
_ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPcreateConsLinear(
scip_, &constraint, name.c_str(), range.variables.size(),
const_cast<SCIP_VAR**>(range.variables.data()),
const_cast<double*>(range.coefficients.data()),
ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
/*lhs=*/lb, /*rhs=*/ub,
/*initial=*/options.initial,
/*separate=*/options.separate,
/*enforce=*/options.enforce,
@@ -392,6 +397,10 @@ absl::StatusOr<SCIP_CONS*> GScip::AddQuadraticConstraint(
<< "Error adding quadratic constraint: " << name << " in quadratic term.";
RETURN_ERROR_UNLESS(num_quad_vars == range.quadratic_coefficients.size())
<< "Error adding quadratic constraint: " << name << " in quadratic term.";
OR_ASSIGN_OR_RETURN3(const double lb, ScipInfClamp(range.lower_bound),
_ << "invalid lower bound");
OR_ASSIGN_OR_RETURN3(const double ub, ScipInfClamp(range.upper_bound),
_ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPcreateConsQuadratic(
scip_, &constraint, name.c_str(), num_lin_vars,
const_cast<SCIP_Var**>(range.linear_variables.data()),
@@ -399,7 +408,7 @@ absl::StatusOr<SCIP_CONS*> GScip::AddQuadraticConstraint(
const_cast<SCIP_Var**>(range.quadratic_variables1.data()),
const_cast<SCIP_Var**>(range.quadratic_variables2.data()),
const_cast<double*>(range.quadratic_coefficients.data()),
ScipInfClamp(range.lower_bound), ScipInfClamp(range.upper_bound),
/*lhs=*/lb, /*rhs=*/ub,
/*initial=*/options.initial,
/*separate=*/options.separate,
/*enforce=*/options.enforce,
@@ -428,12 +437,15 @@ absl::StatusOr<SCIP_CONS*> GScip::AddIndicatorConstraint(
RETURN_ERROR_UNLESS(indicator_constraint.variables.size() ==
indicator_constraint.coefficients.size())
<< "Error adding indicator constraint: " << name << ".";
OR_ASSIGN_OR_RETURN3(const double ub,
ScipInfClamp(indicator_constraint.upper_bound),
_ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPcreateConsIndicator(
scip_, &constraint, name.c_str(), indicator,
indicator_constraint.variables.size(),
const_cast<SCIP_Var**>(indicator_constraint.variables.data()),
const_cast<double*>(indicator_constraint.coefficients.data()),
ScipInfClamp(indicator_constraint.upper_bound),
/*rhs=*/ub,
/*initial=*/options.initial,
/*separate=*/options.separate,
/*enforce=*/options.enforce,
@@ -598,13 +610,13 @@ absl::Status GScip::SetBranchingPriority(SCIP_VAR* var, int priority) {
}
absl::Status GScip::SetLb(SCIP_VAR* var, double lb) {
lb = ScipInfClamp(lb);
OR_ASSIGN_OR_RETURN3(lb, ScipInfClamp(lb), _ << "invalid lower bound");
RETURN_IF_SCIP_ERROR(SCIPchgVarLb(scip_, var, lb));
return absl::OkStatus();
}
absl::Status GScip::SetUb(SCIP_VAR* var, double ub) {
ub = ScipInfClamp(ub);
OR_ASSIGN_OR_RETURN3(ub, ScipInfClamp(ub), _ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPchgVarUb(scip_, var, ub));
return absl::OkStatus();
}
@@ -711,13 +723,13 @@ absl::string_view GScip::Name(SCIP_CONS* constraint) {
}
absl::Status GScip::SetLinearConstraintLb(SCIP_CONS* constraint, double lb) {
lb = ScipInfClamp(lb);
OR_ASSIGN_OR_RETURN3(lb, ScipInfClamp(lb), _ << "invalid lower bound");
RETURN_IF_SCIP_ERROR(SCIPchgLhsLinear(scip_, constraint, lb));
return absl::OkStatus();
}
absl::Status GScip::SetLinearConstraintUb(SCIP_CONS* constraint, double ub) {
ub = ScipInfClamp(ub);
OR_ASSIGN_OR_RETURN3(ub, ScipInfClamp(ub), _ << "invalid upper bound");
RETURN_IF_SCIP_ERROR(SCIPchgRhsLinear(scip_, constraint, ub));
return absl::OkStatus();
}
@@ -810,8 +822,10 @@ absl::StatusOr<GScipResult> GScip::Solve(
scip_, params.scip_model_filename().c_str(), "cip", FALSE));
}
if (params.has_objective_limit()) {
RETURN_IF_SCIP_ERROR(
SCIPsetObjlimit(scip_, ScipInfClamp(params.objective_limit())));
OR_ASSIGN_OR_RETURN3(const double scip_obj_limit,
ScipInfClamp(params.objective_limit()),
_ << "invalid objective_limit");
RETURN_IF_SCIP_ERROR(SCIPsetObjlimit(scip_, scip_obj_limit));
}
// Install the message handler if necessary. We do this after setting the
@@ -986,10 +1000,20 @@ absl::StatusOr<std::string> GScip::DefaultStringParamValue(
return std::string(result);
}
double GScip::ScipInfClamp(double d) {
absl::StatusOr<double> GScip::ScipInfClamp(const double d) {
const double kScipInf = ScipInf();
if (d > kScipInf) return kScipInf;
if (d < -kScipInf) return -kScipInf;
if (d == std::numeric_limits<double>::infinity()) {
return kScipInf;
}
if (d == -std::numeric_limits<double>::infinity()) {
return -kScipInf;
}
// NaN is considered finite here.
if (d >= kScipInf || d <= -kScipInf) {
return util::InvalidArgumentErrorBuilder()
<< d << " is not in SCIP's finite range: (" << -kScipInf << ", "
<< kScipInf << ")";
}
return d;
}

View File

@@ -23,8 +23,8 @@
// problem creation are thus not supported.
// * gSCIP uses std::numeric_limits<double>::infinity(), rather than SCIPs
// infinity (a default value of 1e20). Doubles with absolute value >= 1e20
// are automatically converting to std::numeric_limits<double>::infinity()
// by gSCIP. Changing the underlying SCIP's infinity is not supported.
// but < inf result in an error. Changing the underlying SCIP's infinity is
// not supported.
// * absl::Status and absl::StatusOr are used to propagate SCIP errors (and on
// a best effort basis, also filter out bad input to gSCIP functions).
//
@@ -324,10 +324,11 @@ class GScip {
// more useful.
absl::Status SetBranchingPriority(SCIP_VAR* var, int priority);
// Doubles with absolute value of at least this value are replaced by this
// value before giving them SCIP. SCIP considers values at least this large to
// be infinite. When querying gSCIP, if an absolute value exceeds ScipInf, it
// is replaced by std::numeric_limits<double>::infinity().
// Doubles with absolute value of at least this value are invalid and result
// in errors. Floating point actual infinities are replaced by this value in
// SCIP calls. SCIP considers values at least this large to be infinite. When
// querying gSCIP, if an absolute value exceeds ScipInf, it is replaced by
// std::numeric_limits<double>::infinity().
double ScipInf();
static constexpr double kDefaultScipInf = 1e20;
@@ -359,8 +360,8 @@ class GScip {
absl::Status SetParams(const GScipParameters& params,
const std::string& legacy_params);
absl::Status FreeTransform();
// Clamps d to [-ScipInf(), ScipInf()].
double ScipInfClamp(double d);
// Replaces +/- inf by +/- ScipInf(), fails when |d| is in [ScipInf(), inf).
absl::StatusOr<double> ScipInfClamp(double d);
// Returns +/- inf if |d| >= ScipInf(), otherwise returns d.
double ScipInfUnclamp(double d);