Error handling in pyomo - division by zero - linear-programming

I am working on a linear optimization problem where I have a set of cities and a set of powerplants. The cities have an electricity demand that needs to be satisfied. However, in the context of my problem, in certain time periods, the cities have no electricity demand (from the power plants because they can produce some of their own). I do not think the specific details are very important so below is my best description of the issue.
The objective function contains the following term:
Term in objective function
I created the appropriate city and month sets and set up my objective function as:
sum(sum(1/model.monthly_demand[c,t]*model.theta[c] for c in model.cities) for t in model.months)
The issue clearly arises when monthly_demand[c,t] = 0 as i get a division by zero error. And I am not sure how to deal with this. Ideally I would like theta[c] to be set to zero in that case but I am unsure how to do this. I tried adding some if/else statements in the sum() function but this is not possible as far as I understand.
I think I can also define a function that is passed into the pyomo objective, so my idea was to try something like an if statement that sets theta[c] to zero when the monthly demand is zero, but this was not successful.
Another idea was to set the demands to something like 0.000001 but I would like this to be a last resort solution because I think it will cause issues.

You should just make a subset wherever convenient of the non-zero elements of demand. I am assuming demand is a parameter which would make sense, but you didn't specify. Then use that subset as the basis of summation. This will avoid including the empty/zero elements.
Note the elements of the objective in the printout of the model.
Code:
import pyomo.environ as pyo
demand_data = { ('LA', 0) : 20,
('LA', 1) : 0,
('SF', 1) : 15,
('NY', 0) : 20,
('NY', 1) : 30}
m = pyo.ConcreteModel('electricity')
m.C = pyo.Set(initialize=['LA', 'SF', 'NY'])
m.T = pyo.Set(initialize=list(range(2)))
# VARS
m.x = pyo.Var(m.C, m.T, domain=pyo.NonNegativeReals)
# PARAMS
m.demand = pyo.Param(m.C, m.T, initialize=demand_data, default=0)
# CONSTRAINTS
# ...
# OBJ
# make a subset of the non-zero demand periods
nonzero_demand_domain = {(c,t) for c in m.C for t in m.T if m.demand[c, t] > 0}
# use that in your objective...
m.obj = pyo.Objective(expr=sum(m.x[c, t] for c, t in nonzero_demand_domain))
m.pprint()
Output:
4 Set Declarations
C : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'LA', 'SF', 'NY'}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {0, 1}
demand_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : C*T : 6 : {('LA', 0), ('LA', 1), ('SF', 0), ('SF', 1), ('NY', 0), ('NY', 1)}
x_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : C*T : 6 : {('LA', 0), ('LA', 1), ('SF', 0), ('SF', 1), ('NY', 0), ('NY', 1)}
1 Param Declarations
demand : Size=6, Index=demand_index, Domain=Any, Default=0, Mutable=False
Key : Value
('LA', 0) : 20
('LA', 1) : 0
('NY', 0) : 20
('NY', 1) : 30
('SF', 1) : 15
1 Var Declarations
x : Size=6, Index=x_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('LA', 0) : 0 : None : None : False : True : NonNegativeReals
('LA', 1) : 0 : None : None : False : True : NonNegativeReals
('NY', 0) : 0 : None : None : False : True : NonNegativeReals
('NY', 1) : 0 : None : None : False : True : NonNegativeReals
('SF', 0) : 0 : None : None : False : True : NonNegativeReals
('SF', 1) : 0 : None : None : False : True : NonNegativeReals
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : x[NY,0] + x[NY,1] + x[LA,0] + x[SF,1]
7 Declarations: C T x_index x demand_index demand obj

Related

Pyomo - Mindtpy: Why does reformulating nonlinear exponential objective as constraints not work?

The question is why Pyomo - MindtPy is unable to get an optimal solution with nonlinear exponential function is built in constraints, while being able to get an optimal solution with nonlinear exponential function is built in objective?
The nonlinear optimization problem is
Max Total_Reach_Freq
Constraints are:
Total_Reach_Freq =[1-exp( -2.4208*x[0])] +[1-exp(-1.6278*x[1])]
8000 <= 266*x[0]+494*x[1] <= 12000, 0 <=x[0] <=1755, 0 <=x[1]<=2873, x[0] and x[1] are integers
where exp is the exponential function.
The Python code is below
import pandas as pd
import numpy as np
import pyomo.environ as pe
from pyomo.opt import SolverStatus, TerminationCondition
from pyomo.util.infeasible import log_infeasible_constraints
model = pe.ConcreteModel(name="Pyomo Test Optimization")
########### Define integer variables x[0], x[1]
### such that 0 <= x[0] <= 1755
### 0 <= x[1] <= 2873
cap_list=[1755, 2873]
def cap_rule( model, i):
return (0, cap_list[i])
model.x = pe.Var( [0, 1], within=pe.NonNegativeIntegers, bounds= cap_rule )
C=[-2.4208, -1.6278]
##### Define objective variable Total_Reach_Freq >=0
### Total_Reach_Freq =[1-pe.exp( -2.4208*x[0])] +[1-pe.exp(-1.6278*x[1])]
model.Total_Reach_Freq = pe.Var( within=pe.NonNegativeReals, bounds=(0, None) )
model.Constraint_Define_Objective= pe.Constraint(expr= (1-pe.exp(C[0]*model.x[0])) +(1-pe.exp(C[1]*model.x[1])) == model.Total_Reach_Freq )
model.objective = pe.Objective(expr=model.Total_Reach_Freq, sense= pe.maximize)
#model.objective = pe.Objective(expr=(1-pe.exp(C[0]*model.x[0])) +(1-pe.exp(C[1]*model.x[1])), sense= pe.maximize)
##### Define constraints
#### 8000 <= 266*x[0]+494*x[1] <= 12000
D=[266, 494]
model.Constraint_Budget_lb= pe.Constraint(expr= D[0]*model.x[0]+D[1]*model.x[1] >= 8000 )
model.Constraint_Budget_ub= pe.Constraint(expr= D[0]*model.x[0]+D[1]*model.x[1] <= 12000 )
model.pprint()
results=pe.SolverFactory('mindtpy').solve(model, tee=True)
log_infeasible_constraints(model)
#model.load(results)
#model.solutions.load_from(results)
print()
print("Results=", results)
status= results.solver.termination_condition
print("############################## Status ############################")
print()
print( "results.solver.status =", results.solver.status)
print("results.solver.termination_condition =", results.solver.termination_condition )
print("SolverStatus.warning =", SolverStatus.warning)
print()
print("Solution:")
print()
print( "pe.value(model.objective)=", pe.value(model.objective) )
print( "Decision variable x =", [model.x[0].value, model.x[1].value ] )
print("################################################################")
R_var= [ np.round_( 1-pe.exp( C[0]*model.x[0].value ), decimals=4), np.round_( 1-pe.exp(C[1]*model.x[1].value), decimals=4) ]
print()
print("R_i", R_var)
print()
print("sum (R_i)=", np.round_(sum(R_var), decimals=2))
This problem has optimal solution. However, the output shows a feasible solution
1 Set Declarations
x_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {0, 1}
2 Var Declarations
Total_Reach_Freq : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : None : None : False : True : NonNegativeReals
x : Size=2, Index=x_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : None : 1755 : False : True : NonNegativeIntegers
1 : 0 : None : 2873 : False : True : NonNegativeIntegers
1 Objective Declarations
objective : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : maximize : Total_Reach_Freq
3 Constraint Declarations
Constraint_Budget_lb : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 8000.0 : 266*x[0] + 494*x[1] : +Inf : True
Constraint_Budget_ub : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : -Inf : 266*x[0] + 494*x[1] : 12000.0 : True
Constraint_Define_Objective : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 0.0 : 1 - exp(-2.4208*x[0]) + 1 - exp(-1.6278*x[1]) - Total_Reach_Freq : 0.0 : True
7 Declarations: x_index x Total_Reach_Freq Constraint_Define_Objective objective Constraint_Budget_lb Constraint_Budget_ub
---------------------------------------------------------------------------------------------
Mixed-Integer Nonlinear Decomposition Toolbox in Pyomo (MindtPy)
---------------------------------------------------------------------------------------------
For more information, please visit https://pyomo.readthedocs.io/en/stable/contributed_packages/mindtpy.html
Original model has 3 constraints (1 nonlinear) and 0 disjunctions, with 3 variables, of which 0 are binary, 2 are integer, and 1 are continuous.
rNLP is the initial strategy being used.
===============================================================================================
Iteration | Subproblem Type | Objective Value | Primal Bound | Dual Bound | Gap | Time(s)
- Relaxed NLP 2 -inf 2 nan% 0.05
WARNING: DEPRECATED: The 'ignore_integrality' argument no longer has any
functionality. (deprecated in 6.4.2) (called from
1 MILP 2 -inf 2 nan% 0.17
* 1 Fixed NLP 1 1 2 100.00% 0.21
MILP main problem is infeasible. Problem may have no more feasible binary configurations.
MindtPy exiting due to MILP main problem infeasibility.
===============================================================================================
Primal integral : 0.0000
Dual integral : 0.0000
Primal-dual gap integral : 0.0000
Results=
Problem:
- Name: Pyomo Test Optimization
Lower bound: 1.0
Upper bound: 2.0000000000256444
Number of objectives: 1
Number of constraints: 3
Number of variables: 3
Number of binary variables: 0
Number of integer variables: 2
Number of continuous variables: 1
Number of nonzeros: None
Sense: maximize
Number of disjunctions: 0
Solver:
- Name: MindtPyOA
Status: ok
Message: None
User time: None
System time: None
Wallclock time: None
Termination condition: feasible
Termination message: None
Timing: Call after main solve: 1.1296011507511139e-05
Call after subproblem solve: 1.0070973075926304e-05
OA cut generation: 0.0011551158968359232
fixed subproblem: 0.028742596972733736
initialization: 0.1482729569543153
main loop: 0.07431022403761744
main: 0.0369135340442881
main_timer_start_time: 804870.380321695
total: 0.22866498795337975
Iterations: 2
Num infeasible nlp subproblem: 0
Best solution found time: 0.20502531598322093
Primal integral: 0.0
Dual integral: 0.0
Primal dual gap integral: 0.0
############################## Status ############################
results.solver.status = ok
results.solver.termination_condition = feasible
SolverStatus.warning = warning
Solution:
pe.value(model.objective)= 1.0
Decision variable x = [45.0, 0.0]
################################################################
R_i [1.0, 0.0]
sum (R_i)= 1.0
I eliminated the nonlinear constraint and instead define it in the objective function. Pyomo - Mindtpy is able to get the optimal solution. The Python code is below.
import pandas as pd
import numpy as np
import pyomo.environ as pe
from pyomo.opt import SolverStatus, TerminationCondition
from pyomo.util.infeasible import log_infeasible_constraints
model = pe.ConcreteModel(name="Pyomo Test Optimization")
########### Define integer variables x[0], x[1]
### such that 0 <= x[0] <= 1755
### 0 <= x[1] <= 2873
cap_list=[1755, 2873]
def cap_rule( model, i):
return (0, cap_list[i])
model.x = pe.Var( [0, 1], within=pe.NonNegativeIntegers, bounds= cap_rule )
C=[-2.4208, -1.6278]
##### Define objective variable Total_Reach_Freq >=0
### Total_Reach_Freq =[1-pe.exp( -2.4208*x[0])] +[1-pe.exp(-1.6278*x[1])]
# model.Total_Reach_Freq = pe.Var( within=pe.NonNegativeReals, bounds=(0, None) )
# model.Constraint_Define_Objective= pe.Constraint(expr= (1-pe.exp(C[0]*model.x[0])) +(1-pe.exp(C[1]*model.x[1])) == model.Total_Reach_Freq )
# model.objective = pe.Objective(expr=model.Total_Reach_Freq, sense= pe.maximize)
model.objective = pe.Objective(expr=(1-pe.exp(C[0]*model.x[0])) +(1-pe.exp(C[1]*model.x[1])), sense= pe.maximize)
##### Define constraints
#### 8000 <= 266*x[0]+494*x[1] <= 12000
D=[266, 494]
model.Constraint_Budget_lb= pe.Constraint(expr= D[0]*model.x[0]+D[1]*model.x[1] >= 8000 )
model.Constraint_Budget_ub= pe.Constraint(expr= D[0]*model.x[0]+D[1]*model.x[1] <= 12000 )
model.pprint()
results=pe.SolverFactory('mindtpy').solve(model, tee=True)
log_infeasible_constraints(model)
#model.load(results)
#model.solutions.load_from(results)
print()
print("Results=", results)
status= results.solver.termination_condition
print("############################## Status ############################")
print()
print( "results.solver.status =", results.solver.status)
print("results.solver.termination_condition =", results.solver.termination_condition )
print("SolverStatus.warning =", SolverStatus.warning)
print()
print("Solution:")
print()
print( "pe.value(model.objective)=", pe.value(model.objective) )
print( "Decision variable x =", [model.x[0].value, model.x[1].value ] )
print("################################################################")
R_var= [ np.round_( 1-pe.exp( C[0]*model.x[0].value ), decimals=4), np.round_( 1-pe.exp(C[1]*model.x[1].value), decimals=4) ]
print()
print("R_i", R_var)
print()
print("sum (R_i)=", np.round_(sum(R_var), decimals=2))
The output is below
1 Set Declarations
x_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {0, 1}
1 Var Declarations
x : Size=2, Index=x_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : None : 1755 : False : True : NonNegativeIntegers
1 : 0 : None : 2873 : False : True : NonNegativeIntegers
1 Objective Declarations
objective : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : maximize : 1 - exp(-2.4208*x[0]) + 1 - exp(-1.6278*x[1])
2 Constraint Declarations
Constraint_Budget_lb : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 8000.0 : 266*x[0] + 494*x[1] : +Inf : True
Constraint_Budget_ub : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : -Inf : 266*x[0] + 494*x[1] : 12000.0 : True
5 Declarations: x_index x objective Constraint_Budget_lb Constraint_Budget_ub
---------------------------------------------------------------------------------------------
Mixed-Integer Nonlinear Decomposition Toolbox in Pyomo (MindtPy)
---------------------------------------------------------------------------------------------
For more information, please visit https://pyomo.readthedocs.io/en/stable/contributed_packages/mindtpy.html
Original model has 2 constraints (0 nonlinear) and 0 disjunctions, with 2 variables, of which 0 are binary, 2 are integer, and 0 are continuous.
Objective is nonlinear. Moving it to constraint set.
rNLP is the initial strategy being used.
===============================================================================================
Iteration | Subproblem Type | Objective Value | Primal Bound | Dual Bound | Gap | Time(s)
- Relaxed NLP 2 -inf 2 nan% 0.06
WARNING: DEPRECATED: The 'ignore_integrality' argument no longer has any
functionality. (deprecated in 6.4.2) ()
1 MILP 2 -inf 2 nan% 0.18
* 1 Fixed NLP 1.99243 1.99243 2 0.38% 0.22
2 MILP 2 1.99243 2 0.38% 0.23
* 2 Fixed NLP 1.99851 1.99851 2 0.07% 0.27
MindtPy exiting on bound convergence. |Primal Bound: 1.998513324083709 - Dual Bound: 2.0| / (1e-10 + |Primal Bound|:1.998513324083709) <= relative tolerance: 0.001
===============================================================================================
Primal integral : 0.0013
Dual integral : 0.0000
Primal-dual gap integral : 0.0013
Results=
Problem:
- Name: Pyomo Test Optimization
Lower bound: 1.998513324083709
Upper bound: 2.0
Number of objectives: 1
Number of constraints: 2
Number of variables: 2
Number of binary variables: 0
Number of integer variables: 2
Number of continuous variables: 0
Number of nonzeros: None
Sense: maximize
Number of disjunctions: 0
Solver:
- Name: MindtPyOA
Status: ok
Message: None
User time: None
System time: None
Wallclock time: None
Termination condition: optimal
Termination message: None
Timing: Call after main solve: 2.035603392869234e-05
Call after subproblem solve: 1.256109680980444e-05
OA cut generation: 0.0016140680527314544
fixed subproblem: 0.06024683394934982
initialization: 0.1535441749729216
main loop: 0.10393345193006098
main: 0.02929913904517889
main_timer_start_time: 805180.471824162
total: 0.27106013789307326
Iterations: 2
Num infeasible nlp subproblem: 0
Best solution found time: 0.2668719069333747
Primal integral: 0.0013113116202245812
Dual integral: 1.0499250925580773e-09
Primal dual gap integral: 0.0013113126701496738
############################## Status ############################
results.solver.status = ok
results.solver.termination_condition = optimal
SolverStatus.warning = warning
Solution:
pe.value(model.objective)= 1.9985133053813313
Decision variable x = [23.0, 4.0]
################################################################
R_i [1.0, 0.9985]
sum (R_i)= 2.0

pyomo: an indexed variable should be linear or integer depending on the variable index

I have a indexed variable New_UnitsBuilt[p] and this variabele should be integer for the index "GasPowerplant"
but linear for the index "batterystorage".
new_units_built_set = pyo.Set(initialize=list(params.Installable_units))
model.New_UnitsBuilt = pyo.Var(new_units_built_set, domain=(pyo.NonNegativeIntegers if p="GasPowerplant" else NonNegativeReals)
Please help me how to do this in pyomo.
I am new in pyomo
Best Greetings
Gerhard
There are a couple ways you can accomplish this. For the following, I am assuming that your params.Installable_units = ["GasPowerplant", "batterystorage"]:
If the number of elements in new_units_built_set is small, then you can use a dictionary:
model.new_units_built_set = pyo.Set(initialize=list(params.Installable_units))
model.New_UnitsBuilt = pyo.Var(model.new_units_built_set,
domain={"GasPowerplant": pyo.NonNegativeIntegers, "batterystorage": pyo.NonNegativeReals})
Or if there are a lot – or there is a simple formula to get the return value – you can use a function (rule):
model.new_units_built_set = pyo.Set(initialize=list(params.Installable_units))
def _new_unitsbuilt_domain(m, p):
return pyo.NonNegativeIntegers if p=="GasPowerplant" else pyo.NonNegativeReals
model.New_UnitsBuilt = pyo.Var(model.new_units_built_set, domain=_new_unitsbuilt_domain)
Or you can just set everything to one value and override later (assuming you are using a ConcreteModel):
model.new_units_built_set = pyo.Set(initialize=list(params.Installable_units))
model.New_UnitsBuilt = pyo.Var(model.new_units_built_set, domain=pyo.NonNegativeReals)
model.New_UnitsBuilt["GasPowerplant"].domain = pyo.NonNegativeIntegers
All of these will produce:
>>> model.pprint()
1 Set Declarations
new_units_built_set : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {'GasPowerplant', 'batterystorage'}
1 Var Declarations
New_UnitsBuilt : Size=2, Index=new_units_built_set
Key : Lower : Value : Upper : Fixed : Stale : Domain
GasPowerplant : 0 : None : None : False : True : NonNegativeIntegers
batterystorage : 0 : None : None : False : True : NonNegativeReals
2 Declarations: new_units_built_set New_UnitsBuilt

Flutter sort List of Objects after two values

I have a List of CustomObjects that I need to sort. First the objects should be sorted after their property dateTime and if that is the same, it should be sorted after another property, the compare-property.
I searched for multisort and found this:
medcimentNotificationListData.sort((med1, med2) {
var r = med1.datetime.compareTo(med2.datetime);
if (r != 0) return r;
return med1.mealTimeDescription.compareValue
.compareTo(med2.mealTimeDescription.compareValue);
});
But when printing the list right after it, the list is not sorted..
medcimentNotificationListData.forEach((medicamentNotificationData) {
print(
'${medicamentNotificationData.title}, order: ${medicamentNotificationData.mealTimeDescription.compareValue}');
});
What am I missing here? Is there an easy way to multisort?
Let me know if you need any more info!
when you are calling the sort() method the function calls (a, b) { // your function} which should return either -1 , 0 or 1 . this function is called on the existing order.
at first your element a is your first element and element b is second element of the list as the existing order of the list
if your function returns -1 it means your element a should be placed before the element b therefore it places a before the b and call the function again by replacing older element b as new element a and new element b will be the element after the old b element.
if your function returns 0 it means elements a and b are both same. therefore it places a before the b and call the function again by replacing older element b as new element a.
but when your function returns the 1 it means your element a is coming after the element b. therefore the function is called again by replacing element a with the element before the old element a.
Following code shows how this is works
final List<int> list = [1, 0, 3, 4, 2 , 6, 8, 2 , 5];
list.sort((a,b) {
print("a : $a, b : $b");
int result = a.compareTo(b);
print('result : $result \n');
return result;
});
output
a : 1, b : 0
result : 1
a : 1, b : 3
result : -1
a : 3, b : 4
result : -1
a : 4, b : 2
result : 1
a : 3, b : 2
result : 1
a : 1, b : 2
result : -1
a : 4, b : 6
result : -1
a : 6, b : 8
result : -1
a : 8, b : 2
result : 1
a : 6, b : 2
result : 1
a : 4, b : 2
result : 1
a : 3, b : 2
result : 1
a : 2, b : 2
result : 0
a : 8, b : 5
result : 1
a : 6, b : 5
result : 1
a : 4, b : 5
result : -1

Pyomo: ERROR: evaluating expression: No value for uninitialized NumericValue object

I am working on an Pyomo optimization script. It is moderately complex with indexed parameters and variables and 8 constraints. If I leave the decision variables with no initial value, I get "ERROR: evaluating expression: No value for uninitialized NumericValue object" errors for constraints involving a decision variable. If I initialize the decision variables to 1 or 0 the solver(glpk) returns Status: optimal and objective function value = 0. All decision variables are also set to 0. I am looking for ideas about how to troubleshoot this. Below is relevant code (w/o data) and the output from the solver and model.display, which has been edited to make it more compact.
#Sets
#clinics
model.C = Set(initialize=list(clinics.keys()))
#clients
model.B = Set(initialize=list(client_blocks.keys()))
#scalar params
model.clt_stf_max = 10
model.tt_max = 45
model.selected_clinic_max = 4
model.stf_max = sum(staff_cap.values()) #total available staff is sum of clinic new staff capacity
model.z_M = 5000 #used in clients at selected clinics constraint
model.e_M = 500 #used in staff at selected clinics constraint
#indexed params
model.cnc_stf_cap = Param(C, initialize=staff_cap)
model.clt_blk = Param(B, initialize=client_blocks)
model.trav_time = Param(T, initialize=trav_time)
#decision vars
#x new staff at each clinic
model.new_stf = Var(model.C, domain=NonNegativeIntegers, initialize=0)
#y new clients at each clinic/block combo
model.new_clt = Var(model.C, model.B, domain=NonNegativeIntegers, initialize=0)
#z client at selected clinics only
model.z = Var(model.C, model.B, domain=Binary, initialize=0)
#e staff at selected clinics only
model.e = Var(model.C, domain=Binary, initialize=0)
#objective function
def o_min_tt_rule(model):
return sum(model.trav_time[c,b]*model.new_clt[c,b] for c in model.C for b in model.B)
model.o_min_tt = Objective(rule=o_min_tt_rule, sense=minimize)
#constraints
# limit new clients at clinic to staff capacity
def limit_clients_to_clinic_staff_cap_rule(model, c):
return sum(model.new_clt[c,b] for c in model.C for b in model.B) <= (model.cnc_stf_cap[c] * model.clt_stf_max)
model.limit_clients_to_clinic_staff_cap = Constraint(model.C, rule=limit_clients_to_clinic_staff_cap_rule)
#total of new clients served in block should not exceed the number new clients in the block
def limit_newclient_block_rule(model, b):
return sum(model.new_clt[c,b] for c in model.C for b in model.B) <= (model.clt_blk[b])
model.limit_newclient_block = Constraint(model.B, rule=limit_newclient_block_rule)
#limit new clients to selected clinics
def client_to_selected_clinic_rule(model, c, b):
return model.new_clt[c,b] <= model.z[c,b] * model.z_M
model.client_to_selected_clinic = Constraint(model.C, model.B, rule=client_to_selected_clinic_rule)
#limit single client travel time to max travel time minutes
def limit_client_travtime_rule(model, c, b):
return (model.trav_time[c,b] * model.z[c,b]) <= model.tt_max
model.limit_client_travtime = Constraint(model.C, model.B, rule=limit_client_travtime_rule)
#limit selected clinics to max number
def limit_selected_clinic_to_max_rule(model):
return summation(model.e) <= model.selected_clinic_max
model.limit_selected_clinic_to_max = Constraint(rule=limit_selected_clinic_to_max_rule,)
#limit new staff to selected clinics
def staff_to_selected_clinic_rule(model, c):
return model.new_stf[c] <= model.e[c] * model.e_M
model.staff_to_selected_clinic = Constraint(model.C, rule=staff_to_selected_clinic_rule)
#limit new staff at clinic to clinic capacity
def limit_staff_to_clnic_cap_rule(model, c):
return model.new_stf[c] <= model.cnc_stf_cap[c]
model.limit_staff_to_clnic_cap = Constraint(model.C, rule=limit_staff_to_clnic_cap_rule)
#limit total new staff to staff max
def limit_tot_staff_rule(model):
return summation(model.new_stf) <= model.stf_max
model.limit_tot_staff = Constraint(rule=limit_tot_staff_rule)
# solve the model
solver = SolverFactory("glpk", tee=True, warmstart=True, symbolic_solver_labels=True)
OUTPUT from solver and model.display()
SOLVER:
Problem:
- Name: unknown
Lower bound: 0.0
Upper bound: 0.0
Number of objectives: 1
Number of constraints: 753
Number of variables: 665
Number of nonzeros: 29213
Sense: minimize
Solver:
- Status: ok
Termination condition: optimal
Statistics:
Branch and bound:
Number of bounded subproblems: 1
Number of created subproblems: 1
Error rc: 0
Time: 0.10507559776306152
Solution:
- number of solutions: 1
number of solutions displayed: 1
- Gap: 0.0
Status: optimal
Message: None
Objective:
o_min_tt:
Value: 0
Variable: No nonzero values
Constraint: No values
MODEL:
Model (Staff_Allocation)
Variables:
new_stf : Size=4, Index=Clinics
Key : Lower : Value : Upper : Fixed : Stale : Domain
FEDCAP Counseling Center - 01004 : 0 : 0 : None : False : False : NonNegativeIntegers
The Salvation Army Belmont Center - 04002 : 0 : 0 : None : False : False : NonNegativeIntegers
VIP Wellness Center - 12000 : 0 : 0 : None : False : False : NonNegativeIntegers
Westchester Center of Excellence - 11006 : 0 : 0 : None : False : False : NonNegativeIntegers
new_clt : Size=392, Index=new_clt_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('FEDCAP Counseling Center - 01004', 360050019001022) : 0 : 0 : None : False : False : NonNegativeIntegers
z : Size=392, Index=z_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('FEDCAP Counseling Center - 01004', 360050019001022) : 0 : 0 : 1 : False : False : Binary
e : Size=4, Index=Clinics
Key : Lower : Value : Upper : Fixed : Stale : Domain
FEDCAP Counseling Center - 01004 : 0 : 0 : 1 : False : False : Binary
The Salvation Army Belmont Center - 04002 : 0 : 0 : 1 : False : False : Binary
VIP Wellness Center - 12000 : 0 : 0 : 1 : False : False : Binary
Westchester Center of Excellence - 11006 : 0 : 0 : 1 : False : False : Binary
Objectives:
o_min_tt : Size=1, Index=None, Active=True
Key : Active : Value
None : True : 0
Constraints:
limit_clients_to_clinic_staff_cap : Size=4
Key : Lower : Body : Upper
FEDCAP Counseling Center - 01004 : None : 0 : 200.0
The Salvation Army Belmont Center - 04002 : None : 0 : 150.0
VIP Wellness Center - 12000 : None : 0 : 150.0
Westchester Center of Excellence - 11006 : None : 0 : 250.0
limit_newclient_block : Size=98
Key : Lower : Body : Upper
360050019001022 : None : 0 : 1.0
.... 97 more like this
client_to_selected_clinic : Size=392
Key : Lower : Body : Upper
('FEDCAP Counseling Center - 01004', 360050019001022) : None : 0 : 0.0
.... 391 more like this
limit_client_travtime : Size=392
Key : Lower : Body : Upper
('FEDCAP Counseling Center - 01004', 360050019001022) : None : 0 : 75.0
.... 391 more like this
limit_selected_clinic_to_max : Size=1
Key : Lower : Body : Upper
None : None : 0 : 4.0
staff_to_selected_clinic : Size=4
Key : Lower : Body : Upper
FEDCAP Counseling Center - 01004 : None : 0 : 0.0
The Salvation Army Belmont Center - 04002 : None : 0 : 0.0
VIP Wellness Center - 12000 : None : 0 : 0.0
Westchester Center of Excellence - 11006 : None : 0 : 0.0
limit_staff_to_clnic_cap : Size=4
Key : Lower : Body : Upper
FEDCAP Counseling Center - 01004 : None : 0 : 4.0
The Salvation Army Belmont Center - 04002 : None : 0 : 3.0
VIP Wellness Center - 12000 : None : 0 : 3.0
Westchester Center of Excellence - 11006 : None : 0 : 5.0
limit_tot_staff : Size=1
Key : Lower : Body : Upper
None : None : 0 : 15.0

How to get most nested values?

I got a nested dictionary that looks like this:
d = {"my momma" : {"your momma" : 1}, "flying on" : {"a broom" : 2}}
I need to multiply all most nested values (the 1 and the 2) by 2.
How do I do this?
I just cant manage to access them.
Recursion, if you don't know how many nesting levels you will have:
INDEX = []
def disMantle(target, depth):
# ensure a list for given depth
while len(INDEX) <= depth: INDEX.append([])
# analyze given target
for key in target:
atype = type(target[key])
if atype == dict:
# next depth
disMantle(target[key], depth+1)
elif atype in [int,float]:
# record the numeric values
INDEX[depth].append({'key':key,'value':target[key]})
d = {"my momma" : {"your momma" : 1}, "flying on" : {"a broom" : 2.0}}
disMantle(d, 0)
print INDEX[-1]
for key in d:
for skey in d[key]:
d[key][skey] *= 2
print d