Bugfixes.
- Added
InstanceCrash
attribute to specify crash method to use in sample-based schemes.
Bugfixes. Internal renaming for better clarity:
VerticalStructure
becomesStageDecompositionStructure
HorizontalStructure
becomesScenarioDecompositionStructure
andStageDecomposition
andScenarioDecomposition
are the official API structs passed through theinstantiation
keyword. The old API structsVertical
andHorizontal
are kept to avoid breaking.
Apart from bugfixes, v0.6.1 introduces the following new features:
@stochastic_model
now allows the following syntax:
@stochastic_model simple begin
@stage 1 begin
@decision(simple, x₁ >= 40)
@decision(simple, x₂ >= 20)
@objective(simple, Min, 100*x₁ + 150*x₂)
@constraint(simple, x₁ + x₂ <= 120)
end
@stage 2 begin
@uncertain q₁ q₂ d₁ d₂
@recourse(simple, 0 <= y₁ <= d₁)
@recourse(simple, 0 <= y₂ <= d₂)
@objective(simple, Max, q₁*y₁ + q₂*y₂)
@constraint(simple, 6*y₁ + 10*y₂ <= 60*x₁)
@constraint(simple, 8*y₁ + 5*y₂ <= 80*x₂)
end
end
where the resuling model object is stored in simple
. Note that the old restriction to use the reserved keyword model
to refer to the inner JuMP model in the @stage
blocks is removed. Instead the name should now match the name simple
given as the first argument to @stochastic_model
. The previous anonymous syntax is kept to avoid breaking:
simple = @stochastic_model begin
@stage 1 begin
@decision(model, x₁ >= 40)
@decision(model, x₂ >= 20)
@objective(model, Min, 100*x₁ + 150*x₂)
@constraint(model, x₁ + x₂ <= 120)
end
@stage 2 begin
@uncertain q₁ q₂ d₁ d₂
@recourse(model, 0 <= y₁ <= d₁)
@recourse(model, 0 <= y₂ <= d₂)
@objective(model, Max, q₁*y₁ + q₂*y₂)
@constraint(model, 6*y₁ + 10*y₂ <= 60*x₁)
@constraint(model, 8*y₁ + 5*y₂ <= 80*x₂)
end
end
where model
must still be used to refer to the JuMP model. Regardless of syntax used, the model name is now properly checked and enforced in the @stage
blocks. If there are any typoes or discrepancies with the required name an error message with the relevant line number will be thrown .
- Improved error messages in creation macros. Now include line numbers and more information about what went wrong.
Apart from performance improvements and various bugfixes, v0.6 introduces the following breaking changes and features:
- A few attributes were not properly camel cased in previus versions, but now are. These are as follows:
SubproblemOptimizer
->SubProblemOptimizer
SubproblemOptimizerAttribute
->SubProblemOptimizerAttribute
RawSubproblemOptimizerParameter
->RawSubProblemOptimizerParameter
Penaltyterm
->PenaltyTerm
AbstractPenaltyterm
->AbstractPenaltyTerm
RegularizationPenaltyterm
->RegularizationPenaltyTerm
- Solution caching, introduced in v0.5, is no longer enabled by default since it can be time consuming for large models. Caching is only run if
cache = true
is supplied as a keyword argument tooptimize!
, or by running the newcache_solution!
function after optimizing. This is documented in the "Quick start" section of the manual.
- A new structured solver suite, based on quasi-gradient algorithms, has been added. The solvers are accessed through
QuasiGradient.Optimizer
and operate on vertical structures. See the documentation for more details. - The L-shaped solver suite has been extended with experimental strategies for problems with integer recourse. These strategies are activated by setting the
IntegerStrategy
attribute. See the documentation for more details. - The structured solvers now implement
TimeLimit
functionality. - Integer/binary variables are now supported by the SMPS reader. In the
.cor
file'sBOUNDS
section, a variable bound annotated byBV
is binary,I
is integer, andLI
andUI
can be used to annotate an integer variable with a lower/upper bound. - The
SCENARIOS
format is now supported by the SMPS reader for two-stage models. - The crash start option
PreSolve
has been added, which runs a supplied optimization procedure (preferrably suboptimal or with early termination), to determine a suitable starting point. - Added
cache_solution!
which tries to save all solution attributes that are queryable after a successful call tooptimize!
.
- The
@scenario
macro is now used to createScenario
objects that match a certain@uncertain
declaration. For example, if the following declaration is used in a stage definition:
@uncertain q₁ q₂ d₁ d₂
then a matching scenario can be created through
ξ = @scenario q₁ = 24.0 q₂ = 28.0 d₁ = 500.0 d₂ = 100.0 probability = 0.4
Container syntax is also supported:
@uncertain ξ[i in 1:4]
@uncertain ξ[i in 1:5, i != 3]
@uncertain ξ[i in 1:5, j in 1:5]
@uncertain ξ[i in 1:5, k in [:a,:b,:c]]
together with:
ξ = @scenario ξ[i in 1:4] = [24.0, 28.0, 500.0, 100.0] probability = 0.4
ξ = @scenario ξ[i in 1:5, i != 3] i * rand() probability = rand()
ξ = @scenario ξ[i in 1:5, j in 1:5] = rand(5,5) probability = rand()
ξ = @scenario ξ[i in 1:5, k in [:a,:b,:c]] = rand(5,5) probability = rand()
See the documentation for further examples.
- The old @scenario functionality is replaced by @define_scenario. Syntax is otherwise unchanged.
- The decision handling has been refactored. StochasticPrograms now provide an extended version of JuMPs API for decision variables/constraints/objectives with stage and scenario dependence. Some short examples are given below.
ξ₁ = @scenario a = 1 probability = 0.5
ξ₂ = @scenario a = 2 probability = 0.5
sp = StochasticProgram([ξ₁,ξ₂], Deterministic())
@first_stage sp = begin
@decision(model, x >= 2)
@objective(model, Min, x)
end
@second_stage sp = begin
@known x
@uncertain a
@recourse(model, y >= 0)
@objective(model, Max, y)
@constraint(model, con, a*y <= x)
end
generate!(sp)
x = sp[1,:x] # Returns a DecisionVariable object that adheres to JuMPs API
lower_bound(x) # 2
y = sp[2,:y] # Returns a DecisionVariable object that adheres to JuMPs API
lower_bound(y) # Errors, y is scenario dependent
lower_bound(y, 1) # 0 (lower bound of y in scenario 1)
con = sp[2,:con] # The constraint `con` is found in the second stage
normalized_coefficient(con, x, 1) # -1, coeff of x in scenario 1
normalized_coefficient(con, x, 2) # -1, coeff of x in scenario 2
normalized_coefficient(con, y, 1) # 1, coeff of y in scenario 1
normalized_coefficient(con, y, 2) # 2, coeff of y in scenario 2
objective_function(sp, 1) # First-stage objective
objective_function(sp, 2, 1) # Second-stage objective in scenario 1
objective_function(sp, 2, 1) # Second-stage objective in scenario 2
objective_function(sp) # Full objective
set_optimizer(sp, GLPK.Optimizer)
value(x) # 2, optimal value of x
value(y) # Errors, y is scenario-dependent
value(y, 1) # 2, optimal value of y in scenario 1
value(y, 1) # 1, optimal value of y in scenario 2
dual(con) # Errors, con is scenario-dependent
dual(con, 1) # -0.5, dual value of con in scenario 1
dual(con, 2) # -0.25, dual value of con in scenario 1
- The new
@recourse
annotation should be used to annotate decisions in the final stage. - Only variables created with
@decision
and@recourse
are accessible with the new API. Likewise, only constraints that include@decision
and/or@recourse
variables are accessible. Regular JuMP variables and constraints are accessed by first querying the relevant JuMP subproblem and the use standars getters. - An SMPS reader has been implemented and added to the framework. It currently supports the INDEP and BLOCKS formats for specifying scenarios. See the documentation for an example.
- The new function
optimal_recourse_decision(sp, scenario_index)
can be used to obtain the optimal recourse decision in scenarioscenario_index
after optimizingsp
. - The new function
recourse_decision(sp, x, scenario)
can be used to obtain the optimal recourse decision in scenarioscenario
ifx
is the first-stage decision. - A granulated aggregation procedure has been added to the L-shaped suite
- The function
lower_bound
becomeslower_confidence_interval
and the functionupper_bound
becomesupper_confidence_interval
to avoid name clashes with JuMP - Solution attributes queryable after optimizing are now automatically cached and are therefore not lost if a decision is evaluated after optimizing.
- Various bugfixes
StochasticPrograms is now compatible with JuMP 0.19+ and the new MathOptInterface backend. This required a major overhaul of the design, which has resulted in breaking changes and many new features. See the documentation for further details.
- The role of the
@decision
macro has changed. It was previously used to annotate variables that originate from previous stages. Now, it is used to define the variable in its origin stage. Specifically, a model that was previosly defined through:
@stochastic_model begin
@stage 1 begin
@variable(model, x₁ >= 40)
@variable(model, x₂ >= 20)
@objective(model, Min, 100*x₁ + 150*x₂)
@constraint(model, x₁ + x₂ <= 120)
end
@stage 2 begin
@decision x₁ x₂
@uncertain q₁ q₂ d₁ d₂
@variable(model, 0 <= y₁ <= d₁)
@variable(model, 0 <= y₂ <= d₂)
@objective(model, Min, q₁*y₁ + q₂*y₂)
@constraint(model, 6*y₁ + 10*y₂ <= 60*x₁)
@constraint(model, 8*y₁ + 5*y₂ <= 80*x₂)
end
end
is now defined through
@stochastic_model begin
@stage 1 begin
@decision(model, x₁ >= 40)
@decision(model, x₂ >= 20)
@objective(model, Min, 100*x₁ + 150*x₂)
@constraint(model, x₁ + x₂ <= 120)
end
@stage 2 begin
@uncertain q₁ q₂ d₁ d₂
@variable(model, 0 <= y₁ <= d₁)
@variable(model, 0 <= y₂ <= d₂)
@objective(model, Max, q₁*y₁ + q₂*y₂)
@constraint(model, 6*y₁ + 10*y₂ <= 60*x₁)
@constraint(model, 8*y₁ + 5*y₂ <= 80*x₂)
end
end
Inside a @stochastic_model
definition, any variable defined using @decision
is available for usage in the next stage. The syntax is the same as JuMP's @variable
macro.
- The
@decision
macro creates specializedAbstractVariableRef
objects calledDecisionVariable
. Internally, the behaviour of the decision variables vary with context. In a deterministic equivalent problem, or the first stage, the decision variables behave as standard JuMP variables. In second-stage subproblems, they act as parameters with known values. - The
DecisionVariable
, as well as its internal representationsDecisionRef
andKnownRef
, all implement JuMP's variable interface. For example, the following now works:
x₁ = decision_by_name(sp, "x₁")
fix(x₁, 40)
and fixes x₁
in all stages.
- The workflow has been overhauled to match the new JuMP workflow. In short, most actions (optimization, evaluation, VSS, EVPI) require an optimizer to first be set (either through the
optimizer
keyword duringinstantiate
or throughset_optimizer
). Optimizers are like JuMP/MOI added as constructors:
set_optimizer(sp, LShaped.Optimizer)
- The L-shaped and progressive-hedging solver suites now each implement a MOI wrapper similar to third-party solvers. In other words, they are now configured in the same way as MOI solvers:
set_optimizer(sp, LShaped.Optimizer)
set_optimizer_attribute(sp, Regularizer(), TrustRegion())
set_optimizer_attribute(sp, Aggregator(), PartialAggregate(2))
This replaces the previous LShapedSolver
/ProgressiveHedgingSolver
API.
- The underlying storage structure of an instantiated stochastic program is now induced by the solver. If instantiated with a third-party solver (GLPK, Gurobi, etc) the finite extensive form (DEP) is generated and stored to represent the stochastic program. If instantiated with an L-shaped solver, the program is stored in a vertical structure with a first stage and a collection of second-stage subproblems. If instantiated with a progressive-hedging solver, the program is stored in a horizontal structure with a collection of subproblems with non-anticipativity constraints. Further, these block-decomposition structures can be distributed in memory. The storage type can be set explicitly by setting the
instantiation
keyword during model creation to one ofDeterministic
,Vertical
,Horizontal
,DistributedVertical
, orDistributedHorizontal
. @uncertain
can now be used with JuMP's container syntax. The new@container_scenario
macro can be used to create scenarios that match the@uncertain
declaration.- Calling
instantiate
with anAbstractSampler
and a desired number of scenarios replacesSAA
for sampled model instantiation.
- LShapedSolvers.jl and ProgressiveHedgingSolvers have been integrated into
StochasticPrograms
. The solver repositories will stay up for future development, but the aim is to keep stable versions inStochasticPrograms
- Both
LShapedSolvers
andProgressiveHedgingSolvers
have seen major rework. This includes both changes to the software design (A policy-base design has succeeded the use ofTraitDispatch
) as well as feature additions (Executors, Cut aggregation, Penalty approximations, ...). See the documentation for further details. - Added functionality for calculating confidence intervals around EVPI and VSS for continuous models.
- Documentation has been extended to cover all new features. In addition, terminology clarifications have been made for sampled models and SAA.
- Bugfixes
0.2 includes a major refactor of model creation.
- Introduces
@stochastic_model
as the main method of model definition. The macro returns aStochasticModel
object that can be used to eitherinstantiate
a stochastic program from a given list of scenarios, or to generate anSAA
model by supplying a sampler object. - StochasticPrograms now supports an arbitrary number of stage blocks in a type-safe manner. However, most tools and specialized solvers are still only implemented for two-stage models.
- Stages are defined using the new
@stage
block.@first_stage
and@second_stage
still exist and are equivalent to@stage 1
and@stage 2
. - The new
@parameters
block is used to specify deterministic parameters in a stage block. The parameters must be provided when instantiating models, but default values can be specified directly in the@parameters
block. - The new
@uncertain
block is used to specify stochastic parameters in a stage block. This can be done in multiple ways for flexibility. For example, it is possible to define and utilize a new scenario type using@scenario
syntax directly in the@uncertain
block. - New sample-based tools added for stochastic programs over continuous random variables. These include calculating confidence intervals around the true optimal value or expected results of given first-stage decisions.
- New sample-based solver interface for approximately solving stochastic programs over continuous random variables. A simple solver based on a sequential SAA algorithm is provided by StochasticPrograms.