简体   繁体   中英

Maximising standard deviation of decision variables via PuLP

I'm new to using PuLP and am trying to programme the standard deviation as my objective function in an optimisation problem. I've read this answer and, though I know it's related, am having trouble applying it to my specific situation.

I'm trying to solve the following optimisation problem: maximise the standard deviation for a set of 3 decision variables with an associated weight vector of [0.25, 0.40, and 0.35]. The constraints I have are that each decision variable should range between 0.5 and 2.0. (This is a simplified example; in practice, I will have a much larger set of decision variables and a larger corresponding weight vector).

So far, my code is the following:

from pulp import LpMaximize, LpProblem, LpVariable

# Create the model
model = LpProblem(name="max_stdev", sense=LpMaximize)

# Define the decision variables
x = {i: LpVariable(name=f"x{i}", lowBound=0.5, upBound=2.0) for i in range(3)}

# Add the constraints to the model
model += (0.25*x[0] + 0.40*x[1] + 0.35*x[2] == 1, "weight_constraint")

# Add the objective function to the model, which should be the standard deviation of the x vector
model += ??

# Solve the problem
status = model.solve()

I'm just not sure how to apply the standard deviation formula in the form of an objective function (see above). Again, I know this answer could be useful, but am just not sure how to make this work.

Many thanks in advance for any help!

It may not be so easy to do this with Pulp. It only accepts linear models and this is inherently non-linear and non-convex. Using a non-convex quadratic solver, we can just maximize

sum(i, (x[i]-μ)^2)

This gives:

----     30 VARIABLE x.L  

i1 0.500,    i2 0.500,    i3 1.929


----     35 VARIABLE z.L                   =        1.361  obj
            VARIABLE mu.L                  =        0.976  mean
            PARAMETER stdev                =        0.825  standard deviation

Possible solvers include Cplex, Gurobi, Baron, Antigone.

It may be possible to replace the squared deviation objective by some absolute value term. But this will be messy as the problem is non-convex. That would require some extra binary variables. Something along the lines of:

   max sum(i, splus[i] + smin[i])
       μ = sum(i, x[i])/n
       splus[i] - smin[i] = x(i)-μ
       splus[i] ≤ b[i]*M
       smin[i]  ≤ (1-b[i])*M 
       0.25*x[0] + 0.40*x[1] + 0.35*x[2] = 1
       smin[i],splus[i] ≥ 0
       b[i] ∈ {0,1}
       x[i] ∈ [0.5,2]
       M = 2-0.5

I get the same results for this example:

----     85 VARIABLE x.L  

i1 0.500,    i2 0.500,    i3 1.929


----     85 VARIABLE z.L                   =        1.905  obj
            VARIABLE mu.L                  =        0.976  mean
            PARAMETER stdev                =        0.825  standard deviation
     

(Usually the solution will not be exactly the same).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM