def build_controller(): c = GEKKO(remote=False) nt = 41 c.time = np.linspace(0, 6, nt) Tc = c.MV(value=300) q = c.Param(value=100) V = c.Param(value=100) rho = c.Param(value=1000) Cp = c.Param(value=0.239) mdelH = c.Param(value=50000) ER = c.Param(value=8000) k0 = c.Param(value=7.2 * 10**8) UA = c.Param(value=5 * 10**5) Ca0 = c.Param(value=1) T0 = c.Param(value=350) Ca = c.CV(value=.8, ub=1, lb=0) T = c.CV(value=325, lb=250, ub=500) k = c.Var() rate = c.Var() c.Equation(k == k0 * c.exp(-ER / T)) c.Equation(rate == k * Ca) c.Equation(V * Ca.dt() == q * (Ca0 - Ca) - V * rate) c.Equation(rho * Cp * V * T.dt() == q * rho * Cp * (T0 - T) + V * mdelH * rate + UA * (Tc - T)) #Global options c.options.IMODE = 6 c.options.NODES = 2 c.options.CV_TYPE = 2 c.options.MAX_ITER = 750 c.options.TIME_SHIFT = 0 #MV tuning Tc.STATUS = 1 Tc.DCOST = .01 #Tc.DMAX = 10 Tc.LOWER = 250 Tc.UPPER = 450 #CV Tuning Ca.STATUS = 1 Ca.TR_INIT = 0 Ca.TAU = 1 T.STATUS = 0 return c, T, Tc, Ca
def solve08(): # Nonlinear Regression # measurements xm = np.array([0, 1, 2, 3, 4, 5]) ym = np.array([0.1, 0.2, 0.3, 0.5, 0.8, 2.0]) # GEKKO model m = GEKKO() # parameters x = m.Param(value=xm) a = m.FV() a.STATUS = 1 # variables y = m.CV(value=ym) y.FSTATUS = 1 # regression equation m.Equation(y == 0.1 * m.exp(a * x)) # regression mode m.options.IMODE = 2 # optimize m.solve(disp=False) # print parameters print('Optimized, a = ' + str(a.value[0])) plt.plot(xm, ym, 'bo') plt.plot(xm, y.value, 'r-') plt.show()
def initGekko(alpha, beta, paddle, last_move): m = GEKKO() m.WEB = 0 m.options.SOLVER = 1 # APOPT is an MINLP solver # optional solver settings with APOPT m.solver_options = ['minlp_maximum_iterations 500', \ # minlp iterations with integer solution 'minlp_max_iter_with_int_sol 10', \ # treat minlp as nlp 'minlp_as_nlp 0', \ # nlp sub-problem max iterations 'nlp_maximum_iterations 50', \ # 1 = depth first, 2 = breadth first 'minlp_branch_method 1', \ # maximum deviation from whole number 'minlp_integer_tol 0.1', \ # covergence tolerance 'minlp_gap_tol 0.01'] m.time = [0, 1, 2, 3] # control variable u = m.MV(lb=-1, ub=1, integer=True) u.DCOST = 0.1 # parameters alpha = m.Param(value=alpha) beta = m.Param(value=beta) # need need the last control vector ulast = m.Var() m.delay(u, ulast, 1) #variable y = m.CV(paddle) #equation m.Equation(y.dt() == (alpha * u) + (beta * ulast)) #options m.options.IMODE = 6 m.options.NODES = 2 m.options.CV_TYPE = 1 y.STATUS = 1 y.FSTATUS = 1 # to do get this from input y.SPHI = 25 y.SPLO = 25 y.TAU = 0 y.TR_INIT = 2 u.STATUS = 1 u.FSTATUS = 0 return m, y, u
def solve11(): # error # Moving Horizon Estimation # Estimator Model m = GEKKO() m.time = p.time # Parameters m.u = m.MV(value=u_meas) #input m.K = m.FV(value=1, lb=1, ub=3) # gain m.tau = m.FV(value=5, lb=1, ub=10) # time constant # Variables m.x = m.SV() #state variable m.y = m.CV(value=y_meas) #measurement # Equations m.Equations([m.tau * m.x.dt() == -m.x + m.u, m.y == m.K * m.x]) # Options m.options.IMODE = 5 #MHE m.options.EV_TYPE = 1 # STATUS = 0, optimizer doesn't adjust value # STATUS = 1, optimizer can adjust m.u.STATUS = 0 m.K.STATUS = 1 m.tau.STATUS = 1 m.y.STATUS = 1 # FSTATUS = 0, no measurement # FSTATUS = 1, measurement used to update model m.u.FSTATUS = 1 m.K.FSTATUS = 0 m.tau.FSTATUS = 0 m.y.FSTATUS = 1 # DMAX = maximum movement each cycle m.K.DMAX = 2.0 m.tau.DMAX = 4.0 # MEAS_GAP = dead-band for measurement / model mismatch m.y.MEAS_GAP = 0.25 # solve m.solve(disp=False) # Plot results plt.subplot(2, 1, 1) plt.plot(m.time, u_meas, 'b:', label='Input (u) meas') plt.legend() plt.subplot(2, 1, 2) plt.plot(m.time, y_meas, 'gx', label='Output (y) meas') plt.plot(p.time, p.y.value, 'k-', label='Output (y) actual') plt.plot(m.time, m.y.value, 'r--', label='Output (y) estimated') plt.legend() plt.show()
def solve12(): # Model Predictive Control m = GEKKO() m.time = np.linspace(0, 20, 41) # Parameters mass = 500 b = m.Param(value=50) K = m.Param(value=0.8) # Manipulated variable p = m.MV(value=0, lb=0, ub=100) p.STATUS = 1 # allow optimizer to change p.DCOST = 0.1 # smooth out gas pedal movement p.DMAX = 20 # slow down change of gas pedal # Controlled Variable v = m.CV(value=0) v.STATUS = 1 # add the SP to the objective m.options.CV_TYPE = 2 # squared error v.SP = 40 # set point v.TR_INIT = 1 # set point trajectory v.TAU = 5 # time constant of trajectory # Process model m.Equation(mass * v.dt() == -v * b + K * b * p) m.options.IMODE = 6 # control m.solve(disp=False) # get additional solution information import json with open(m.path + '//results.json') as f: results = json.load(f) plt.figure() plt.subplot(2, 1, 1) plt.plot(m.time, p.value, 'b-', label='MV Optimized') plt.legend() plt.ylabel('Input') plt.subplot(2, 1, 2) plt.plot(m.time, results['v1.tr'], 'k-', label='Reference Trajectory') plt.plot(m.time, v.value, 'r--', label='CV Response') plt.ylabel('Output') plt.xlabel('Time') plt.legend(loc='best') plt.show()
def solve07(): # Linear and Polynomial Regression xm = np.array([0, 1, 2, 3, 4, 5]) ym = np.array([0.1, 0.2, 0.3, 0.5, 1.0, 0.9]) xm = np.array([0, 1, 2, 3, 4, 5]) ym = np.array([0.1, 0.2, 0.3, 0.5, 0.8, 2.0]) #### Solution m = GEKKO() m.options.IMODE = 2 # coefficients c = [m.FV(value=0) for i in range(4)] x = m.Param(value=xm) y = m.CV(value=ym) y.FSTATUS = 1 # polynomial model m.Equation(y == c[0] + c[1] * x + c[2] * x**2 + c[3] * x**3) # linear regression c[0].STATUS = 1 c[1].STATUS = 1 m.solve(disp=False) p1 = [c[1].value[0], c[0].value[0]] # quadratic c[2].STATUS = 1 m.solve(disp=False) p2 = [c[2].value[0], c[1].value[0], c[0].value[0]] # cubic c[3].STATUS = 1 m.solve(disp=False) p3 = [c[3].value[0], c[2].value[0], c[1].value[0], c[0].value[0]] # plot fit plt.plot(xm, ym, 'ko', markersize=10) xp = np.linspace(0, 5, 100) plt.plot(xp, np.polyval(p1, xp), 'b--', linewidth=2) plt.plot(xp, np.polyval(p2, xp), 'r--', linewidth=3) plt.plot(xp, np.polyval(p3, xp), 'g:', linewidth=2) plt.legend(['Data', 'Linear', 'Quadratic', 'Cubic'], loc='best') plt.xlabel('x') plt.ylabel('y') plt.show()
def SS(A, B, C, D=None): """ Build a GEKKO from SS representation. Give A,B,C and D, returns: m (GEKKO model) x (states) y (outputs) u (inputs) """ #set all matricies to numpy A = np.array(A) B = np.array(B) C = np.array(C) if D != None: #D is supplied D = np.array(D) #count number of states, inputs and outputs nx = A.shape[0] ny = C.shape[0] nu = B.shape[1] #initialize GEKKO Model m = GEKKO() #define arrays of states, outputs and inputs x = [m.SV() for i in np.arange(nx)] y = [m.CV() for i in np.arange(ny)] u = [m.MV() for i in np.arange(nu)] #build equations for states state_eqs = np.dot(A, x) + np.dot(B, u) [m.Equation(state_eqs[i] == x[i].dt()) for i in range(nx)] #build equations for outputs if D != None: output_eqs = np.dot(C, x) + np.dot(D, u) else: output_eqs = np.dot(C, x) [m.Equation(output_eqs[i] == y[i].dt()) for i in range(ny)] return m, x, y, u
# Measured inputs Q1 = m.Param() Q2 = m.Param() Ta = 21.0 + 273.15 # K mass = 4.0 / 1000.0 # kg Cp = 0.5 * 1000.0 # J/kg-K A = 10.0 / 100.0**2 # Area not between heaters in m^2 As = 2.0 / 100.0**2 # Area between heaters in m^2 eps = 0.9 # Emissivity sigma = 5.67e-8 # Stefan-Boltzmann TH1 = m.SV() TH2 = m.SV() TC1 = m.CV() TC2 = m.CV() # Heater Temperatures in Kelvin T1 = m.Intermediate(TH1 + 273.15) T2 = m.Intermediate(TH2 + 273.15) # Heat transfer between two heaters Q_C12 = m.Intermediate(Us * As * (T2 - T1)) # Convective Q_R12 = m.Intermediate(eps * sigma * As * (T2**4 - T1**4)) # Radiative # Energy balances m.Equation(TH1.dt() == (1.0/(mass*Cp))*(U*A*(Ta-T1) \ + eps * sigma * A * (Ta**4 - T1**4) \ + Q_C12 + Q_R12 \ + alpha1*Q1))
import numpy as np from random import random from gekko import GEKKO import matplotlib.pyplot as plt #----- Process Simulation Setup -----# p = GEKKO(remote=False) p.time = np.linspace(0, 0.5, 0.01) p.dl = p.MV() p.beta = p.Param(value=0.05) p.g = p.CV() p.t = p.Param(value=p.time) A = 20 K = 300 p.Equation(p.exp(-p.t * p.beta) * p.g.dt() == p.dl) p.options.IMODE = 4 #----- Moving Horizon Estimation Model Setup -----# mhe = GEKKO(remote=False) mhe.time = np.linspace(0, 0.5, 0.01) mhe.dl = mhe.MV() #output mhe.beta = mhe.FV(value=0.01, lb=0.0000001, ub=0.5) mhe.g = mhe.CV() #measured variable mhe.t = mhe.Param(value=mhe.time) mhe.Equation(mhe.dl == mhe.exp(-mhe.t * mhe.beta) * mhe.g.dt()) mhe.options.IMODE = 5 mhe.options.EV_TYPE = 1 mhe.options.DIAGLEVEL = 0
# taus = second order time constant # zeta = damping factor (zeta>1 for overdamped) T = ? return T # Connect to Arduino a = tclab.TCLab() # Second order model of TCLab m = GEKKO(remote=False) Kp = m.FV(1.0,lb=0.5,ub=2.0) taus = m.FV(50,lb=10,ub=200) zeta = m.FV(1.2,lb=1.1,ub=5) y0 = a.T1 u = m.MV(0) x = m.Var(y0); y = m.CV(y0) m.Equation(x==y.dt()) m.Equation((taus**2)*x.dt()+2*zeta*taus*y.dt()+(y-y0) == Kp*u) m.options.IMODE = 5 m.options.NODES = 2 m.time = np.linspace(0,200,101) m.solve(disp=False) y.FSTATUS = 1 # Turn LED on print('LED On') a.LED(100) # Run time in minutes run_time = 5
#%% Model #Initialize model m = GEKKO() #time array m.time = np.arange(50) #Parameters u = m.Param(value=42) d = m.FV(value=0) Cv = m.Param(value=1) tau = m.Param(value=0.1) #Variable flow = m.CV(value=42) #Equation m.Equation(tau * flow.dt() == -flow + Cv * u + d) # Options m.options.imode = 5 m.options.ev_type = 1 #start with l1 norm m.options.coldstart = 1 d.status = 1 flow.fstatus = 1 flow.wmeas = 100 flow.wmodel = 0 #flow.dcost = 0
] #%% Model m = GEKKO() #time m.time = np.linspace(0, 15, 61) #parameters to estimate lg10_kr = [m.FV(value=lkr[i]) for i in range(6)] #variables kr = [m.Var() for i in range(6)] H = m.Var(value=1e6) I = m.Var(value=0) V = m.Var(value=1e2) #Variable to match with data LV = m.CV(value=2) #equations m.Equations([10**lg10_kr[i] == kr[i] for i in range(6)]) m.Equations([ H.dt() == kr[0] - kr[1] * H - kr[2] * H * V, I.dt() == kr[2] * H * V - kr[3] * I, V.dt() == -kr[2] * H * V - kr[4] * V + kr[5] * I, LV == m.log10(V) ]) #%% Estimation ## Global options m.options.IMODE = 5 #switch to estimation m.options.TIME_SHIFT = 0 #don't timeshift on new solve m.options.EV_TYPE = 2 #l2 norm m.options.COLDSTART = 2
from StokesSingularities import * #This iteration includes interaction forces IV = [50, 50] #Initial position g = GEKKO(remote=True) nt = 400 #number of timesteps g.time = np.linspace(0, 100, nt) #STATUS = 1 implies that the variable is being optimized by the solver #DCOST is the amount which is added to the cost function when the variable is modified -> this prevents blowup # These are the coordinates of the passive particle y1 = g.CV(value=IV[0]) y1.LOWER = -100 y1.UPPER = 100 y2 = g.CV(value=IV[1]) y2.LOWER = -100 y2.UPPER = 100 x11 = g.Var(value=2, lb=1, ub=3) x12 = g.Var(value=0, lb=-1, ub=1) x21 = g.Var(value=0, lb=-1, ub=1) x22 = g.Var(value=0, lb=-1, ub=1) v11 = g.MV(value=0) v11.STATUS = 0 v12 = g.MV(value=0) v12.STATUS = 1
class gekko_model(): def __init__(self, x0, param0, physics0, x_target): x_pos = x0[0] y_pos = x0[1] x_vel = x0[2] y_vel = x0[3] heading = x0[4] ang_vel = x0[5] SPS_mass = x0[6] RCS_mass = x0[7] dry_mass = param0[0] SPS_thrust = param0[1] RCS_thrust = param0[2] SPS_mass_flow = param0[3] RCS_mass_flow = param0[4] J = param0[5] r = param0[6] x_pos_t = x_target[0] y_pos_t = x_target[1] x_vel_t = x_target[2] y_vel_t = x_target[3] mu = physics0[0] self.m = GEKKO(remote=False) self.x_t = self.m.Var(value=x_pos_t) self.y_t = self.m.Var(value=y_pos_t) self.x_vel_t = self.m.Var(value=x_vel_t) self.y_vel_t = self.m.Var(value=y_vel_t) self.dry_mass = self.m.Param(value=dry_mass) self.mu = self.m.Param(value=mu) self.SPS_flow = self.m.FV(value=SPS_mass_flow, lb=0, ub=SPS_mass) self.RCS_flow = self.m.FV(value=RCS_mass_flow, lb=0, ub=RCS_mass) self.r = self.m.Param(value=r) self.RCS_bias = self.m.FV(value=1.0, ub=1.5, lb=.5) self.SPS_bias = self.m.FV(value=1.0, ub=1.5, lb=.5) self.RCS_com = self.m.MV(value=0, lb=-1, ub=1, integer=True) self.SPS_com = self.m.MV(value=0, lb=0, ub=1, integer=True) self.x = self.m.CV(value=x_pos, name='x') self.y = self.m.CV(value=y_pos, name='y') self.x_vel = self.m.CV(value=x_vel, name='x_vel') self.y_vel = self.m.CV(value=y_vel, name='y_vel') self.heading = self.m.CV(value=heading, name='heading') self.ang_vel = self.m.CV(value=ang_vel, name='ang_vel') self.SPS_mass = self.m.Var(value=SPS_mass, lb=0, ub=SPS_mass, name='SPS_mass') self.RCS_mass = self.m.Var(value=RCS_mass, lb=0, ub=RCS_mass, name='RCS_mass') self.J = self.m.FV(value=J) self.SPS_thrust = self.m.FV(value=SPS_thrust) self.RCS_thrust = self.m.FV(value=RCS_thrust) self.SPS_thrust_f = self.m.Intermediate( self.SPS_com * self.SPS_thrust * self.SPS_bias) self.RCS_thrust_f = self.m.Intermediate( self.RCS_com * self.RCS_thrust * self.RCS_bias) self.d_t = self.m.Intermediate(self.m.sqrt(self.x_t**2 + self.y_t**2)) self.r_dd_t = self.m.Intermediate(-self.mu / self.d_t**3) self.mass_t = self.m.Intermediate(self.dry_mass + self.RCS_mass + self.SPS_mass) self.d = self.m.Intermediate(self.m.sqrt(self.x**2 + self.y**2)) self.r_dd = self.m.Intermediate(-self.mu / (self.d**3)) self.x_accel_g = self.m.Intermediate(self.x * self.r_dd) self.y_accel_g = self.m.Intermediate(self.y * self.r_dd) self.x_accel_SPS = self.m.Intermediate( self.SPS_thrust_f * self.m.sin(self.heading) / self.mass_t) self.y_accel_SPS = self.m.Intermediate( self.SPS_thrust_f * self.m.cos(self.heading) / self.mass_t) self.phase = self.m.Intermediate(self.m.atan(self.x / self.y)) self.phase_t = self.m.Intermediate(self.m.atan(self.x_t / self.y_t)) self.m.Equation(self.x.dt() == self.x_vel) self.m.Equation(self.y.dt() == self.y_vel) self.m.Equation(self.x_vel.dt() == self.x_accel_g + self.x_accel_SPS) self.m.Equation(self.y_vel.dt() == self.y_accel_g + self.y_accel_SPS) self.m.Equation(self.heading.dt() == self.ang_vel) self.m.Equation(self.ang_vel.dt() == self.RCS_thrust_f * self.r / self.J) self.m.Equation(self.SPS_mass.dt() == -self.SPS_flow * self.SPS_com * self.SPS_bias) self.m.Equation(self.RCS_mass.dt() == -self.RCS_flow * self.m.abs(self.RCS_com) * self.RCS_bias) self.m.Equation(self.x_t.dt() == self.x_vel_t) self.m.Equation(self.y_t.dt() == self.y_vel_t) self.m.Equation(self.x_vel_t.dt() == self.x_t * self.r_dd_t) self.m.Equation(self.y_vel_t.dt() == self.y_t * self.r_dd_t) def mpc_setup(self, time): self.m.time = time p = np.zeros(len(time)) p[-2:] = 1 p[:] = 1 self.final = self.m.Param(value=p) self.RCS_com.STATUS = 1 self.SPS_com.STATUS = 1 self.m.options.MAX_ITER = 1000 self.m.Equation( self.d >= 6471000 ) #Distance must be larger than the radius of the Earth + 100 km self.m.Equation(self.RCS_mass >= 0) #Must have positive mass in tanks self.m.Equation(self.SPS_mass >= 0) self.m.Equation(self.m.abs(self.ang_vel) <= 2 * 3.14) self.m.Obj((self.final * (self.d - self.d_t)**2)) self.m.Obj(1e12 * self.final * (self.phase - self.phase_t)**2) self.m.Obj((self.m.sqrt(self.x_vel**2 + self.y_vel**2) - self.m.sqrt(self.x_vel_t**2 + self.y_vel_t**2))**2) self.m.options.IMODE = 6 def mpc_update(self, x0, x_target): x_pos = x0[0] y_pos = x0[1] x_vel = x0[2] y_vel = x0[3] heading = x0[4] ang_vel = x0[5] SPS_mass = x0[6] RCS_mass = x0[7] x_pos_t = x_target[0] y_pos_t = x_target[1] x_vel_t = x_target[2] y_vel_t = x_target[3] self.x.VALUE = x_pos self.y.VALUE = y_pos self.x_vel.VALUE = x_vel self.y_vel.VALUE = y_vel self.heading.VALUE = heading self.ang_vel.VALUE = ang_vel self.SPS_mass.VALUE = SPS_mass self.RCS_mass.VALUE = RCS_mass self.x_t.VALUE = x_pos_t self.y_t.VALUE = y_pos_t self.x_vel_t.VALUE = x_vel_t self.y_vel_t.VALUE = y_vel_t def mpc_solve(self): try: self.m.solve(disp=False) print("Finished") RCS_com = self.RCS_com.NEWVAL SPS_com = self.SPS_com.NEWVAL except: print("Did not finish") RCS_com = 0 SPS_com = 0 return ([SPS_com, RCS_com]) def mhe_setup(self, time): self.m.time = time self.m.options.EV_TYPE = 1 self.m.options.IMODE = 5 self.m.options.ICD_CALC = 1 def mhe_on(self): self.x.FSTATUS = 1 #Receive measurements self.y.FSTATUS = 1 self.ang_vel.FSTATUS = 1 self.RCS_com.FSTATUS = 1 self.SPS_com.FSTATUS = 1 self.SPS_bias.FSTATUS = 0 self.RCS_bias.FSTATUS = 0 self.x.STATUS = 1 self.y.STATUS = 1 self.ang_vel.STATUS = 1 self.RCS_com.STATUS = 0 self.SPS_com.STATUS = 0 self.SPS_bias.STATUS = 1 self.RCS_bias.STATUS = 1 self.SPS_bias.DMAX = .05 self.RCS_bias.DMAX = .05 def mhe_add(self, x, y, ang_vel, SPS_com, RCS_com): self.x.MEAS = x self.y.MEAS = y self.ang_vel.MEAS = ang_vel self.SPS_com.MEAS = SPS_com self.RCS_com.MEAS = RCS_com def mhe_solve(self, x, y, ang_vel, SPS_com, RCS_com): self.x.MEAS = x self.y.MEAS = y self.ang_vel.MEAS = ang_vel self.SPS_com.MEAS = SPS_com self.RCS_com.MEAS = RCS_com self.m.solve(disp=False) return ([self.SPS_bias.NEWVAL, self.RCS_bias.NEWVAL], [self.x.MODEL, self.y.MODEL, self.ang_vel.MODEL]) def sim_setup(self, time): self.m.time = time self.RCS_com.FSTATUS = 1 self.SPS_com.FSTATUS = 1 self.m.options.SOLVER = 3 self.m.options.IMODE = 4 def sim_solve(self, SPS_com, RCS_com): self.RCS_com.MEAS = RCS_com self.SPS_com.MEAS = SPS_com self.SPS_com.STATUS = 0 self.RCS_com.STATUS = 0 self.m.solve(disp=False) return ([self.x.MODEL, self.y.MODEL, self.ang_vel.MODEL])
#Parameter to Estimate UA_mhe = m.FV(value=10 * 10**4, name='ua') UA_mhe.STATUS = 1 #estimate UA_mhe.FSTATUS = 0 #no measurements #upper and lower bounds for optimizer UA_mhe.LOWER = 10000 UA_mhe.UPPER = 100000 #Measurement input Tc_mhe = m.MV(value=300, name='tc') Tc_mhe.STATUS = 0 #don't estimate Tc_mhe.FSTATUS = 1 #receive measurement #Measurement to match simulation with T_mhe = m.CV(value=325, lb=250, ub=500, name='t') T_mhe.STATUS = 1 #minimize error between simulation and measurement T_mhe.FSTATUS = 1 #receive measurement T_mhe.MEAS_GAP = 0.1 #measurement deadband gap #State to watch Ca_mhe = m.SV(value=0.8, ub=1, lb=0, name='ca') #Other parameters q = m.Param(value=100) V = m.Param(value=100) rho = m.Param(value=1000) Cp = m.Param(value=0.239) mdelH = m.Param(value=50000) ER = m.Param(value=8750) k0 = m.Param(value=7.2 * 10**10)
# Measured inputs Q1 = m.MV(value=0, name='q1') Q1.STATUS = 0 # don't estimate Q1.FSTATUS = 1 # receive measurement Q2 = m.MV(value=0, name='q2') Q2.STATUS = 0 # don't estimate Q2.FSTATUS = 1 # receive measurement # State variables TH1 = m.SV(value=T1m[0], name='th1') TH2 = m.SV(value=T2m[0], name='th2') # Measurements for model alignment TC1 = m.CV(value=T1m[0], name='tc1') TC1.STATUS = 1 # minimize error between simulation and measurement TC1.FSTATUS = 1 # receive measurement TC1.MEAS_GAP = 0.1 # measurement deadband gap TC1.LOWER = 0 TC1.UPPER = 200 TC2 = m.CV(value=T2m[0], name='tc2') TC2.STATUS = 1 # minimize error between simulation and measurement TC2.FSTATUS = 1 # receive measurement TC2.MEAS_GAP = 0.1 # measurement deadband gap TC2.LOWER = 0 TC2.UPPER = 200 Ta = m.Param(value=23.0 + 273.15) # K mass = m.Param(value=4.0 / 1000.0) # kg
from gekko import GEKKO # noise level noise = 0.2 #%% Process p = GEKKO(remote=False) p.time = [0,.5] #time discretization #Parameters p.u = p.MV() p.K = p.Param(value=1.25) #gain p.tau = p.Param(value=8) #time constant #variable p.y = p.CV(1) #measurement #Equations p.Equation(p.tau * p.y.dt() == -p.y + p.K * p.u) #options p.options.IMODE = 4 p.options.NODES = 4 def process_simulator(meas): if meas is not None: p.u.MEAS = meas p.solve(disp=False) return p.y.MODEL + (random()-0.5)*noise
70.0,4.0,392,350 80.0,4.0,407,345 90.0,4.0,426,340 100.0,4.0,445,340 ''' fid = open('data.csv','w') fid.write(eofile) fid.close() m = GEKKO() nt = 101 m.time = np.linspace(0,100,nt) eo_collect = m.CV(value=0,lb=0) eo_collect.STATUS = 1 usp = np.zeros(nt) usp[0:]=550 #usp[10:]=500 u = m.MV(value=usp,lb=340,ub=550) u.STATUS = 1 u.DMAX = 4 flow = m.Var(value=10,lb=0) eo_frac = m.Var(value=0.01,lb=0) eo_tot = m.Var(value=0,lb=0) K = m.FV(value=0.0198)
#p.u.STATUS = 0 #%% Model m = GEKKO() m.time = np.linspace(0, 20, 41) #0-20 by 0.5 -- discretization must match simulation #Parameters m.u = m.MV() #input m.K = m.FV(value=1, lb=1, ub=3) #gain m.tau = m.FV(value=5, lb=1, ub=10) #time constant #Variables m.x = m.SV() #state variable m.y = m.CV() #measurement #Equations m.Equations([m.tau * m.x.dt() == -m.x + m.u, m.y == m.K * m.x]) #Options m.options.IMODE = 5 #MHE m.options.EV_TYPE = 1 # STATUS = 0, optimizer doesn't adjust value # STATUS = 1, optimizer can adjust m.u.STATUS = 0 m.K.STATUS = 1 m.tau.STATUS = 1 m.y.STATUS = 1
from scipy import optimize import matplotlib.pyplot as plt from gekko import GEKKO import numpy as np m = GEKKO() m.options.SOLVER = 3 m.options.IMODE = 2 xzd = np.linspace(1,5,100) yzd = np.sin(xzd) xz = m.Param(value=xzd) yz = m.CV(value=yzd) yz.FSTATUS = 1 xp_val = np.array([1, 2, 3, 3.5, 4, 5]) yp_val = np.array([1, 0, 2, 2.5, 2.8, 3]) xp = [m.FV(value=xp_val[i],lb=xp_val[0],ub=xp_val[-1]) for i in range(6)] yp = [m.FV(value=yp_val[i]) for i in range(6)] for i in range(6): xp[i].STATUS = 0 yp[i].STATUS = 1 for i in range(5): m.Equation(xp[i+1]>=xp[i]+0.05) x = [m.Var(lb=xp[i],ub=xp[i+1]) for i in range(5)] x[0].lower = -1e20 x[-1].upper = 1e20 # Variables slk_u = [m.Var(value=1,lb=0) for i in range(4)] slk_l = [m.Var(value=1,lb=0) for i in range(4)] # Intermediates slope = [] for i in range(5):
class Brain(): def __init__(self, remote=True, bfgs=True, explicit=True): self.m = GEKKO(remote=remote) #generic model options self.m.options.MAX_ITER = 4000 self.m.options.OTOL = 1e-4 self.m.options.RTOL = 1e-4 if bfgs: self.m.solver_options = ['hessian_approximation limited-memory'] self._explicit = explicit self._input_size = None self._output_size = None self._layers = [] self._weights = [] self._biases = [] self.input = [] self.output = [] def input_layer(self, size): #store input size self._input_size = size #build FV with Feedback to accept inputs self.input = [self.m.Param() for _ in range(size)] # #set FV options # for n in self.input: # n.FSTATUS = 1 # n.STATUS = 0 #add input layer to list of layers self._layers.append(self.input) def layer(self, linear=0, relu=0, tanh=0, gaussian=0, bent=0, leaky=0, ltype='dense'): """ Layer types: dense convolution pool (mean) Activation options: none softmax relu tanh sigmoid linear """ size = relu + tanh + linear + gaussian + bent + leaky if size < 1: raise Exception("Need at least one node") if ltype == 'dense': ## weights between neurons n_p = len(self._layers[-1]) #number of neuron in previous layer n_c = n_p * size # number of axion connections # build n_c FVs as axion weights, initialize randomly in [-1,1] self._weights.append([ self.m.FV(value=[np.random.rand() * 2 - 1]) for _ in range(n_c) ]) for w in self._weights[-1]: w.STATUS = 1 w.FSTATUS = 0 #input times weights, add bias and activate self._biases.append([self.m.FV(value=0) for _ in range(size)]) for b in self._biases[-1]: b.STATUS = 1 b.FSTATUS = 0 count = 0 if self._explicit: # build new neuron weighted inputs neuron_inputs = [ self.m.Intermediate(self._biases[-1][i] + sum( (self._weights[-1][(i * n_p) + j] * self._layers[-1][j]) for j in range(n_p))) for i in range(size) ] #i counts nodes in this layer, j counts nodes of previous layer ##neuron activation self._layers.append([]) if linear > 0: self._layers[-1] += [ self.m.Intermediate(neuron_inputs[i]) for i in range(count, count + linear) ] count += linear if tanh > 0: self._layers[-1] += [ self.m.Intermediate(self.m.tanh(neuron_inputs[i])) for i in range(count, count + tanh) ] count += tanh if relu > 0: self._layers[-1] += [ self.m.Intermediate( self.m.log(1 + self.m.exp(neuron_inputs[i]))) for i in range(count, count + relu) ] count += relu if gaussian > 0: self._layers[-1] += [ self.m.Intermediate(self.m.exp(-neuron_inputs[i]**2)) for i in range(count, count + gaussian) ] count += gaussian if bent > 0: self._layers[-1] += [ self.m.Intermediate( (self.m.sqrt(neuron_inputs[i]**2 + 1) - 1) / 2 + neuron_inputs[i]) for i in range(count, count + bent) ] count += bent if leaky > 0: s = [self.m.Var(lb=0) for _ in range(leaky * 2)] self.m.Equations([ (1.5 * neuron_inputs[i + count]) - (0.5 * neuron_inputs[i + count]) == s[2 * i] - s[2 * i + 1] for i in range(leaky) ]) self._layers[-1] += [ self.m.Intermediate(neuron_inputs[count + i] + s[2 * i]) for i in range(leaky) ] [self.m.Obj(s[2 * i] * s[2 * i + 1]) for i in range(leaky)] self.m.Equations( [s[2 * i] * s[2 * i + 1] == 0 for i in range(leaky)]) count += leaky else: #type=implicit # build new neuron weighted inputs neuron_inputs = [self.m.Var() for i in range(size)] self.m.Equations( [ neuron_inputs[i] == self._biases[-1][i] + sum( (self._weights[-1][(i * n_p) + j] * self._layers[-1][j]) for j in range(n_p)) for i in range(size) ] ) #i counts nodes in this layer, j counts nodes of previous layer ##neuron activation neurons = [self.m.Var() for i in range(size)] self._layers.append(neurons) ##neuron activation if linear > 0: self.m.Equations([ neurons[i] == neuron_inputs[i] for i in range(count, count + linear) ]) count += linear if tanh > 0: self.m.Equations([ neurons[i] == self.m.tanh(neuron_inputs[i]) for i in range(count, count + tanh) ]) for n in neurons[count:count + tanh]: n.LOWER = -5 n.UPPER = 5 count += tanh if relu > 0: self.m.Equations([ neurons[i] == self.m.log(1 + self.m.exp(neuron_inputs[i])) for i in range(count, count + relu) ]) for n in neurons[count:count + relu]: n.LOWER = -10 count += relu if gaussian > 0: self.m.Equations([ neurons[i] == self.m.exp(-neuron_inputs[i]**2) for i in range(count, count + gaussian) ]) for n in neurons[count:count + gaussian]: n.LOWER = -3.5 n.UPPER = 3.5 count += gaussian if bent > 0: self.m.Equations([ neurons[i] == ( (self.m.sqrt(neuron_inputs[i]**2 + 1) - 1) / 2 + neuron_inputs[i]) for i in range(count, count + bent) ]) count += bent if leaky > 0: s = [self.m.Var(lb=0) for _ in range(leaky * 2)] self.m.Equations([ (1.5 * neuron_inputs[count + i]) - (0.5 * neuron_inputs[count + i]) == s[2 * i] - s[2 * i + 1] for i in range(leaky) ]) self.m.Equations([ neurons[count + i] == neuron_inputs[count + i] + s[2 * i] for i in range(leaky) ]) [ self.m.Obj(10000 * s[2 * i] * s[2 * i + 1]) for i in range(leaky) ] #self.m.Equations([s[2*i]*s[2*i+1] == 0 for i in range(leaky)]) count += leaky else: raise Exception('layer type not implemented yet') def output_layer(self, size, ltype='dense', activation='linear'): """ Layer types: dense convolution pool (mean) Activation options: none softmax relu tanh sigmoid linear """ # build a layer to ensure that the number of nodes matches the output self.layer(size, 0, 0, 0, 0, 0, ltype) self.output = [self.m.CV() for _ in range(size)] for o in self.output: o.FSTATUS = 1 o.STATUS = 1 #link output CVs to last layer for i in range(size): self.m.Equation(self.output[i] == self._layers[-1][i]) def think(self, inputs): #convert inputs to numpy ndarray inputs = np.atleast_2d(inputs) ##confirm input/output dimensions in_dims = inputs.shape ni = len(self.input) #consistent layer size if in_dims[0] != ni: raise Exception('Inconsistent number of inputs') #set input values for i in range(ni): self.input[i].value = inputs[i, :] #solve in SS simulation self.m.options.IMODE = 2 #disable all weights for wl in self._weights: for w in wl: w.STATUS = 0 for bl in self._biases: for b in bl: b.STATUS = 0 self.m.solve(disp=False) ##return result res = [] #concatentate result from each CV in one list for i in range(len(self.output)): res.append(self.output[i].value) return res def learn(self, inputs, outputs, obj=2, gap=0, disp=True): """ Make the brain learn. Give inputs as (n)xm Where n = input layer dimensions m = number of datasets Give outputs as (n)xm Where n = output layer dimensions m = number of datasets Objective can be 1 (L1 norm) or 2 (L2 norm) If obj=1, gap provides a deadband around output matching. """ #convert inputs to numpy ndarray inputs = np.atleast_2d(inputs) outputs = np.atleast_2d(outputs) ##confirm input/output dimensions in_dims = inputs.shape out_dims = outputs.shape ni = len(self.input) no = len(self.output) #consistent dataset size if in_dims[1] != out_dims[1]: raise Exception('Inconsistent number of datasets') #consistent layer size if in_dims[0] != ni: raise Exception('Inconsistent number of inputs') if out_dims[0] != no: raise Exception('Inconsistent number of outputs') #set input values for i in range(ni): self.input[i].value = inputs[i, :] #set output values for i in range(no): o = self.output[i] o.value = outputs[i, :] if obj == 1: #set meas_gap while cycling through CVs o.MEAS_GAP = gap #solve in MPU mode self.m.options.IMODE = 2 self.m.options.EV_TYPE = obj self.m.options.REDUCE = 3 #enable all weights for wl in self._weights: for w in wl: w.STATUS = 1 for bl in self._biases: for b in bl: b.STATUS = 1 self.m.solve(disp=disp) def shake(self, percent): """ Neural networks are non-convex. Some stochastic shaking can sometimes help bump the problem to a new region. This function perturbs all weights by +/-percent their values.""" for l in self._weights: for f in l: f.value = f.value[-1] * ( 1 + (1 - 2 * np.random.rand()) * percent / 100)
class mpc(): def __init__(self, alpha, beta, paddle, last_move, justLeftOfPaddle, lmode): #db_file_name = "third_attempt_PT.db" # name of database to use/create db_file_name = "pong_v0.db" self.justLeftOfPaddle = justLeftOfPaddle self.m = GEKKO(remote=False) self.learnMode = lmode self.m.WEB = 0 self.m.options.SOLVER = 1 # APOPT is an MINLP solver #self.m.options.LINEAR=1 self.maxIter = 30 # this is a parameter #optional solver settings with APOPT self.m.solver_options = ['minlp_maximum_iterations 500', \ # minlp iterations with integer solution 'minlp_max_iter_with_int_sol 10', \ # treat minlp as nlp 'minlp_as_nlp 0', \ # nlp sub-problem max iterations 'nlp_maximum_iterations 50', \ # 1 = depth first, 2 = breadth first 'minlp_branch_method 1', \ # maximum deviation from whole number 'minlp_integer_tol 0.01', \ # covergence tolerance 'minlp_gap_tol 0.1'] self.m.time = [0, 1, 2, 3] # control variable self.u = self.m.MV(lb=-1, ub=1, integer=True) self.u.DCOST = 0.1 # parameters alpha = self.m.Param(value=alpha) beta = self.m.Param(value=beta) # need need the last control vector ulast = self.m.Var() self.m.delay(self.u, ulast, 1) #variable self.y = self.m.CV(paddle) #equation self.m.Equation(self.y.dt() == (alpha * self.u) + (beta * ulast)) #options self.m.options.IMODE = 6 self.m.options.NODES = 2 self.m.options.CV_TYPE = 1 self.y.STATUS = 1 self.y.FSTATUS = 1 # to do get this from input self.y.SPHI = 25 self.y.SPLO = 25 self.y.TAU = 0 self.y.TR_INIT = 2 self.u.STATUS = 1 self.u.FSTATUS = 0 #self.m.options.MAX_TIME = 0.1 sqlite3.register_adapter(np.int32, lambda val: int(val)) init_PT_db(db_file_name) d = getcwd() + "\\Database\\" + db_file_name # get path to db self.c = create_connection(d) print(self.m._path) def nxtMPC(self, ball_y, paddle, m, y, u): error = 0 self.y.MEAS = paddle self.y.sphi = ball_y + 1 self.y.splo = ball_y - 1 start = timer() try: self.m.solve(False) except: error += 1 end = timer() return self.u.NEWVAL def getMPCPred(self, pongStates): # if we the states are right, use nxtMPC if not self.checkState(pongStates): return 0, -1 predY, criticalT = getTrajectory(pongStates.statek1, self.justLeftOfPaddle, self.maxIter, self.c) #print("\n\nPrediciton: ", predY) if (self.learnMode): addState(pongStates.statek, pongStates.statek1, self.c) if (predY != None): nextU = self.nxtMPC(predY, pongStates.agent, self.m, self.y, self.u) #nextU = 0 nextInd = int(round(nextU)) #print("Action: ",nextInd) next_move = indexToAction(nextInd) return next_move, predY # otherwise, return zero else: return 0, -1 def checkState(self, pongStates): # want to check the ball is heading towards us # and that it is a certain distance frome us if (pongStates.velxk <= 0 or pongStates.velxk1 <= 0): return False elif (pongStates.ball[0, 0] < pongStates.activeArea): return False elif (pongStates.found3 is False): return False else: return True
E_a_1 = reaction_model.FV(E_a_1_initial_guess) E_a_2 = reaction_model.FV(E_a_2_initial_guess) A_1 = reaction_model.FV(A_1_initial_guess) A_2 = reaction_model.FV(A_2_initial_guess) alpha = reaction_model.FV(alpha_initial_guess) beta = reaction_model.FV(beta_initial_guess) # one-sided bounds #alpha.LOWER = 0 #beta.LOWER = 0 # state Variables Ph_3_minus = reaction_model.SV(Ph_3_minus_initial) # variable we will use to regress other Parameters Ph_2_minus = reaction_model.CV(ph_abs) # intermediates k1 = reaction_model.Intermediate(A_1 * reaction_model.exp(-E_a_1 / (R * T))) k2 = reaction_model.Intermediate(A_2 * reaction_model.exp(-E_a_2 / (R * T))) # forward reaction r1 = reaction_model.Intermediate(k1 * Ph_2_minus**alpha) # backwards reaction r2 = reaction_model.Intermediate(k2 * Ph_3_minus**beta) # equations reaction_model.Equations( [Ph_2_minus.dt() == r2 - r1, Ph_3_minus.dt() == r1 - r2]) # parameter options
# Manipulated variable Q1 = m.MV(value=Q1_ss) Q1.STATUS = 1 # use to control temperature Q1.FSTATUS = 0 # no feedback measurement Q1.LOWER = 0.0 Q1.UPPER = 100.0 Q1.DMAX = 20.0 Q1.COST = 0.0 Q1.DCOST = 1.0e-3 # Variables x1 = m.Var(value=0) x2 = m.Var(value=0) # Controlled variable TC1 = m.CV(value=TC1_ss) TC1.STATUS = 1 # minimize error with setpoint range TC1.FSTATUS = 1 # receive measurement TC1.TR_INIT = 1 # reference trajectory TC1.TAU = 10 # time constant for response # Equation m.Equation(x2 == x1.dt()) m.Equation(tau**2*x2.dt() + 2*zeta*tau*x1.dt() \ + x1 == Kp * (Q1-Q1_ss)) m.Equation(TC1 == x1 + TC1_ss) # Global Options #m.server = 'http://127.0.0.1' # local server, if available m.options.IMODE = 6 # MPC m.options.CV_TYPE = 1 # Objective type
x_euler, y_euler, z_euler = np.loadtxt('rcbb.csv', delimiter=',', unpack='true') phi_euler, theta_euler, psi_euler = np.loadtxt('eulerangles.csv', delimiter=',', unpack='true') #%% Model #Initialize model m = GEKKO() m.time = time x_euler_model = m.CV(value=x_euler) y_euler_model = m.CV(value=y_euler) z_euler_model = m.CV(value=z_euler) phi_euler_model = m.CV(value=phi_euler) theta_euler_model = m.CV(value=theta_euler) psi_euler_model = m.CV(value=psi_euler) x_aruco_model = m.CV(value=x_aruco) y_aruco_model = m.CV(value=y_aruco) z_aruco_model = m.CV(value=z_aruco) phi_aruco_model = m.CV(value=phi_aruco) theta_aruco_model = m.CV(value=theta_aruco) psi_aruco_model = m.CV(value=psi_aruco) x_offset = m.MV(value=0) y_offset = m.MV(value=0)
mum.STATUS = 1 romax = m.FV(value=85, lb=0, name="ro_max (%/g-d)") romax.STATUS = 1 ko = m.FV(value=6.32, lb=0, name="k_o (%)") ko.STATUS = 1 osat = m.FV(value=86.2, lb=0, name="o_sat (%)") osat.STATUS = 1 kL = m.FV(value=0.0137, lb=0, name="k_L (h/L-d)") kL.STATUS = 1 yco = m.FV(value=0.897, lb=0) yxs.STATUS = 1 vL = m.FV(value=0.05) vL.STATUS = 1 # variables rs = m.CV() rs.FSTATUS = 1 mu = m.CV() mu.FSTATUS = 1 ro = m.CV() ro.FSTATUS = 1 rc = m.CV() rc.FSTATUS = 1 s = m.CV(value=substrate_data, lb=0) s.FSTATUS = 1 x = m.CV(value=cells_data, lb=0) x.FSTATUS = 1 o = m.CV(value=o2_data, lb=0) o.FSTATUS = 1 c = m.CV(value=co2_data, lb=0) c.FSTATUS = 1
m = GEKKO() m.time = np.linspace(0, 20, 41) # Parameters mass = 500 b = m.Param(value=50) K = m.Param(value=0.8) # Manipulated variable p = m.MV(value=0, lb=0, ub=100) p.STATUS = 1 # allow optimizer to change p.DCOST = 0.1 # smooth out gas pedal movement p.DMAX = 20 # slow down change of gas pedal # Controlled Variable v = m.CV(value=0) v.STATUS = 1 # add the SP to the objective m.options.CV_TYPE = 2 # squared error v.SP = 40 # set point v.TR_INIT = 1 # set point trajectory v.TAU = 5 # time constant of trajectory # Process model m.Equation(mass * v.dt() == -v * b + K * b * p) m.options.IMODE = 6 # control m.solve(disp=False) # get additional solution information import json with open(m.path + '//results.json') as f:
vs, #10 acc] #11 #%%Gekko mhe mhe=GEKKO() mhe.time=np.linspace(0,2,21) mhe_ac=mhe.MV(value=0,lb=0,name='ac') mhe_ac.STATUS=0 mhe_ac.FSTATUS=1 mhe_br=mhe.MV(value=0,ub=0,name='br') mhe_ac.STATUS=0 mhe_ac.FSTATUS=1 mhe_v = mhe.CV(value=0, name='v',lb=0) #vs mhe_v.FSTATUS=1 mhe_v.STATUS=1 mhe_v.MEAS_GAP=1 mhe_a = mhe.SV(value=0,name='a') #acc mhe_f=mhe.SV(value=0,name='f') mhe_grade=mhe.MV(0) mhe_grade.STATUS=0 mhe_grade.FSTATUS=1 mhe_cd=mhe.FV(value=0.003875,lb=0,ub=50) mhe_rr1=mhe.FV(value=0.001325,lb=0,ub=50) mhe_rr2=mhe.FV(value=0.265,lb=0,ub=50) mhe_tau=mhe.FV(value=0.01,lb=0)
m.options.NODES = 100 m.options.SOLVER = 3 m.options.IMODE = 6 m.options.MAX_ITER = 5000 m.options.MV_TYPE = 0 m.options.DIAGLEVEL = 0 m.options.REDUCE = 0 g = 9.8 S = 0.05 m0 = 600 mp0 = 550 tsp = 20.0 Isp = 300 tf = m.CV(value=200, lb=0.) tf.STATUS = 1 alpha = m.MV(value=0.0, lb=-20 * d2r, ub=20 * d2r) alpha.STATUS = 1 x = m.Var(value=0., lb=0.) y = m.Var(value=0., lb=0.) v = m.Var(value=0., lb=0.) # , ub=1000.) gam = m.Var(value=89.9 * d2r, lb=-180. * d2r, ub=180. * d2r) mass = m.Var(value=m0)#, lb=m0-mp0, ub=m0) tave = mp0 * Isp * g / tsp step = [0 if z > tsp else tave for z in t_array * tf.value] ft = m.Param(value=step)
from gekko import GEKKO import numpy as np import matplotlib.pyplot as plt m = GEKKO(remote=False) xm = np.array([0, 1, 2, 3, 4, 5]) ym = np.array([0.1, 0.2, 0.3, 0.5, 0.8, 2.0]) m.options.IMODE = 2 # coeffs: c = [m.FV(value=0) for i in range(4)] x = m.Param(value=xm) y = m.CV(value=ym) # cv: match the model and the measured value y.FSTATUS = 1 # we gonna use the measurements # polynom model itself m.Equation(y == c[0] + c[1] * x + c[2] * x**2 + c[3] * x**3) # linReg c[0].STATUS = 1 c[1].STATUS = 1 m.options.EV_TYPE = 1 # error is absolute # m.options.EV_TYPE = 2 # error is squarred m.solve(disp=False) p1 = [c[1].value[0], c[0].value[0]] xp = np.linspace(0, 5, 100) c[2].STATUS = 1