Build the true problem

The first step is to construct the true problem. The true problem can be either stage-wise independent or Markovian.

Stage-wise independent true problem

Construction of a stage-wise independent true problem has two steps.

First, create an MSLP instance by specifying number of time periods T. This will create a list of T empty StochasticModel objects.

Second, run a for loop and fill in the T StochasticModel objects.

Stage-wise independent finite discrete problems

Suppose we want to purchase some newspaper today and sell it tomorrow. The demand for newspaper tomorrow is uniformly distributed in 0 to 10. The retail price, production cost, and recycled value of one newspaper is $2, $1, $0.5. How many newspaper should we buy today?

from msppy.msp import MSLP
nvid = MSLP(T=2, sense=-1, bound=20)
for t in range(2):
    m = nvid[t]
    if t == 0:
        buy_now, _ = m.addStateVar(name='bought', obj=-1.0)
    else:
        _, buy_past = m.addStateVar(name='bought')
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0,
            uncertainty={'rhs':range(11)})
        m.addConstr(sold + recycled == buy_past)

We start with building an MSLP project representing a two-stage stochastic linear program to be maximized. We then run a loop to fill in each individual stage problem m. The state variable in this problem is the number of newspaper to buy. So we add this state variable by addStateVar to each stage problem. The addStateVar will return a tuple that represents the added state variable and its local copy variable. In stage one, we add control variables sold, unsatisfied, and recycled that represent the number of newspaper to sell, the number of ordered newspaper is unsatisfied, and the number of newspaper to recycle. We also add the demand-supply constraint by addConstr. The right hand side of this constraint representing demand has scenarios from 0 to 10 (by default with equal probability) and is initialized to be 5 (does not matter since it will be overwritten by the scenarios) . In the end, we add the recycle equality.

Stage-wise independent continuous problems

Now suppose the uncertain demand follows a lognormal distribution. The problem can be constructed simply by replace the scenario list with a continuous function.

from msppy.msp import MSLP
import numpy as np
nvic = MSLP(T=2, sense=-1, bound=100)
def f(random_state):
    return random_state.lognormal(mean=np.log(4),sigma=2)
for t in range(2):
    m = nvic[t]
    buy_now, buy_past = m.addStateVar(name='bought', obj=-1.0)
    if t == 1:
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0, uncertainty={'rhs':f})
        m.addConstr(sold + recycled == buy_past)

Markovian true problems

Construction of a Markovian true problem has three steps.

First, create an MSLP instance by specifying number of time periods T. This will create a list of T empty StochasticModel objects.

Second, add Markovian uncertainty. The Markovian uncertainty can be a (non-homogeneous) Markov chain process or a Markovian continuous process. The Markov chain process should be specified by a Markov state space and a transition matrix. The Markovian continuous process should be specified by a sample path generator.

Third, run a for loop and fill in the T StochasticModel objects. Each dimension of the Markovian uncertainty is added during the process.

Markov chain problems

Continue with the simple news vendor problem. Suppose now we are dealing with a three-stage news vendor problem with a Markov chain demand. Specifically, In the first stage, there is no demand. In the second stage, the initial Markov state are [4,6] with equal probability. In the third stage, the Markov states are [4,6] and the transition matrix from stage two to stage three is [[0.3,0.7],[0.7,0.3]].

from msppy.msp import MSLP
nvmc = MSLP(T=3, sense=-1, bound=100)
nvmc.add_MC_uncertainty(
    Markov_states=[[[0]],[[4],[6]],[[4],[6]]],
    transition_matrix=[
        [[1]],
        [[0.5,0.5]],
        [[0.3,0.7],[0.7,0.3]]
    ]
)
for t in range(3):
    m = nvmc[t]
    buy_now, buy_past = m.addStateVar(name='bought', obj=-1.0)
    if t != 0:
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0,
            uncertainty_dependent={'rhs':0})
        m.addConstr(sold + recycled == buy_past)

Markovian continuous problems

Suppose now the demand follows a time series \(d_t=0.5\times d_{t-1}+\epsilon_{t}\), where \(\epsilon_{t}\) is i.i.d and follows a lognormal distribution.

from msppy.msp import MSLP
import numpy as np
nvm = MSLP(T=3, sense=-1, bound=500)
def sample_path_generator(random_state, size):
    a = np.zeros([size,3,1])
    for t in range(1,3):
        a[:,t,:] = (0.5 * a[:,t-1,:]
            + random_state.lognormal(2.5,1,size=[size,1]))
    return a
nvm.add_Markovian_uncertainty(sample_path_generator)
for t in range(3):
    m = nvm[t]
    buy_now, buy_past = m.addStateVar(name='bought', obj=-1.0)
    if t != 0:
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0, uncertainty_dependent={'rhs':0})
        m.addConstr(sold + recycled == buy_past)

Risk averse problem

Besides expectation, the package also provides a built-in risk measure, called as Expectation_AVaR, that is a linear combination of expectation and average value at risk (AVaR). Risk measures can be added as a direct method (without adding additional things and directly changing the coefficients and rhs of cutting planes) or an indirect method (adding additional state variables to transform the problem into risk neutral). This two methods are equivalent when the numbers of samples times the parameter of Value-at-risk happen to be integer for each stage.

The following snippet constructs a stage-wise independent finite discrete problem in Expectation_AVaR. The parameter l represents the weight given to AVaR and a represents the parameter of value-of-risk.

from msppy.msp import MSLP
import numpy as np
nvica = MSLP(T=2, sense=-1, bound=100)
for t in range(2):
    m = nvica[t]
    buy_now, buy_past = m.addStateVar(name='bought', obj=-1.0)
    if t == 1:
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0,
            uncertainty={'rhs':range(11)})
        m.addConstr(sold + recycled == buy_past)
nvica.set_AVaR(l=0.5, a=0.1, method='direct')

Integer problems

The variables are in fact integer. This can be achieved by created MSIP instance. The program can also be binarized (this is useful for tighter cuts).

from msppy.msp import MSIP
import numpy as np
nvidi = MSIP(T=2, sense=-1, bound=100)
for t in range(2):
    m = nvidi[t]
    buy_now, buy_past = m.addStateVar(name='bought', obj=-1.0, vtype='I')
    if t == 1:
        sold = m.addVar(name='sold', obj=2, vtype='I')
        unsatisfied = m.addVar(name='unsatisfied', vtype='I')
        recycled = m.addVar(name='recycled', obj=0.5, vtype='I')
        m.addConstr(sold + unsatisfied == 0,
            uncertainty={'rhs':range(11)})
        m.addConstr(sold + recycled == buy_past)

Infinite horizon problems

Infinite horizon problem can be built using exactly the same syntax. In the following snippet, the period is 2 stages, and hence the number of stages to consider is 3. (Recall that we have a deterministic first stage).

from msppy.msp import MSLP
rhs = [[0,2,4,6,8],[1,3,5,7,9]]
nvidinf = MSLP(T=3, discount=0.9, sense=-1, bound=20)
for t in range(3):
    m = nvidinf[t]
    if t == 0:
        buy_now, _ = m.addStateVar(name='bought', obj=-1.0)
    else:
        _, buy_past = m.addStateVar(name='bought')
        sold = m.addVar(name='sold', obj=2)
        unsatisfied = m.addVar(name='unsatisfied')
        recycled = m.addVar(name='recycled', obj=0.5)
        m.addConstr(sold + unsatisfied == 0,
            uncertainty={'rhs':rhs[t-1]})
        m.addConstr(sold + recycled == buy_past)

Dual problems

Coming soon…

Uncertainty

From the above examples, you have already seen the way to build the true problem. It starts with creating an MSLP/MSIP object. An MSLP/MSIP object is composed of a list of StochasticModel objects. Users are then required to fill in each StochasticModel object. The StochasticModel class is a stochastic version of the gurobipy.Model that introduced in the Gurobi library. It allows users to directly write into a stochastic model rather than treating the deterministic counterpart and uncertainties separately. In order to achieve it while staying close to the gurobipy syntax, the MSPPy package encapsulates the gurobipy.Model and its randomness. Hence, all things that work on gurobipy.Model will work on Stochastic Model. In addition, four routines from gurobipy are overwritten and several new routines are created for modeling convenience. The four overwritten routines as shown in the snippet below, addVar, addVars, addConstr, addConstrs, include additional arguments called uncertainty and uncertainty_dependent in order to incorporate stage-wise independent data process and Markovian process. Uncertainties that appear in the objective can be added along with adding related variables (by addVar or addVars). Uncertainties that appear in the constraints can be added along with adding related constraints (by addConstr or addConstrs).

m = StochasticModel()
m.addVars(..., uncertainty, uncertainty_dependent)
m.addVar(..., uncertainty, uncertainty_dependent)
m.addConstrs(..., uncertainty, uncertainty_dependent)
m.addConstr(...., uncertainty, uncertainty_dependent)

Two new routines are added in order to include state variable(s). Local copy variable(s) will be added correspondingly behind the scenes. In the following snippet, now is a reference to the added state variable(s) and past is a reference to the corresponding local copy variable(s).

now, past = m.addStateVars(..., uncertainty, uncertainty_dependent)
now, past = m.addStateVar(..., uncertainty, uncertainty_dependent)

There are some subtlety when adding multiple uncertainties. Using the above routine adds stage-wise independent uncertainty sequentially by specifying its scenarios (if finite discrete) or its marginal distribution (if continuous). The dependence between uncertainties should be taken care of. Note that the package does not allow for a mixture of finite discrete distribution and continuous distribution.

Adding multiple stage-wise independent finite discrete uncertainties

When the problem has multiple finite discrete uncertainties, the package requires for an unique probability measure and the sequentially added uncertainties should be of the same length. Hence, users should first construct the joint distribution of the uncertainties and compute all the scenarios. These scenarios are then added sequentially and the dependence will be retained.

For example, consider a hypothetical StochasticModel m with two uncertainties. The right hand side of one of its constraints is random with a finite sample space of [1,2]. Besides, in the objective function, one of the coefficient is random with a finite sample space of [3,4]. Assume the joint distribution of the two uncertainties are given by the following table,

samples probability
(1,3) 0.2
(1,4) 0.3
(2,3) 0.3
(2,4) 0.2

We can then add the two uncertainties and the probability measure by

m.addConstr(..., uncertainty={'rhs':[1,1,2,2]}
m.addVar(..., uncertainty=[3,4,3,4])
m.set_probability([0.2,0.3,0.3,0.2])

Adding multiple stage-wise independent continuous uncertainties

When the problem has multiple continuous uncertainties, if those uncertainties are independent to each other, users can use the above routines to add them sequentially to the model by specifying their marginal distributions. Otherwise, users should use another routine, add_continuous_uncertainty, to directly add their joint distribution. For example, consider a hypothetical StochasticModel m with two uncertainties. The right hand side of one of its constraints is normally distributed with mean 0 and std 1. Besides, in the objective function, one of the coefficient is normally distributed with mean 0 and std 1.

If those two uncertainties are independent to each other, we can add the two uncertainties by

def f(random_state):
    random_state.normal(0,1)
m.addConstr(..., uncertainty={'rhs':f}
m.addVar(..., uncertainty=f)

If those two uncertainties are dependent and follow multivariate normal distribution with a correlation of 0.5 , we can add the two uncertainties by

def f(random_state):
    random_state.multivariate_normal(
        mean=[0,0],
        cov=[
            [1,0.5],
            [0.5,1]
        ]
    )
a_constr = m.addConstr(...}
a_var = m.addVar(...)
def f(random_state):
    random_state.normal(0,1)
m.add_continuous_uncertainty(uncertainty=f, locations=[a_constr, a_var])

Module Reference

The StochasticModel class

class msppy.sp.StochasticModel(name='')[source]

The StochasticModel class

msppy.msp.StochasticModel.addStateVars(self, *indices, lb=0.0, ub=1e+100, obj=0.0, vtype='C', name='', uncertainty=None, uncertainty_dependent=None)

Add state variables in bulk. Generalize gurobipy.addVars() to incorporate uncertainty in the objective function. Variables are added as state variables and the corresponding local copy variables will be added behind the scene

Parameters:
  • uncertainty (callable, optional, default=None) – The scenarios of stage-wise independent uncertain objective coefficients.
  • uncertainty – The multivariate random variable generator of stage-wise independent uncertain objective coefficients. It must take numpy RandomState as its only argument.
  • uncertainty_dependent (array-like, optional, default=None) – The location index in the stochastic process generator of stage-wise dependent uncertain objective coefficients.
Returns:

(the created state variables, the corresponding local_copy variables)

Return type:

tuple

Examples

>>> now,past = model.addStateVars(
...     2,
...     ub=2.0,
...     uncertainty={[[2,4],[3,5]]}
... )
>>> now,past = model.addStateVars(
...     [(1,2),(2,1)],
...     ub=2.0,
...     uncertainty={[[2,4],[3,5]]}
... )

stage-wise independent continuous uncertain objective coefficients

>>> def f(random_state):
...     return random_state.multivariate_normal(
...         mean = [0,0],
...         cov = [[1,0],[0,1]]
...     )
>>> now,past = model.addStateVars(2, ub=2.0, uncertainty=f)

Markovian objective coefficients

>>> now,past = model.addStateVars(2, ub=2.0, uncertainty_dependent=[1,2])
msppy.msp.StochasticModel.addStateVar(self, lb=0.0, ub=1e+100, obj=0.0, vtype='C', name='', column=None, uncertainty=None, uncertainty_dependent=None)

Add a state variable to the model. Generalize gurobipy.addVar() to incorporate uncertainty in the objective function. The variable is added as a state variable and the corresponding local copy variable will be added behind the scene

Parameters:
  • uncertainty (int, optional, default=None) – The scenarios of the stage-wise independent uncertain objective coefficient
  • uncertainty – The univariate random variable generator of stage-wise independent uncertain objective coefficient. The callable must take numpy.random.
  • uncertainty – The location index in the stochastic process generator of the stage-wise dependent uncertain objective coefficient
Returns:

(the created state variable, the corresponding local copy variable)

Return type:

tuple

Examples

>>> now,past = model.addStateVar(ub=2.0, uncertainty=[1,2,3])

stage-wise independent continuous uncertain objective coefficient

>>> def f(random_state):
...     return random_state.normal(0, 1)
>>> now,past = model.addStateVar(ub=2.0, uncertainty=f)

Markovian objective coefficient

>>> now,past = model.addStateVar(ub=2.0, uncertainty_dependent=[1,2])
msppy.msp.StochasticModel.addVars(self, *indices, lb=0.0, ub=1e+100, obj=0.0, vtype='C', name='', uncertainty=None, uncertainty_dependent=None)

Add variables in bulk. Generalize gurobipy.addVars() to incorporate uncertainty in the objective function

Parameters:
  • uncertainty (callable, optional, default=None) – The scenarios of the stage-wise independent uncertain objective coefficients
  • uncertainty – The multivariate random variable generator of stage-wise independent uncertain objective coefficients. The callable must take numpy RandomState as its only argument
  • uncertainty_dependent (array-like, optional, default=None) – The locations index in the stochastic process generator of the stage-wise dependent objective coefficients
Returns:

The created variables

Return type:

list of gurobipy.Var

Examples

>>> newVars = model.addVars(
...     3,
...     ub=2.0,
...     uncertainty={[[2,4,6],[3,5,7]]}
... )
>>> newVars = model.addVars(
...     [(1,2),(2,1)],
...     ub=2.0,
...     uncertainty={[[2,4],[3,5],[4,6]]}
... )

stage-wise independent continuous uncertain objective coefficients

>>> def f(random_state):
...     return random_state.multivariate_normal(
...         mean = [0,0],
...         cov = [[1,0],[0,100]]
...     )
>>> newVars = model.addVars(
...     2,
...     ub=2.0,
...     uncertainty=f
... )

Markovian objective coefficients

>>> newVars = model.addVars(
...     2,
...     ub=2.0,
...     uncertainty_dependent=[1,2]
... )
msppy.msp.StochasticModel.addVar(self, lb=0.0, ub=1e+100, obj=0.0, vtype='C', name='', column=None, uncertainty=None, uncertainty_dependent=None)

Add a variable to the model. Generalize gurobipy.addVar() to incorporate uncertainty in the objective function

Parameters:
  • uncertainty (int, optional, default=None) – The scenarios of the stage-wise independent uncertain objective coefficient
  • uncertainty – The univariate random variable generator of stage-wise independent uncertain objective coefficient. The callable must take numpy RandomState as its only argument.
  • uncertainty – The location index in the sample path generator of the stage-wise dependent uncertain objective coefficient
Returns:

The created variable

Return type:

gurobipy.Var

Examples

>>> newVar = model.addVar(ub=2.0, uncertainty=[1,2,3])

stage-wise independent continuous uncertain objective coefficient

>>> def f(random_state):
...     return random_state.normal(0, 1)
... newVar = model.addVar(ub=2.0, uncertainty=f)

Markovian objective coefficient

>>> newVar = model.addVar(ub=2.0, uncertainty_dependent=[1])
msppy.msp.StochasticModel.addConstrs(self, generator, name='', uncertainty=None, uncertainty_dependent=None)

Add constraints in bulk to the model. Generalize gurobipy.addConstrs() to incorporate uncertainty on the RHS of the constraints. If you want to add constraints with uncertainties on coefficients, use addConstr() instead and add those constraints one by one

Parameters:
  • uncertainty (array-like/callable, optional, default=None) – The scenarios/multivariate random variable generator of the stage-wise independent uncertain RHS. A generator must take numpy RandomState as its only argument
  • uncertainty_dependent (array-like, optional, default=None) – The locations in the sample path generator of the stage-wise independent uncertain RHS. A generator must take numpy RandomState as its only argument
Returns:

The created constraints

Return type:

list of gurobipy.Constr

Examples

>>> new, past = model.addStateVar(ub=2.0)

stage-wise independent discrete uncertain RHSs

>>> newConstrs = model.addConstrs(
...     new[i] + past[i] == 0 for i in range(2),
...     uncertainty=[[1,2],[2,3]]
... )

The above example dictates scenarios of RHSs to be [1,2] and [2,3]

stage-wise independent continuous uncertain RHSs

>>> def f(random_state):
...     return random_state.multivariate_normal(
...         mean = [0,0],
...         cov = [[1,0],[0,100]]
...     )
>>> newConstrs = model.addConstrs(
...        (new[i] + past[i] == 0 for i in range(2)),
...        uncertainty=f
... )

Markovian uncertain RHSs

>>> newConstrs = model.addConstrs(
...     (new[i] + past[i] == 0 for i in range(2)),
...     uncertainty_dependent = [0,1],
... )
msppy.msp.StochasticModel.addConstr(self, lhs, sense=None, rhs=None, name='', uncertainty=None, uncertainty_dependent=None)

Add a constraint to the model. Generalize gurobipy.addConstr() to incorporate uncertainty in a constraint

Parameters:
  • uncertainty (dict, optional, default=None) – The scenarios/univariate random variable generator of the stage-wise independent uncertain constraint coefficient and RHS
  • uncertainty_dependent (dict, optional, default=None) – The location index in the sample path genator of the stage-wise dependent uncertain constraint coefficient and RHS
Returns:

The created constraint

Return type:

gurobipy.Constr

Examples

>>> new, past = model.addStateVar(ub=2.0)

stage-wise independent finite discrete uncertain rhs/constraint coefficient

>>> newConstr = model.addConstr(
...     new + past == 3.0,
...     uncertainty={'rhs': [1,2,3], new: [3,4,5]}
... )

The above example dictates scenarios of RHS to be [1,2,3] and coefficient of new to be [3,4,5]

stage-wise independent continuous uncertain rhs/constraint coefficient

>>> def f(random_state):
...     return random_state.normal(0, 1)
>>> newConstr = model.addConstr(
...     ub=2.0,
...     uncertainty={new: f},
...     uncertainty_dependent = {'rhs': [1]}
... )

The above constraint contains a stage-wise independent uncertain constraint coefficient and a Markovian RHS

msppy.msp.StochasticModel.set_probability(self, probability)

Set probability measure of discrete scenarios.

Parameters:probability (array-like) – Probability of scenarios. Default is uniform measure [1/n_samples for _ in range(n_samples)]. Length of the list must equal length of uncertainty. The order of the list must match with the order of uncertainty list.

Examples

>>> newVar = model.addVar(ub=2.0, uncertainty=[1,2,3])
>>> model.setProbability([0.2,0.3,0.4])
msppy.msp.StochasticModel.add_continuous_uncertainty(self, uncertainty, locations)

Add continuous stage-wise independent uncertainties.

Parameters:
  • uncertainty (callable) – A random variable generator that takes numpy RandomState as its only argument.
  • location (list) – Entries of the list can be gurobipy.Var, gurobipy.Constr, or (gurobipy.Constr, gurobipy.var).
  • dimension of random variable generator should equal (The) –
  • length of locations. (the) –

Examples

>>> now, past = model.addStateVar()
>>> TS = model.addConstr(now - past == 0)
>>> model.add_continuous_uncertainty(f, [(TS, past), TS])

The MSLP class

class msppy.msp.MSLP(T, bound=None, sense=1, outputFlag=0, discount=1.0, ctg=False, **kwargs)[source]

A multistage stochastic linear program composed of a sequence of StochasticModels.

Parameters:
  • T (integer (>1)) – The number of stages.
  • bound (float, optional) – A known uniform lower bound or uppder bound (depending on optimization sense) for each stage problem. Default value is -1B for maximization problem and 1B for maximation problem.
  • sense (+1/-1, optional, default=1) – The optimization sense. +1 indicates minimization and -1 indicates maximization.
  • outputFlag (1/0, optional, default=0) – Log model solving process or not.
  • discount (float between 0(exclusive) and 1(inclusive), optional (default=1)) – The discount factor used to compute present value.
  • ctg (bool, optional, default=0) – Whether to create ctg variable alpha for each stage (except the last stage) when initialization.
  • **kwargs (optional) – Gurobipy attributes to specify on individual StochasticModels. (e.g., presolve, method)
add_MC_uncertainty:

Set Markov state spaces and transition matricies for the Markov chain process.

add_Markovian_uncertainty:

Set a sample path generator for the Markovian process.

discretize:

discretize the Markovian continuous process.

msppy.msp.MSLP.add_MC_uncertainty(self, Markov_states, transition_matrix)

Add a Markov chain process.

Parameters:
  • Markov_states (list of matrix-like) – Markov state spaces in each stage. The shape of matrix-like must be (p,q) where q is the dimension index of the Markov chain and p is the index of the Markov states
  • transition_matrix (list of matrix-like) – Markov chain transition matrices in each stage. The shape of must be compatible with the Markov states
  • start (start period (inclusive) of the Markov chain process) –
  • end (end period (exclusive) of the Markov chain process) –
  • dimension of all entries in Markov states and transition matrices (The) –
  • be in the form of (must) – transition_matrix: [[1]], [1,p_{1}], [p_{1},p_{2}], [p_{T-2},p_{T-1}]
  • p_1,..p_{T-1} are integers. (where) –

Examples

>>> add_MC_uncertainty(
...     Markov_states=[[[0]],[[4],[6]],[[4],[6]]],
...     transition_matrix=[
...         [[1]],
...         [[0.5,0.5]],
...         [[0.3,0.7],[0.7,0.3]]
...     ]
... )

Three dimensional Markov chain

>>> add_MC_uncertainty(
...     Markov_states=[[[0]],[[4,6,5],[6,3,4]],[[4,6,5],[6,3,4]]],
...     transition_matrix=[
...         [[1]],
...         [[0.5,0.5]],
...         [[0.3,0.7],[0.7,0.3]]
...     ]
... )
msppy.msp.MSLP.add_Markovian_uncertainty(self, Markovian_uncertainty)

Add a Markovian continuous process.

Parameters:Markovian_uncertainty (callable) – A sample path generator. The callable should take numpy.random.randomState and size as its parameters. It should return a three dimensional numpy array (n_samples * T * n_states)

Example

>>> def f(random_state, size):
...     a = numpy.empty([size,3,2])
...     a[:,0,:] = [[0.2,0.2]]
...     for t in range(1,3):
...         a[:,t,:] = (
...             0.5 * numpy.array(a[:,t-1,:])
...             + random_state.multivariate_normal(
...                 mean=[0,0],
...                 cov=[[0,1],[1,0]],
...                 size=size,
...                )
...         )
...     return a
>>> add_Markovian_uncertainty(f)
msppy.msp.MSLP.set_AVaR(self, l, a, method='indirect')

Set linear combination of expectation and conditional value at risk (average value at risk) as risk measure

Parameters:
  • l (float between 0 and 1/array-like of floats between 0 and 1) – The weights of AVaR from stage 2 to stage T If float, the weight will be assigned to the same number. If array-like, must be of length T-1 (for finite horizon problem) or T (for infinite horizon problem).
  • a (float between 0 and 1/array-like of floats between 0 and 1) – The quantile parameters in value-at-risk from stage 2 to stage T If float, those parameters will be assigned to the same number. If array-like, must be of length T-1 (for finite horizon problem) or T (for infinite horizon problem).
  • method ('direct'/'indirect') – direct method directly solves the risk averse problem. indirect method adds additional state variables and transform the risk averse problem into risk netural.

Notes

Bigger l means more risk averse; smaller a means more risk averse.

msppy.msp.MSLP.write(self, path, suffix)

Write all StochasticModels to files. If stage-wise independent, the files would be named as stage_t (t is the stage) If Markov chain, the files would be named as stage_t_k (t is the stage and k is the index of Markov state)

Parameters:
  • path (string) – The location to write the StochasticModel
  • suffix (string) – The format to write the StochasticModel

Examples

write(path = “/Users/lingquan/Desktop”, suffix = “.lp”)

The MSIP class

class msppy.msp.MSIP(T, bound=None, sense=1, outputFlag=0, discount=1.0, ctg=False, **kwargs)[source]
msppy.msp.MSIP.binarize(self, precision=0, bin_stage=0)

Binarize MSIP.

Parameters:
  • precision (int, optional (default=0)) – The number of decimal places of accuracy
  • bin_stage (int, optional (default=0)) – All stage models before bin_stage (exclusive) will be binarized.