title: scipy.optimize with multiple bounds, constraints and continuous fields
body: <p>I want to optimize the operation of a <a href="https://en.wikipedia.org/wiki/Cogeneration" rel="nofollow noreferrer">CHP plant</a> over a requested power profile. Therefore I define a power profile, which should be followed by the CHP plant as much as possible.
  Multiple bounds and constraints must be applied to represent the realistic operation of a CHP plant. This for example includes that the CHP can bei either on or off and while on, its power modulation can only be set to a specific percentage range.</p>
  
  <p>Here is a minimum working example with short explanations:</p>
  
  <pre><code>import scipy.optimize as opt
  import numpy as np
  
  x = np.arange(200)  # dummy x vector
  poly_profile = np.array(  # 7th degree polynome fit of profile
      [-2.14104340e-11,  1.85108903e-08, -6.66697810e-06,  1.29239710e-03,
       -1.45110876e-01,  9.40324129e+00, -3.24548750e+02,  4.60006330e+03])
  poly_fun = np.poly1d(poly_profile)  # make poly fun
  profile = poly_fun(x[65:196])
  x0 = np.zeros_like(profile)  # all zeros as starting values
  
  def optifun(x, profile):  # define minimization fun
      return - np.sum(profile * x)
  
  bnds_hi = opt.Bounds(0.3, 1)  # upper bounds
  bnds_lo = opt.Bounds(0, 0)  # lower bounds
  
  res = opt.minimize(
      optifun, x0, args=(profile), bounds=bnds_hi,
      constraints={'type': 'eq', 'fun': lambda x:  np.sum(x*40) - 2000},
      method='SLSQP')
  plt.plot(res.x)
  plt.plot(profile)
  </code></pre>
  
  <p>So these are the bounds I want to use:</p>
  
  <ul>
  <li><code>(x == 0) or (0.3 &lt;= x &lt;= 1)</code>, for any value in the array <code>x</code><br>
  This means that x, the modulation degree of the total CHP power, can be either 0 (switched off) or <code>&gt;0.3</code> and <code>&lt;= 1</code>. But I can either specify the lower bounds <strong>OR</strong> the upper bounds. Only specifying the upper bounds makes it impossible to "switch the CHP off", while setting the lower bounds to
  <code>bnds_lo = opt.Bounds(0, 1)</code><br>
  will enable the CHP plant to operate in a non-realistic operation point (between 0% and 30% of power modulation).<br>
  Is there any way to make this work with the bounds as specified in the minimum working example? Specifically: Can I set two kinds of bounds at the same time, like <code>bounds=[bnds_lo, bnds_hi]</code>?<br>
  I guess this is a mixed integer linear programming problem, but shouldn't COBYLA or SLSQP be able to handle this? If not: Is there any workaround?</li>
  </ul>
  
  <p>And the constraints I want to use:</p>
  
  <ul>
  <li><code>np.sum(x*40) - 450</code><br>
  Limits the thermal output to some thermal storage capacity. Here 40 is the thermal output power while 450 is the remaining storage capacity. This is fairly easy to implement.</li>
  <li><p>Limit the number of starts of the CHP plant. As an example let's assume</p>
  
  <pre><code>bnds_lo = opt.Bounds(0, 1)  # lower bounds
  res = opt.minimize(
      optifun, x0, args=(profile), bounds=bnds_lo,
      constraints={'type': 'eq', 'fun': lambda x:  np.sum(x*40) - 1000},
      method='SLSQP')
  </code></pre>
  
  <p>This leads to 3 periods of CHP plant operation. Is there any way to limit this? I was thinking about adding a specific constraints function which counts the positive diffs after a leading 0, but I was not able to make anything like this work (for example since most <code>x</code> are not exactly 0, since bounds are set to <code>(0, 1)</code>. But other issues may also be the reason)...</p></li>
  <li>Set a minimum consecutive run time of the CHP plant. That means that it should be favourable to have at least, let's say 5, consecutive <code>x != 0</code>. I thought about trying something similar as in my last point (limiting the number of starts), but was also not able to work out something useful. This is by far the least important problem.</li>
  </ul>
  
  <p>To solve these issues I also tried using
  <code>scipy.optimize.LinearConstraings</code> and <code>NonlinearConstraings</code>
  But <code>method='trust-constr'</code> requires a jac (as far as I read on github this seems to be a bug) and thus I wasn't able to make it work.</p>
  
  <p>Is there any way I can make this work? Especially specifying multiple bounds is important.</p>
  
  <p>Thanks in advance!</p>
  
  <p>Sincerely,
  Scotty</p>