user18368547
user18368547

Reputation:

SciPy minimization of a SimPy simulation says 'Inequality constraints incompatible' when using only an eq constraint

So I'm trying to maximize the output of a queue chain, and after building the whole simulation I applied the "- minimization" approach. The code does run, but when I check the results, all I see is

fun: -76.0
     jac: array([2.68435456e+08, 1.34217728e+08, 2.01326592e+08])
 message: 'Inequality constraints incompatible'
    nfev: 4
     nit: 1
    njev: 1
  status: 4
 success: False
       x: array([5., 5., 5.])

being ([5,5,5]) my initial input. When I tried substituting the function with a simpler dummy, it did optimize without problems, so at least I know that the error should be in the interaction (as the simulation works on its own).

This is the pertinent code, including defining the simulation:

import simpy
import random
from scipy.optimize import minimize

b1,b2,b3=0,0,0
#4 machines

class Tandem_Model:
    def __init__(self, env):
        # self.material=simpy.Container(env, capacity=9999999999, init= 999999999)
        self.buff1 = simpy.Container(env, capacity = b1+1, init =0)
        self.buff2 = simpy.Container(env, capacity = b2+1, init =0)
        self.buff3 = simpy.Container(env, capacity = b3+1, init =0)
        self.output = simpy.Container(env, capacity = 99999999999999999999, init =0)
        

def mach1(env, tandem_model):
    while True:
        # yield tandem_model.wood.get(1)
        mach1_time = random.expovariate(1/5)
        yield env.timeout(mach1_time)
        yield tandem_model.buff1.put(1)

def mach2(env, tandem_model):
    while True:
        yield tandem_model.buff1.get(1)
        mach2_time = 6
        yield env.timeout(mach2_time)
        yield tandem_model.buff2.put(1)
        
def mach3(env, tandem_model):
    while True:
        yield tandem_model.buff2.get(1)
        mach3_time = random.expovariate(1/6)
        yield env.timeout(mach3_time)
        yield tandem_model.buff3.put(1)

def mach4(env, tandem_model):
    while True:
        yield tandem_model.buff3.get(1)
        mach4_time = random.expovariate(1/5)
        yield env.timeout(mach4_time)
        yield tandem_model.output.put(1)
  

#working hours
hours = 8
#total working time (minutes)
total_time = hours *60

b =int(input("Total amount of buffers: "))

n_buff=b
n_mach=3
bounds=[(0,b) for n in range(n_mach)]
def con(x):
    return x[0]+x[1]+x[2]-b
cons = {'type':'eq', 'fun': con}

def fmodel(x):
    env = simpy.Environment()
    tand = Tandem_Model(env)
    b1,b2,b3=x[0],x[1],x[2]
    mach1_process = env.process(mach1(env, tand))
    mach2_process = env.process(mach2(env, tand))
    mach3_process = env.process(mach3(env, tand))
    mach4_process = env.process(mach4(env, tand))
    env.run(until = total_time)
    return -(tand.output.level+tand.buff1.level+tand.buff2.level+tand.buff3.level)
          
res = minimize(
    fmodel,
    x0=(5,5,5),
    constraints=cons,
    bounds=bounds,
)

I would really appreciate the help. As an extra bit of context, the solution will be approximated to the most optimal result using integers (by calculating the output of the closest integer solutions).

Upvotes: 1

Views: 272

Answers (1)

Michael
Michael

Reputation: 1924

so if I'm reading this right, your goal is to maximize tand.output.level. But I see only a single path of machines. so it seems to me tand.output.level will be determined by your slowest machine in the line. and not by the number of buffers.

If you change fmodel's output to be just -tand.output.level and change all the machine time outs to be constants, I think you will see the same fun value regardless of the number of buffers

Would a better question be: given a 3 step process, and 4 machines, which step should I place the 4th machine? Or, given 9 machines, each with different processing rates, which step should each machine be assigned to max throughput?

finally, have you seen Pulp? its a python optimization package that uses coin for its solver.

Upvotes: 0

Related Questions