Choice of IMODE in gekko optimisation problems - python-3.x

I'm seeing here that imode=3 is equivalent to the steady-state simulation (which I guess imode=2) except that additional degrees of freedom are allowed.
How do I decide to use imode=3 instead of imode=2?
I'm doing optimization using imode=2 where I'm defining variables calculated by solver to meet constraint using m.Var & other using m.Param. What changes I need to do in variables to use imode=3 ?

Niladri,
IMODE 2 is for steady state problems with multiple data points.
Here is an example:
from gekko import GEKKO
import numpy as np
xm = np.array([0,1,2,3,4,5])
ym = np.array([0.1,0.2,0.3,0.5,1.0,0.9])
m = GEKKO()
m.x = m.Param(value=np.linspace(-1,6))
m.y = m.Var()
m.options.IMODE=2
m.cspline(m.x,m.y,xm,ym)
m.solve(disp=False)
This is a Cubic Spline approximation with multiple data points. When you switch to IMODE 3, it is very similar but it only considers one instance of your model. All of the value properties should only have 1 value such as when you optimize the Cubic spline to find the maximum value.
p = GEKKO()
p.x = p.Var(value=1,lb=0,ub=5)
p.y = p.Var()
p.cspline(p.x,p.y,xm,ym)
p.Obj(-p.y)
p.solve(disp=False)
Here is additional information on IMODE:
https://apmonitor.com/wiki/index.php/Main/OptionApmImode
https://apmonitor.com/wiki/index.php/Main/Modes
https://gekko.readthedocs.io/en/latest/imode.html
Best regards,
John Hedengren

Related

Mixed integer nonlinear programming with gekko python

I want to solve the following optimization problem using Gekko in python 3.7 window version.
Original Problem
Here, x_s are continuous variables, D and Epsilon are deterministic and they are also parameters.
However, since minimization function exists in the objective function, I remove it using binary variables(z1, z2) and then the problem becomes MINLP as follows.
Modified problem
With Gekko,
(1) Can both original problem & modified problem be solved?
(2) How can I code summation in the objective function and also D & epsilon which are parameters in Gekko?
Thanks in advance.
Both problems should be feasible with Gekko but the original appears easier to solve. Here are a few suggestions for the original problem:
Use m.Maximize() for the objective
Use sum() for the inner summation and m.sum() for outer summation for the objective function. I switch to m.sum() when the summation would create an expression that is over 15,000 characters. Using sum() creates one long expression and m.sum() breaks the summation into pieces but takes longer to compile.
Use m.min3() for the min(Dt,xs) terms or slack variables s with x[i]+s[i]=D[i]. It appears that Dt (size 30) is an upper bound, but it has different dimensions that xs (size 100). Slack variables are much more efficient than using binary variables.
D = np.array(100)
x = m.Array(m.Var,100,lb=0,ub=2000000)
The modified problem has 6000 binary variables and 100 continuous variables. There are 2^6000 potential combinations of those variables so it may take a while to solve, even with the efficient branch and bound method of APOPT. Here are a few suggestions for the modified problem:
Use matrix multiplications when possible. Below is an example of matrix operations with Gekko.
from gekko import GEKKO
import numpy as np
m = GEKKO(remote=False)
ni = 3; nj = 2; nk = 4
# solve AX=B
A = m.Array(m.Var,(ni,nj),lb=0)
X = m.Array(m.Var,(nj,nk),lb=0)
AX = np.dot(A,X)
B = m.Array(m.Var,(ni,nk),lb=0)
# equality constraints
m.Equations([AX[i,j]==B[i,j] for i in range(ni) \
for j in range(nk)])
m.Equation(5==m.sum([m.sum([A[i][j] for i in range(ni)]) \
for j in range(nj)]))
m.Equation(2==m.sum([m.sum([X[i][j] for i in range(nj)]) \
for j in range(nk)]))
# objective function
m.Minimize(m.sum([m.sum([B[i][j] for i in range(ni)]) \
for j in range(nk)]))
m.solve()
print(A)
print(X)
print(B)
Declare z1 and z2 variables as integer type with integer=True. Here is more information on using the integer type.
Solve locally with m=GEKKO(remote=False). The processing time will be large and the public server resets connections and deletes jobs every day. Switch to local mode to avoid a potential disruption.

Implement constrained optimization problem in Mystic

Is it possible to implement the following problem in mystic?
The problem minimizes a sum of squares between two (10000 by 40) matrices: Σ(X-A)^2 where X is a concatenation of four matrices (10000 by 10) and each segment is weighted (W) individually. There is also a constraint where the sum of the weights must equal 1 i.e. (W1 + W2 + W3 + W4 = 1). I'm currently using the SLSQP method in scipy optimize to get the optimal weight values but I want to determine if mystic can improve its performance. I also need to retrieve the final weight values.
from scipy.optimize import minimize
import numpy
def objective(W,X1,X2,X3,X4,A):
W1=W[0]
W2=W[1]
W3=W[2]
W4=W[3]
X=numpy.vstack((W1*X1,W2*X2,W3*X3,W4*X4))
return numpy.sum((X-A)**2)
def constraint1(W):
W1=W[0]
W2=W[1]
W3=W[2]
W4=W[3]
return W1+W2+W3+W4-1
x0=[[0.25,0.25,0.25,0.25]]
cons = {'type': 'eq', 'fun':constraint1}
#Random data only used for purposes of example
segment_1 = numpy.random.rand(10000, 10)
segment_2 = numpy.random.rand(10000, 10)
segment_3 = numpy.random.rand(10000, 10)
segment_4 = numpy.random.rand(10000, 10)
A = numpy.random.rand(10000, 40)
sol=minimize(objective,x0[0],args=(segment_1,segment_2,segment_3,segment_4,A),method='SLSQP',constraints=cons)
print(sol.x)
I'm very new to mystic so take my advice/questions with a grain of salt. I think this should be easily doable. You can almost use the same syntax, just replace the minimize function from scipy with a mystic minimizer.
Mystic offers a few minimal interface minimizers that are almost the same as the minimize function from scipy.
Some examples are diffev2, sparsity, buckshot, lattice, fmin and fminpowell.. All of these functions apply different minimization algorithms. Depending on which algorithm you'd like to use you can just insert one. For more information you should check https://mystic.readthedocs.io/en/latest/mystic.html#minimal-interface.
Cheers

Causal Inference where the treatment assignment is randomised

I have mostly worked with Observational data where the treatment assignment was not randomized. In the past, I have used PSM, IPTW to balance and then calculate ATE.
My problem is:
Now I am working on a problem where the treatment assignment is randomized meaning there won't be a confounding effect. But treatment and control groups have different sizes. There's a bucket imbalance.
Now should I just analyze the data as it is and run statistical significance and Statistical power test?
Or shall I balance the imbalance of sizes between the treatment and control using let's say covariate matching and then run significance tests?
In general, you don't need equal group sizes to estimate treatment effects.
Unequal groups will not bias the estimate, it will just affect its variance - namely, reducing the precision (recall the statistical power is determined by the smallest group, so unequal groups is less sample-efficient, but not categorically wrong).
you can further convince yourself with a simple simulation (code below). Showing that for repeated draws, the estimation is not biased (both distributions perfectly overlay), but having equal groups have improved precision (smaller standard error).
import statsmodels.api as sm
import numpy as np
import pandas as pd
import seaborn as sns
n_trials = 100
balanced = {
True: (100, 100),
False: (190, 10),
}
effect = 2.0
res = []
for i in range(n_trials):
np.random.seed(i)
noise = np.random.normal(size=sum(balanced))
for is_balanced, ratio in balanced.items():
t = np.array([0]*ratio[0] + [1]*ratio[1])
y = effect * t + noise
m = sm.OLS(y, t).fit()
res.append((is_balanced, m.params[0], m.bse[0]))
res = pd.DataFrame(res, columns=["is_balanced", "beta", "se"])
g = sns.jointplot(
x="se", y="beta",
hue="is_balanced",
data=res
)
# Annotate the true effect:
g.fig.axes[0].axhline(y=effect, color='grey', linestyle='--')
g.fig.axes[0].text(y=effect, x=res["se"].max(), s="True effect")

Solving and Graphing a Nonlinear first-order ODE

So far I've been semi-successful in solving and graphing the nonlinear ode dn/dt = n^2-2n-3 for two initial conditions, n(0)=-5 and n(0)=1, but when I add one last line to the graph with the initial condition n(0)=10, everything gets wacky, and the graph doesn't look like what it's supposed or behave like the other two lines.
the code is:
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate
#import warnings
#warnings.simplefilter('ignore')
def func(N, t):
return(N**2 - 2*N - 3)
tvec = np.arange(0,11)
s_1 = scipy.integrate.odeint(func, y0=-5,t = tvec)
s_2 = scipy.integrate.odeint(func,y0=1, t=tvec)
s_3 = scipy.integrate.odeint(func, y0 = 10, t=tvec)
%matplotlib inline
plt.plot(tvec,s_1, label="N0=-5")
plt.plot(tvec,s_2, label="N0=1")
plt.plot(tvec, s_3, label="N0=10")
plt.ylim(-5,10)
plt.legend();
the culprit here being s_3.
Any ideas on how to fix this?
Your differential equation has an unstable equilibrium point at N = 3. Any initial condition larger than 3 results in a solution that blows up in finite time. That's the mathematical statement; numerically, the values will become extremely large, and the ODE solver will eventually start generating nonsense. If any of the "nonsense" values happen to end up being less than 3, the "solution" will then converge to the stable equilibrium at N = -1.

How to solve three quadratic differential equations in Python?

I've just started to use Python for scientific drawing to plot numerical solutions of differential equations. I know how to use modules to solve and plot single differential equations, but have no idea about systems of differential equation. How can I plot following coupled system?
My system of differential equation is:
dw/dx=y and
dy/dx=-a-3*H*y and
dz/dx=-H*(1+z)
that a = 0.1 and H=sqrt((1+z)**3+w+u**2/(2*a))
And my code is:
import numpy as N
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def model(w,y,z,x,H):
dwdx=y
dydx=-a-3*H*y
dzdx=-H*(1+z)
a=0.1
H=sqrt((1+z)**3+w+u**2/(2*a))
return [w,y,z,H]
z0=1100 #initial condition
w0=-2.26e-8
y0=-.38e-4
H0=36532.63
b=0
c=10000
x=N.arange(b,c,0.01)
y=odeint(model,y0,x) #f=Function name that returns derivative values at requested y and t values as dydt = f(y,t)
w=odeint(model,w0,x)
z=odeint(model,z0,x)
plt.plot(w,x)
plt.plot(y,x)
plt.plot(z,x)
plt.legend(loc='best')
plt.show()
General purpose ODE integrators expect the dynamical system reduced to an abstract first order system. Such a system has a state vector space and the differential equation provides velocity vectors for that space. Here the state has 3 scalar components, which gives a 3D vector as state. If you want to use the components separately, the first step in the ODE function is to extract these components from the state vector, and the last step is to compose the return vector from the derivatives of the components in the correct order.
Also, you need to arrange the computation steps in order of dependence
def model(u,t):
w, y, z = u
a=0.1
H=sqrt((1+z)**3+w+u**2/(2*a))
dwdx=y
dydx=-a-3*H*y
dzdx=-H*(1+z)
return [dwdx, dydx, dzdx]
and then call the integrator once with the combined initial state
u0 = [ w0, y0, z0]
u = odeint(model, u0, x)
w,y,z = u.T
Please also check the arguments of the plot function, the general scheme is plot(x,y).

Resources