can Gekko solve vector based dynamic optimization problem for optimal control - vector

i have tried many solver but getting errors somewhere. now im going to try gekko for my problem.
Please Lt me know that gekko can this kind of problem, where M in python function take the variable q. and all variables and parameters are in form of vector or matrix.
thanks you
q should be function of time, and M, c sai and other matrix depends on q and u.

Here is a similar problem with an inverted pendulum
There is also a related Stack Overflow question: how to use arrays in gekko optimizer for python Gekko can solve path planning problems that are subject to actuator constraints and equations of motion. One of the challenging mathematical features of this problem is how to smoothly pose the path constraints so that the robot does not pause at each intermediate path point. A potential method is to create a path cubic spline that helps to define the desired location for each time point. Here is one problem with matrices:
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)
Here is another test script that demonstrates dot products and the trace function with Numpy:
import numpy as np
from gekko import GEKKO
m = GEKKO(remote=False)
# Random 3x3
A = np.random.rand(3,3)
# Random 3x1
b = np.random.rand(3,1)
# Gekko array 3x3
p = m.Array(m.Param,(3,3))
# Gekko array 3x1
y = m.Array(m.Var,(3,1))
# Dot product of A p
x = np.dot(A,p) # or A#p
# Dot product of x y
w = x#y
# Dot product of p y
z = p#y # or np.dot(p,y)
# Trace (sum of diag) of p
t = np.trace(p)
# solve Ax = b
s = m.axb(A,b)
m.solve()

Related

How do I define matrix parameters in a Dymos problem?

I'm trying to setup a dynamic optimization with dymos where I have an analysis upstream of my dymos trajectory. This upstream analysis computes some 2D-matrix K. I want to pass this matrix into my dymos problem. According to the documentation (and how I've done this in the past) is to add K as a paramter to the trajectory:
traj.add_parameter('K',targets={'phase0':['K'],opt=False,static_target=True).
However, this returns an error because static_target expects K to be a scalar. If I have static_target=False, this also returns an error because it expects K to have some dimension related to the number of nodes in the trajectory.
Is there something I'm missing here?
Is it sufficient to manually connect K to the trajectory via
p.model.connect('K','traj.phase0.rhs_disc.K') and
p.model.connect('K','traj.phase0.rhs_col.K')? Or will that create issues in how dymos works the problem.
It doesn't seem appropriate to vectorize K either.
Any suggestions are greatly appreciated.
In my opinion, the easiest way to connect parameters from trajectory to phase is to add the parameter to both the Trajectory and the phases in which it is to be used.
Consider a simple oscillator where the mass, spring constant, and dampening coefficient are given as a single size-3 input.
In this case, I used OpenMDAO's tags feature and a special dymos tag dymos.static_target so that dymos realizes the target isn't shaped with a different value at each node. I think its a bit easier to do it this way as opposed to having to add it later at the add_parameter call.
class OscillatorODEVectorParam(om.ExplicitComponent):
"""
A Dymos ODE for a damped harmonic oscillator.
"""
def initialize(self):
self.options.declare('num_nodes', types=int)
def setup(self):
nn = self.options['num_nodes']
# Inputs
self.add_input('x', shape=(nn,), desc='displacement', units='m')
self.add_input('v', shape=(nn,), desc='velocity', units='m/s')
self.add_input('constants', shape=(3,), units=None,
desc='a vector of mass, spring constant, and damping coefficient [m, k, c]',
tags=['dymos.static_target'])
self.add_output('v_dot', val=np.zeros(nn), desc='rate of change of velocity', units='m/s**2')
self.declare_coloring(wrt='*', method='fd')
def compute(self, inputs, outputs):
x = inputs['x']
v = inputs['v']
m, k, c = inputs['constants']
f_spring = -k * x
f_damper = -c * v
outputs['v_dot'] = (f_spring + f_damper) / m
To use the ODE, we have a problem with a single trajectory and in this case, as single phase.
Again, in my opinion, the clearest way to link parameters from the trajectory to phases is to add them in both places with the same name.
Dymos will perform some introspection and automatically link them up.
def test_ivp_driver_shaped_param(self):
import openmdao.api as om
import dymos as dm
import matplotlib.pyplot as plt
# plt.switch_backend('Agg') # disable plotting to the screen
from dymos.examples.oscillator.oscillator_ode import OscillatorODEVectorParam
# Instantiate an OpenMDAO Problem instance.
prob = om.Problem()
# We need an optimization driver. To solve this simple problem ScipyOptimizerDriver will work.
prob.driver = om.ScipyOptimizeDriver()
# Instantiate a Phase
phase = dm.Phase(ode_class=OscillatorODEVectorParam, transcription=dm.Radau(num_segments=10))
# Tell Dymos that the duration of the phase is bounded.
phase.set_time_options(fix_initial=True, fix_duration=True)
# Tell Dymos the states to be propagated using the given ODE.
phase.add_state('x', fix_initial=True, rate_source='v', targets=['x'], units='m')
phase.add_state('v', fix_initial=True, rate_source='v_dot', targets=['v'], units='m/s')
# The spring constant, damping coefficient, and mass are inputs to the system that are
# constant throughout the phase.
# Declare this parameter on phase and then we'll feed its value from the parent trajectory.
phase.add_parameter('constants', units=None)
# Since we're using an optimization driver, an objective is required. We'll minimize
# the final time in this case.
phase.add_objective('time', loc='final')
# Instantiate a Dymos Trajectory and add it to the Problem model.
traj = prob.model.add_subsystem('traj', dm.Trajectory())
traj.add_phase('phase0', phase)
# This parameter value will connect to any phase with a parameter named constants by default.
# This is the easiest way, in my opinion, to pass parameters from trajectory to phase.
traj.add_parameter('constants', units=None, opt=False)
# Setup the OpenMDAO problem
prob.setup()
# Assign values to the times and states
prob.set_val('traj.phase0.t_initial', 0.0)
prob.set_val('traj.phase0.t_duration', 15.0)
prob.set_val('traj.phase0.states:x', 10.0)
prob.set_val('traj.phase0.states:v', 0.0)
# m k c
prob.set_val('traj.parameters:constants', [1.0, 1.0, 0.5])
# Now we're using the optimization driver to iteratively run the model and vary the
# phase duration until the final y value is 0.
prob.run_driver()
# Perform an explicit simulation of our ODE from the initial conditions.
sim_out = traj.simulate(times_per_seg=50)
# Plot the state values obtained from the phase timeseries objects in the simulation output.
t_sol = prob.get_val('traj.phase0.timeseries.time')
t_sim = sim_out.get_val('traj.phase0.timeseries.time')
states = ['x', 'v']
fig, axes = plt.subplots(len(states), 1)
for i, state in enumerate(states):
sol = axes[i].plot(t_sol, prob.get_val(f'traj.phase0.timeseries.states:{state}'), 'o')
sim = axes[i].plot(t_sim, sim_out.get_val(f'traj.phase0.timeseries.states:{state}'), '-')
axes[i].set_ylabel(state)
axes[-1].set_xlabel('time (s)')
fig.legend((sol[0], sim[0]), ('solution', 'simulation'), 'lower right', ncol=2)
plt.tight_layout()
plt.show()

Solving for a matrix in sympy

I want to solve for Ka = F. i do this by defining a new matrix M = Ka-F. And solves for this when its zero. This also works very well for a 2x2 matrix i only have 2 unkown so it should be very trivial to do this one but sympy wont solve it for some reason i cant really seem to find out what the problem is... this is the code:
from sympy import *
K = Matrix([[1/2,0,0,-1/2],[0,1,0,-1],[0,0,1/2,-1/2],[-1/2,-1,-1/2,2]])
T1,T4 = symbols("T_1,T_4")
T = Matrix([[T1],[20],[20],[T4]])
F = Matrix([[29.1666],[16.666],[12.5],[41.6666]])
M = K*T-F
solve(M)

GEKKO - optimization in matrix form

I am trying to solve an optimization problem where I need to specify the problem and the constraints using a 2D matrix. I have been using SCIPY, where the 1D arrays are the requirements. I want to check if GEKKO allows one to specify the objective function, bounds and constraints using a 2D matrix.
I have provided details and a reproducible version of the problem in the post here:
SCIPY - building constraints without listing each variable separately
Thanks
C
You can use the m.Array function in gekko. I don't recommend that you use the np.triu() with the Gekko array because the eliminated variables will still solve but potentially be hidden from the results. Here is a solution:
import numpy as np
import scipy.optimize as opt
from gekko import GEKKO
p= np.array([4, 5, 6.65, 12]) #p = prices
pmx = np.triu(p - p[:, np.newaxis]) #pmx = price matrix, upper triangular
m = GEKKO(remote=False)
q = m.Array(m.Var,(4,4),lb=0,ub=10)
# only upper triangular can change
for i in range(4):
for j in range(4):
if j<=i:
q[i,j].upper=0 # set upper bound = 0
def profit(q):
profit = np.sum(q.flatten() * pmx.flatten())
return profit
for i in range(4):
m.Equation(np.sum(q[i,:])<=10)
m.Equation(np.sum(q[:,i])<=8)
m.Maximize(profit(q))
m.solve()
print(q)
This gives the solution:
[[[0.0] [2.5432017412] [3.7228765674] [3.7339217013]]
[[0.0] [0.0] [4.2771234426] [4.2660783187]]
[[0.0] [0.0] [0.0] [0.0]]
[[0.0] [0.0] [0.0] [0.0]]]

Solve a Quadratic Equation in two variables using Python

I have got two equations, one linear say,
, where m and c are constants
and the other quadratic say,
, where x1, y1 and r are constants.
Is there a way I can solve for x and y using Python ?
I could solve them on pen and paper finding the relation between x and y from the linear equation and substituting it in the other. There would be two roots satisfying the quadratic equation.
Look at SymPy.
Here is an example of how to solve a simple difference of squares equation, taken from their documentation.
>>> from sympy.solvers import solve
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve(x**2 - 1, x)
[-1, 1]
Regarding your specific problem, the solution will look something like this:
>>> x = Symbol('x')
>>> y = Symbol('y')
>>> solve( (x-c1)**2 + (y-c2)**2 - c3**2, x, y)
c1, c2 and c3 are the constants declared as variables earlier in your code.
Provided we know the constants: m, c, x1, y1, r ; the code should look like this:
import sympy as sym
x,y = sym.symbols('x,y')
Eq1 = sym.Eq(y-mx,c)
Eq2 = sym.Eq((x-x1)**2 + (y-y1)**2, r**2)
sol = sym.solve([Eq1,Eq2],(x,y))

Math behind Conv2D function in Keras

I am using Conv2D model of Keras 2.0. However, I cannot fully understand what the function is doing mathematically. I try to understand the math using randomly generated data and a very simple network:
import numpy as np
import keras
from keras.layers import Input, Conv2D
from keras.models import Model
from keras import backend as K
# create the model
inputs = Input(shape=(10,10,1)) # 1 channel, 10x10 image
outputs = Conv2D(32, (3, 3), activation='relu', name='block1_conv1')(inputs)
model = Model(outputs=outputs, inputs=inputs)
# input
x = np.random.random(100).reshape((10,10))
# predicted output for x
y_pred = model.predict(x.reshape((1,10,10,1))) # y_pred.shape = (1,8,8,32)
I tried to calculate, for example, the value of the first row, the first column in the first feature map, following the demo in here.
w = model.layers[1].get_weights()[0] # w.shape = (3,3,1,32)
w0 = w[:,:,0,0]
b = model.layers[1].get_weights()[1] # b.shape = (32,)
b0 = b[0] # b0 = 0
y_pred_000 = np.sum(x[0:3,0:3] * w0) + b0
But relu(y_pred_000) is not equal to y_pred[0][0][0][0].
Could anyone point out what's wrong with my understanding? Thank you.
It's easy and it comes from Theano dim ordering. The result of applying filter in stored in a so called channel dimension. In case of TensorFlow this is the last dimension and that's why results are good. In case of Theano it's second dimension (convolution result has shape (cases, channels, width, height) so in order to solve your problem you need to change prediction line to:
y_pred = model.predict(x.reshape((1,1,10,10)))
Also you need to change the way you get the weights as weights in Theano has shape (output_channels, input_channels, width, height) you need to change the weight getter to:
w = model.layers[1].get_weights()[0] # w.shape = (32,1,3,3)
w0 = w[0,0,:,:]

Resources