Merge branch 'master' of https://github.com/google/or-tools
This commit is contained in:
@@ -65,7 +65,7 @@ ortoolslibs: $(OR_TOOLS_LIBS)
|
||||
CVRPTW_LIBS = $(LIB_DIR)/$(LIB_PREFIX)cvrptw_lib.$(LIB_SUFFIX)
|
||||
CVRPTW_DEPS = \
|
||||
$(EX_DIR)/cpp/cvrptw_lib.h \
|
||||
$(ROUTING_DEPS)
|
||||
$(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
CVRPTW_LNK = $(PRE_LIB)cvrptw_lib$(POST_LIB) $(OR_TOOLS_LNK)
|
||||
cvrptwlibs: $(CVRPTW_LIBS)
|
||||
|
||||
@@ -156,7 +156,7 @@ ccexe: $(CC_BINARIES)
|
||||
CVRPTW_OBJS=\
|
||||
$(OBJ_DIR)/cvrptw_lib.$O
|
||||
|
||||
$(OBJ_DIR)/cvrptw_lib.$O: $(EX_DIR)/cpp/cvrptw_lib.cc $(EX_DIR)/cpp/cvrptw_lib.h $(ROUTING_DEPS)
|
||||
$(OBJ_DIR)/cvrptw_lib.$O: $(EX_DIR)/cpp/cvrptw_lib.cc $(EX_DIR)/cpp/cvrptw_lib.h $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
$(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/cvrptw_lib.cc $(OBJ_OUT)$(OBJ_DIR)$Scvrptw_lib.$O
|
||||
|
||||
$(LIB_DIR)/$(LIB_PREFIX)cvrptw_lib.$(LIB_SUFFIX): $(CVRPTW_OBJS)
|
||||
@@ -435,7 +435,7 @@ $(OBJ_DIR)/nqueens2.$O: $(EX_DIR)/cpp/nqueens2.cc $(CP_DEPS)
|
||||
$(BIN_DIR)/nqueens2$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/nqueens2.$O
|
||||
$(CCC) $(CFLAGS) $(OBJ_DIR)/nqueens2.$O $(OR_TOOLS_LNK) $(OR_TOOLS_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Snqueens2$E
|
||||
|
||||
$(OBJ_DIR)/pdptw.$O: $(EX_DIR)/cpp/pdptw.cc $(ROUTING_DEPS)
|
||||
$(OBJ_DIR)/pdptw.$O: $(EX_DIR)/cpp/pdptw.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
$(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/pdptw.cc $(OBJ_OUT)$(OBJ_DIR)$Spdptw.$O
|
||||
|
||||
$(BIN_DIR)/pdptw$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/pdptw.$O
|
||||
@@ -465,7 +465,7 @@ $(OBJ_DIR)/sports_scheduling.$O: $(EX_DIR)/cpp/sports_scheduling.cc $(CP_DEPS)
|
||||
$(BIN_DIR)/sports_scheduling$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/sports_scheduling.$O
|
||||
$(CCC) $(CFLAGS) $(OBJ_DIR)/sports_scheduling.$O $(OR_TOOLS_LNK) $(OR_TOOLS_LD_FLAGS) $(EXE_OUT)$(BIN_DIR)$Ssports_scheduling$E
|
||||
|
||||
$(OBJ_DIR)/tsp.$O: $(EX_DIR)/cpp/tsp.cc $(ROUTING_DEPS)
|
||||
$(OBJ_DIR)/tsp.$O: $(EX_DIR)/cpp/tsp.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
$(CCC) $(CFLAGS) -c $(EX_DIR)$Scpp/tsp.cc $(OBJ_OUT)$(OBJ_DIR)$Stsp.$O
|
||||
|
||||
$(BIN_DIR)/tsp$E: $(OR_TOOLS_LIBS) $(OBJ_DIR)/tsp.$O
|
||||
|
||||
@@ -1227,7 +1227,6 @@ $(OBJ_DIR)/graph/bellman_ford.$O: \
|
||||
$(OBJ_DIR)/graph/cliques.$O: \
|
||||
$(SRC_DIR)/graph/cliques.cc \
|
||||
$(SRC_DIR)/graph/cliques.h \
|
||||
$(SRC_DIR)/base/callback.h \
|
||||
$(SRC_DIR)/base/hash.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)/graph/cliques.cc $(OBJ_OUT)$(OBJ_DIR)$Sgraph$Scliques.$O
|
||||
|
||||
@@ -1264,7 +1263,6 @@ $(OBJ_DIR)/graph/min_cost_flow.$O: \
|
||||
$(OBJ_DIR)/graph/shortestpaths.$O: \
|
||||
$(SRC_DIR)/graph/shortestpaths.cc \
|
||||
$(SRC_DIR)/graph/shortestpaths.h \
|
||||
$(SRC_DIR)/base/callback.h \
|
||||
$(SRC_DIR)/base/casts.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h \
|
||||
$(SRC_DIR)/base/hash.h \
|
||||
@@ -2280,19 +2278,6 @@ $(SRC_DIR)/linear_solver/glop_utils.h: \
|
||||
$(SRC_DIR)/linear_solver/linear_solver.h \
|
||||
$(SRC_DIR)/lp_data/lp_types.h
|
||||
|
||||
$(SRC_DIR)/linear_solver/linear_expr.h:
|
||||
|
||||
$(SRC_DIR)/linear_solver/linear_solver_ext.h: \
|
||||
$(SRC_DIR)/linear_solver/linear_solver.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h \
|
||||
$(SRC_DIR)/base/hash.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/base/macros.h \
|
||||
$(SRC_DIR)/base/sparsetable.h \
|
||||
$(SRC_DIR)/base/strutil.h \
|
||||
$(SRC_DIR)/base/timer.h
|
||||
|
||||
$(SRC_DIR)/linear_solver/linear_solver.h: \
|
||||
$(SRC_DIR)/linear_solver/linear_expr.h \
|
||||
$(GEN_DIR)/linear_solver/linear_solver.pb.h \
|
||||
@@ -2605,21 +2590,16 @@ $(SRC_DIR)/constraint_solver/constraint_solveri.h: \
|
||||
$(SRC_DIR)/constraint_solver/hybrid.h: \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h
|
||||
|
||||
$(SRC_DIR)/constraint_solver/routing_flags.h: \
|
||||
$(GEN_DIR)/constraint_solver/routing_parameters.pb.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h
|
||||
|
||||
$(SRC_DIR)/constraint_solver/routing.h: \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solveri.h \
|
||||
$(GEN_DIR)/constraint_solver/routing_parameters.pb.h \
|
||||
$(SRC_DIR)/base/adjustable_priority_queue.h \
|
||||
$(SRC_DIR)/constraint_solver/routing_types.h \
|
||||
$(SRC_DIR)/base/adjustable_priority_queue-inl.h \
|
||||
$(SRC_DIR)/base/adjustable_priority_queue.h \
|
||||
$(SRC_DIR)/base/callback.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h \
|
||||
$(SRC_DIR)/base/hash.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/int_type.h \
|
||||
$(SRC_DIR)/base/int_type_indexed_vector.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/base/macros.h \
|
||||
@@ -2627,6 +2607,10 @@ $(SRC_DIR)/constraint_solver/routing.h: \
|
||||
$(SRC_DIR)/util/sorted_interval_list.h \
|
||||
$(SRC_DIR)/graph/graph.h
|
||||
|
||||
$(SRC_DIR)/constraint_solver/routing_flags.h: \
|
||||
$(GEN_DIR)/constraint_solver/routing_parameters.pb.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h
|
||||
|
||||
$(SRC_DIR)/constraint_solver/routing_neighborhoods.h: \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solveri.h \
|
||||
@@ -2707,16 +2691,6 @@ $(OBJ_DIR)/constraint_solver/collect_variables.$O: \
|
||||
$(SRC_DIR)/base/stl_util.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/collect_variables.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Scollect_variables.$O
|
||||
|
||||
$(OBJ_DIR)/constraint_solver/constraints.$O: \
|
||||
$(SRC_DIR)/constraint_solver/constraints.cc \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solveri.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/util/saturated_arithmetic.h \
|
||||
$(SRC_DIR)/util/string_array.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraints.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraints.$O
|
||||
|
||||
$(OBJ_DIR)/constraint_solver/constraint_solver.$O: \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.cc \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
@@ -2736,6 +2710,17 @@ $(OBJ_DIR)/constraint_solver/constraint_solver.$O: \
|
||||
$(SRC_DIR)/util/tuple_set.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraint_solver.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraint_solver.$O
|
||||
|
||||
$(OBJ_DIR)/constraint_solver/constraints.$O: \
|
||||
$(SRC_DIR)/constraint_solver/constraints.cc \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solveri.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/join.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/util/saturated_arithmetic.h \
|
||||
$(SRC_DIR)/util/string_array.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)/constraint_solver/constraints.cc $(OBJ_OUT)$(OBJ_DIR)$Sconstraint_solver$Sconstraints.$O
|
||||
|
||||
$(OBJ_DIR)/constraint_solver/count_cst.$O: \
|
||||
$(SRC_DIR)/constraint_solver/count_cst.cc \
|
||||
$(SRC_DIR)/constraint_solver/constraint_solver.h \
|
||||
@@ -2933,6 +2918,7 @@ $(OBJ_DIR)/constraint_solver/local_search.$O: \
|
||||
$(SRC_DIR)/base/commandlineflags.h \
|
||||
$(SRC_DIR)/base/hash.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/join.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/base/macros.h \
|
||||
$(SRC_DIR)/base/map_util.h \
|
||||
@@ -3002,11 +2988,13 @@ $(OBJ_DIR)/constraint_solver/routing.$O: \
|
||||
$(SRC_DIR)/constraint_solver/routing.cc \
|
||||
$(GEN_DIR)/constraint_solver/model.pb.h \
|
||||
$(SRC_DIR)/constraint_solver/routing.h \
|
||||
$(SRC_DIR)/constraint_solver/routing_neighborhoods.h \
|
||||
$(SRC_DIR)/base/callback.h \
|
||||
$(SRC_DIR)/base/casts.h \
|
||||
$(SRC_DIR)/base/commandlineflags.h \
|
||||
$(SRC_DIR)/base/hash.h \
|
||||
$(SRC_DIR)/base/integral_types.h \
|
||||
$(SRC_DIR)/base/join.h \
|
||||
$(SRC_DIR)/base/logging.h \
|
||||
$(SRC_DIR)/base/map_util.h \
|
||||
$(SRC_DIR)/base/stl_util.h \
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
JAVA_ORTOOLS_LIBS= $(LIB_DIR)/com.google.ortools.jar $(LIB_DIR)/$(LIB_PREFIX)jniortools.$(JNI_LIB_EXT)
|
||||
|
||||
$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/java/constraint_solver.swig $(SRC_DIR)/constraint_solver/java/routing.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/proto.swig $(ROUTING_DEPS)
|
||||
$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/java/constraint_solver.swig $(SRC_DIR)/constraint_solver/java/routing.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/proto.swig $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
$(SWIG_BINARY) -I$(INC_DIR) -c++ -java -o $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc -package com.google.ortools.constraintsolver -module operations_research_constraint_solver -outdir $(GEN_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver $(SRC_DIR)$Sconstraint_solver$Sjava$Srouting.swig
|
||||
|
||||
$(OBJ_DIR)/swig/constraint_solver_java_wrap.$O: $(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc $(ROUTING_DEPS)
|
||||
$(OBJ_DIR)/swig/constraint_solver_java_wrap.$O: $(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc $(CP_DEPS) $(SRC_DIR)/constraint_solver/routing.h
|
||||
$(CCC) $(JNIFLAGS) $(JAVA_INC) -c $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc $(OBJ_OUT)$(OBJ_DIR)$Sswig$Sconstraint_solver_java_wrap.$O
|
||||
|
||||
$(GEN_DIR)/algorithms/knapsack_solver_java_wrap.cc: $(SRC_DIR)/algorithms/java/knapsack_solver.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/java/vector.swig $(SRC_DIR)/algorithms/knapsack_solver.h
|
||||
@@ -403,4 +403,4 @@ clean_java:
|
||||
-$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Salgorithms$S*.class
|
||||
-$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Slinearsolver$S*.class
|
||||
-$(DEL) $(OBJ_DIR)$Scom$Sgoogle$Sortools$Ssamples$S*.class
|
||||
-$(DEL) $(OBJ_DIR)$Sswig$S*java_wrap.$O
|
||||
-$(DEL) $(OBJ_DIR)$Sswig$S*java_wrap.$O
|
||||
|
||||
@@ -90,7 +90,7 @@ endif
|
||||
# Windows specific part.
|
||||
ifeq ("$(SYSTEM)","win")
|
||||
# Detect 32/64bit
|
||||
ifeq ("$(Platform)", "X64")
|
||||
ifeq ("$(Platform)", "X64") # Visual Studio 2015 64 bit
|
||||
PLATFORM = WIN64
|
||||
PTRLENGTH = 64
|
||||
CMAKE_SUFFIX = Win64
|
||||
@@ -99,13 +99,23 @@ ifeq ("$(SYSTEM)","win")
|
||||
GLPK_PLATFORM = w64
|
||||
NETPLATFORM = x64
|
||||
else
|
||||
PLATFORM = Win32
|
||||
PTRLENGTH = 32
|
||||
CMAKE_SUFFIX =
|
||||
ARCH =
|
||||
CBC_PLATFORM_PREFIX = Win32
|
||||
GLPK_PLATFORM = w32
|
||||
NETPLATFORM = x86
|
||||
ifeq ("$(Platform)", "x64") # Visual studio 2013 64 bit
|
||||
PLATFORM = WIN64
|
||||
PTRLENGTH = 64
|
||||
CMAKE_SUFFIX = Win64
|
||||
ARCH= /DARCH_K8
|
||||
CBC_PLATFORM_PREFIX = x64
|
||||
GLPK_PLATFORM = w64
|
||||
NETPLATFORM = x64
|
||||
else # Visual Studio 32 bit (soon obsolete)
|
||||
PLATFORM = Win32
|
||||
PTRLENGTH = 32
|
||||
CMAKE_SUFFIX =
|
||||
ARCH =
|
||||
CBC_PLATFORM_PREFIX = Win32
|
||||
GLPK_PLATFORM = w32
|
||||
NETPLATFORM = x86
|
||||
endif
|
||||
endif
|
||||
|
||||
# Detect visual studio version
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SVN tags of dependencies to checkout.
|
||||
|
||||
GFLAGS_TAG = 2.1.2
|
||||
PROTOBUF_TAG = 3.0.0
|
||||
PROTOBUF_TAG = 3.2.0
|
||||
CBC_TAG = 2.9.8
|
||||
SWIG_TAG = 3.0.12
|
||||
PCRE_TAG = 8.37
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# tags of dependencies to checkout.
|
||||
GFLAGS_TAG = master
|
||||
PROTOBUF_TAG = 3.0.0
|
||||
PROTOBUF_TAG = 3.2.0
|
||||
CBC_TAG = 2.9.8
|
||||
ZLIB_TAG = 1.2.11
|
||||
ZLIB_ARCHIVE_TAG = 1211
|
||||
|
||||
@@ -389,8 +389,8 @@ namespace stdext {
|
||||
template <>
|
||||
inline size_t hash_value<std::pair<int64, int64>>(
|
||||
const std::pair<int64, int64>& a) {
|
||||
PairIntHasher pairIntHasher;
|
||||
return pairIntHasher(a);
|
||||
PairInt64Hasher pairInt64Hasher;
|
||||
return pairInt64Hasher(a);
|
||||
}
|
||||
} // namespace stdext
|
||||
#endif // _MSC_VER
|
||||
|
||||
@@ -2079,8 +2079,12 @@ class CpModelLoader {
|
||||
|
||||
// Returns stored integer expression.
|
||||
IntExpr* IntegerExpression(int index) const;
|
||||
// Returns the number of stored integer expressions.
|
||||
int NumIntegerExpressions() const { return expressions_.size(); }
|
||||
// Returns stored interval variable.
|
||||
IntervalVar* IntervalVariable(int index) const;
|
||||
// Returns the number of stored interval variables.
|
||||
int NumIntervalVariables() const { return intervals_.size(); }
|
||||
|
||||
|
||||
#if !defined(SWIG)
|
||||
|
||||
@@ -1177,7 +1177,7 @@ std::function<LiteralIndex()> FirstUnassignedVarAtItsMinHeuristic(
|
||||
.Index();
|
||||
}
|
||||
}
|
||||
return kNoLiteralIndex;
|
||||
return LiteralIndex(kNoLiteralIndex);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1197,7 +1197,7 @@ std::function<LiteralIndex()> UnassignedVarWithLowestMinAtItsMinHeuristic(
|
||||
candidate_lb = lb;
|
||||
}
|
||||
}
|
||||
if (candidate == kNoIntegerVariable) return kNoLiteralIndex;
|
||||
if (candidate == kNoIntegerVariable) return LiteralIndex(kNoLiteralIndex);
|
||||
return integer_encoder
|
||||
->GetOrCreateAssociatedLiteral(
|
||||
IntegerLiteral::LowerOrEqual(candidate, candidate_lb))
|
||||
|
||||
@@ -918,7 +918,9 @@ class LiteralViews {
|
||||
explicit LiteralViews(Model* model) : model_(model) {}
|
||||
|
||||
static LiteralViews* CreateInModel(Model* model) {
|
||||
return new LiteralViews(model);
|
||||
LiteralViews* const views = new LiteralViews(model);
|
||||
model->TakeOwnership(views);
|
||||
return views;
|
||||
}
|
||||
|
||||
IntegerVariable GetIntegerView(const Literal lit) {
|
||||
|
||||
@@ -137,6 +137,7 @@ class SchedulingConstraintHelper {
|
||||
// Note that for tasks with variable durations, we don't necessarily have
|
||||
// duration-min between the the XXX-min and XXX-max value.
|
||||
IntegerValue DurationMin(int t) const;
|
||||
IntegerValue DurationMax(int t) const;
|
||||
IntegerValue StartMin(int t) const;
|
||||
IntegerValue StartMax(int t) const;
|
||||
IntegerValue EndMin(int t) const;
|
||||
@@ -240,6 +241,12 @@ inline IntegerValue SchedulingConstraintHelper::DurationMin(int t) const {
|
||||
: integer_trail_->LowerBound(duration_vars_[t]);
|
||||
}
|
||||
|
||||
inline IntegerValue SchedulingConstraintHelper::DurationMax(int t) const {
|
||||
return duration_vars_[t] == kNoIntegerVariable
|
||||
? fixed_durations_[t]
|
||||
: integer_trail_->UpperBound(duration_vars_[t]);
|
||||
}
|
||||
|
||||
inline IntegerValue SchedulingConstraintHelper::StartMin(int t) const {
|
||||
return integer_trail_->LowerBound(start_vars_[t]);
|
||||
}
|
||||
@@ -340,6 +347,19 @@ inline std::function<IntegerVariable(const Model&)> SizeVar(
|
||||
};
|
||||
}
|
||||
|
||||
inline std::function<bool(const Model&)> IsOptional(IntervalVariable v) {
|
||||
return [=](const Model& model) {
|
||||
return model.Get<IntervalsRepository>()->IsOptional(v);
|
||||
};
|
||||
}
|
||||
|
||||
inline std::function<Literal(const Model&)> IsPresentLiteral(
|
||||
IntervalVariable v) {
|
||||
return [=](const Model& model) {
|
||||
return model.Get<IntervalsRepository>()->IsPresentLiteral(v);
|
||||
};
|
||||
}
|
||||
|
||||
inline std::function<IntervalVariable(Model*)> NewInterval(int64 min_start,
|
||||
int64 max_end,
|
||||
int64 size) {
|
||||
|
||||
@@ -25,6 +25,8 @@ DEFINE_bool(lp_constraint_use_dual_ray, true,
|
||||
namespace operations_research {
|
||||
namespace sat {
|
||||
|
||||
const double LinearProgrammingConstraint::kEpsilon = 1e-6;
|
||||
|
||||
LinearProgrammingConstraint::LinearProgrammingConstraint(
|
||||
IntegerTrail* integer_trail)
|
||||
: integer_trail_(integer_trail) {
|
||||
|
||||
@@ -127,7 +127,7 @@ class LinearProgrammingConstraint : public PropagatorInterface {
|
||||
glop::Fractional GetVariableValueAtCpScale(glop::ColIndex var);
|
||||
|
||||
// TODO(user): use solver's precision epsilon.
|
||||
constexpr static double kEpsilon = 1e-6;
|
||||
static const double kEpsilon;
|
||||
|
||||
// Underlying LP solver API.
|
||||
glop::LinearProgram lp_data_;
|
||||
|
||||
@@ -35,9 +35,16 @@ TimeTablingPerTask::TimeTablingPerTask(
|
||||
// the profile is shaped like the Hanoi tower. The additional space is for
|
||||
// both extremities and the sentinels.
|
||||
profile_.reserve(2 * num_tasks_ + 4);
|
||||
in_profile_.resize(num_tasks_);
|
||||
scp_.reserve(num_tasks_);
|
||||
ecp_.reserve(num_tasks_);
|
||||
is_in_profile_.resize(num_tasks_);
|
||||
in_profile_.reserve(num_tasks_);
|
||||
// Reversible set of tasks to consider for propagation.
|
||||
num_tasks_to_sweep_ = num_tasks_;
|
||||
tasks_to_sweep_.resize(num_tasks_);
|
||||
for (int t = 0; t < num_tasks_; ++t) {
|
||||
tasks_to_sweep_[t] = t;
|
||||
}
|
||||
}
|
||||
|
||||
void TimeTablingPerTask::RegisterWith(GenericLiteralWatcher* watcher) {
|
||||
@@ -47,6 +54,8 @@ void TimeTablingPerTask::RegisterWith(GenericLiteralWatcher* watcher) {
|
||||
for (int t = 0; t < num_tasks_; t++) {
|
||||
watcher->WatchLowerBound(demand_vars_[t], id);
|
||||
}
|
||||
// Reversible number of tasks to consider for propagation.
|
||||
watcher->RegisterReversibleInt(id, &num_tasks_to_sweep_);
|
||||
}
|
||||
|
||||
bool TimeTablingPerTask::Propagate() {
|
||||
@@ -75,19 +84,23 @@ bool TimeTablingPerTask::BuildProfile() {
|
||||
|
||||
scp_.clear();
|
||||
ecp_.clear();
|
||||
in_profile_.clear();
|
||||
|
||||
// Build start of compulsory part events.
|
||||
for (int i = num_tasks_ - 1; i >= 0; --i) {
|
||||
const auto task_time = by_decreasing_start_max[i];
|
||||
const int t = task_time.task_index;
|
||||
in_profile_[t] =
|
||||
is_in_profile_[t] =
|
||||
helper_->IsPresent(t) && task_time.time < helper_->EndMin(t);
|
||||
if (in_profile_[t]) scp_.push_back(task_time);
|
||||
if (is_in_profile_[t]) {
|
||||
in_profile_.push_back(t);
|
||||
scp_.push_back(task_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Build end of compulsory part events.
|
||||
for (int i = 0; i < num_tasks_; ++i) {
|
||||
if (in_profile_[by_increasing_end_min[i].task_index]) {
|
||||
if (is_in_profile_[by_increasing_end_min[i].task_index]) {
|
||||
ecp_.push_back(by_increasing_end_min[i]);
|
||||
}
|
||||
}
|
||||
@@ -189,17 +202,38 @@ void TimeTablingPerTask::ReverseProfile() {
|
||||
bool TimeTablingPerTask::SweepAllTasks() {
|
||||
// Tasks with a lower or equal demand will not be pushed.
|
||||
const IntegerValue min_demand = CapacityMax() - profile_max_height_;
|
||||
for (int t = 0; t < num_tasks_; ++t) {
|
||||
// Note: We still push the optional task that may be present. It is OK to
|
||||
// propagate the bounds of such tasks. They should become unperformed if
|
||||
// the bounds are no longer consistent.
|
||||
if (DemandMin(t) <= min_demand || helper_->DurationMin(t) == 0) continue;
|
||||
if (helper_->IsAbsent(t)) continue;
|
||||
|
||||
if (helper_->StartMin(t) != helper_->StartMax(t) && !SweepTask(t)) {
|
||||
return false;
|
||||
for (int i = num_tasks_to_sweep_ - 1; i >= 0; --i) {
|
||||
const int t = tasks_to_sweep_[i];
|
||||
const bool fixed_start = helper_->StartMin(t) == helper_->StartMax(t);
|
||||
const bool fixed_end = helper_->EndMin(t) == helper_->EndMax(t);
|
||||
// A task does not have to be considered for propagation in the rest of the
|
||||
// sub-tree if it respects one of these conditions:
|
||||
// - its start and end variables are fixed;
|
||||
// - it has a maximum duration of 0;
|
||||
// - it has a maximum demand of 0;
|
||||
// - it is absent.
|
||||
if ((fixed_start && fixed_end) || helper_->DurationMax(t) == 0 ||
|
||||
DemandMax(t) == 0 || helper_->IsAbsent(t)) {
|
||||
// Remove the task from the set of tasks to sweep.
|
||||
num_tasks_to_sweep_--;
|
||||
tasks_to_sweep_[i] = tasks_to_sweep_[num_tasks_to_sweep_];
|
||||
tasks_to_sweep_[num_tasks_to_sweep_] = t;
|
||||
continue;
|
||||
}
|
||||
// A task does not have to be considered for propagation in this particular
|
||||
// iteration if it respects one of these conditions:
|
||||
// - its start variable is fixed;
|
||||
// - its minimum demand cannot lead to a resource overload;
|
||||
// - its minimum duration is 0.
|
||||
if (fixed_start || DemandMin(t) <= min_demand ||
|
||||
helper_->DurationMin(t) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SweepTask(t)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,7 +283,7 @@ bool TimeTablingPerTask::SweepTask(int task_id) {
|
||||
new_start_min = profile_[rec_id].end;
|
||||
if (start_max < new_start_min) {
|
||||
new_start_min = start_max;
|
||||
overload = !in_profile_[task_id];
|
||||
overload = !is_in_profile_[task_id];
|
||||
}
|
||||
new_end_min = std::max(new_end_min, new_start_min + duration_min);
|
||||
|
||||
@@ -294,13 +328,12 @@ bool TimeTablingPerTask::UpdateStartingTime(int task_id, IntegerValue left,
|
||||
|
||||
void TimeTablingPerTask::AddProfileReason(IntegerValue left,
|
||||
IntegerValue right) {
|
||||
for (int t = 0; t < num_tasks_; ++t) {
|
||||
for (const int t : in_profile_) {
|
||||
const IntegerValue start_max = helper_->StartMax(t);
|
||||
const IntegerValue end_min = helper_->EndMin(t);
|
||||
|
||||
// Do not consider the task if it does not overlap [left, right), if it is
|
||||
// absent, or if it does not have a mandatory part.
|
||||
if (end_min <= left || right <= start_max || !in_profile_[t]) continue;
|
||||
// Do not consider the task if it does not overlap [left, right).
|
||||
if (end_min <= left || right <= start_max) continue;
|
||||
|
||||
helper_->AddPresenceReason(t);
|
||||
helper_->AddStartMaxReason(t, std::max(left, start_max));
|
||||
|
||||
@@ -88,6 +88,10 @@ class TimeTablingPerTask : public PropagatorInterface {
|
||||
return integer_trail_->LowerBound(demand_vars_[task_id]);
|
||||
}
|
||||
|
||||
IntegerValue DemandMax(int task_id) const {
|
||||
return integer_trail_->UpperBound(demand_vars_[task_id]);
|
||||
}
|
||||
|
||||
// Number of tasks.
|
||||
const int num_tasks_;
|
||||
|
||||
@@ -110,12 +114,21 @@ class TimeTablingPerTask : public PropagatorInterface {
|
||||
|
||||
// True if the corresponding task is part of the profile, i.e., it has a
|
||||
// mandatory part and is not optional.
|
||||
std::vector<bool> in_profile_;
|
||||
std::vector<bool> is_in_profile_;
|
||||
|
||||
// Tasks that are part of the profile. In other words, this vector contains
|
||||
// all the tasks for which is_in_profile_ is true.
|
||||
std::vector<int> in_profile_;
|
||||
|
||||
// True if the last call of the propagator has filtered the domain of a task
|
||||
// and changed the shape of the profile.
|
||||
bool profile_changed_;
|
||||
|
||||
// Reversible set of tasks to consider for propagation. The set contains the
|
||||
// tasks in the [0, num_tasks_to_sweep_) prefix of tasks_to_sweep_.
|
||||
std::vector<int> tasks_to_sweep_;
|
||||
int num_tasks_to_sweep_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TimeTablingPerTask);
|
||||
};
|
||||
|
||||
|
||||
@@ -351,53 +351,58 @@ PiecewiseLinearFunction* PiecewiseLinearFunction::CreateFullDomainFunction(
|
||||
|
||||
PiecewiseLinearFunction* PiecewiseLinearFunction::CreateOneSegmentFunction(
|
||||
int64 point_x, int64 point_y, int64 slope, int64 other_point_x) {
|
||||
return new PiecewiseLinearFunction(
|
||||
{PiecewiseSegment(point_x, point_y, slope, other_point_x)});
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(point_x, point_y, slope, other_point_x)};
|
||||
return new PiecewiseLinearFunction(segments);
|
||||
}
|
||||
|
||||
PiecewiseLinearFunction* PiecewiseLinearFunction::CreateRightRayFunction(
|
||||
int64 point_x, int64 point_y, int64 slope) {
|
||||
return new PiecewiseLinearFunction(
|
||||
{PiecewiseSegment(point_x, point_y, slope, kint64max)});
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(point_x, point_y, slope, kint64max)};
|
||||
return new PiecewiseLinearFunction(std::move(segments));
|
||||
}
|
||||
|
||||
PiecewiseLinearFunction* PiecewiseLinearFunction::CreateLeftRayFunction(
|
||||
int64 point_x, int64 point_y, int64 slope) {
|
||||
return new PiecewiseLinearFunction(
|
||||
{PiecewiseSegment(point_x, point_y, slope, kint64min)});
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(point_x, point_y, slope, kint64min)};
|
||||
return new PiecewiseLinearFunction(std::move(segments));
|
||||
|
||||
}
|
||||
|
||||
PiecewiseLinearFunction* PiecewiseLinearFunction::CreateFixedChargeFunction(
|
||||
int64 slope, int64 value) {
|
||||
std::vector<PiecewiseSegment> segments;
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(0, 0, 0, kint64min),
|
||||
PiecewiseSegment(0, value, slope, kint64max)};
|
||||
CHECK_GE(slope, 0);
|
||||
CHECK_GE(value, 0);
|
||||
return new PiecewiseLinearFunction(
|
||||
{PiecewiseSegment(0, 0, 0, kint64min),
|
||||
PiecewiseSegment(0, value, slope, kint64max)});
|
||||
return new PiecewiseLinearFunction(std::move(segments));
|
||||
}
|
||||
|
||||
PiecewiseLinearFunction* PiecewiseLinearFunction::CreateEarlyTardyFunction(
|
||||
int64 reference, int64 earliness_slope, int64 tardiness_slope) {
|
||||
std::vector<PiecewiseSegment> segments;
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(reference, 0, -earliness_slope, kint64min),
|
||||
PiecewiseSegment(reference, 0, tardiness_slope, kint64max)};
|
||||
CHECK_GE(earliness_slope, 0);
|
||||
CHECK_GE(tardiness_slope, 0);
|
||||
return new PiecewiseLinearFunction(
|
||||
{PiecewiseSegment(reference, 0, -earliness_slope, kint64min),
|
||||
PiecewiseSegment(reference, 0, tardiness_slope, kint64max)});
|
||||
return new PiecewiseLinearFunction(std::move(segments));
|
||||
}
|
||||
|
||||
PiecewiseLinearFunction*
|
||||
PiecewiseLinearFunction::CreateEarlyTardyFunctionWithSlack(
|
||||
int64 early_slack, int64 late_slack, int64 earliness_slope,
|
||||
int64 tardiness_slope) {
|
||||
std::vector<PiecewiseSegment> segments;
|
||||
CHECK_GE(earliness_slope, 0);
|
||||
CHECK_GE(tardiness_slope, 0);
|
||||
return new PiecewiseLinearFunction(
|
||||
std::vector<PiecewiseSegment> segments =
|
||||
{PiecewiseSegment(early_slack, 0, -earliness_slope, kint64min),
|
||||
PiecewiseSegment(early_slack, 0, 0, late_slack),
|
||||
PiecewiseSegment(late_slack, 0, tardiness_slope, kint64max)});
|
||||
PiecewiseSegment(late_slack, 0, tardiness_slope, kint64max)};
|
||||
|
||||
CHECK_GE(earliness_slope, 0);
|
||||
CHECK_GE(tardiness_slope, 0);
|
||||
return new PiecewiseLinearFunction(std::move(segments));
|
||||
}
|
||||
|
||||
bool PiecewiseLinearFunction::InDomain(int64 x) const {
|
||||
|
||||
Reference in New Issue
Block a user