Sympy not solving convolution integral - sympy

I'm trying to solve some convolution integrals but without any luck.
import matplotlib.pyplot as plt
import numpy as np
import sympy as sp
t1 = 0.01
t1_sym = sp.Symbol('t_1')
F0 = 30e3
F0_sym = sp.Symbol('F_0')
m = 4000
m_sym = sp.Symbol('m')
k = 5000e3
k_sym = sp.Symbol('k')
omega0_sym = sp.sqrt(k_sym/m_sym)
t = sp.Symbol('t')
tau = sp.Symbol(r'\tau')
F1_sym= 2*F0_sym*tau/t1_sym
x1_sym = sp.integrate((F1_sym*sp.sin(omega0_sym*(t-tau))/(omega0_sym*m_sym)) ,(tau,0,t))
I would be really grateful for any insights.

In general, it is a good practise to provide sympy any information available about the parameters and variables involved in an integral, instead of simply declaring them as symbols. From the numerical values you are using, it is clear that all variables and parameters are real and positive. You can provide sympy this information when you define them. With this information, sympy provides an expression for the integral (I will leave it to you to check if it is correct or not)
t1_sym = sp.Symbol('t_1', positive = True)
F0_sym = sp.Symbol('F_0', positive = True)
m_sym = sp.Symbol('m', positive = True)
k_sym = sp.Symbol('k', positive = True)
omega0_sym = sp.sqrt(k_sym/m_sym)
t = sp.Symbol('t', positive = True)
tau = sp.Symbol(r'\tau', positive = True)
F1_sym= 2*F0_sym*tau/t1_sym
x1_sym = sp.integrate((F1_sym*sp.sin(omega0_sym*(t-tau))/(omega0_sym*m_sym)) ,(tau,0,t))
print(x1_sym)
2*F_0*t/(k*t_1) - 2*F_0*sqrt(m)*sin(sqrt(k)*t/sqrt(m))/(k**(3/2)*t_1)

Related

Solver does not find optimal solution when expanding problems

I have noticed that when using Pyomo + Ipopt, some optimization dae problems that converge to an optimal solution, when expanded in complexity (e.g. larger distance in a car example) and consequetly in the number of finite elements to keep accuracy, the solver displays:
EXIT: Solved To Acceptable Level.
instead of the previous "Optimal solution found".
As an example of stated above, I will use a modified code of "ampl car sample" from Pyomo repository.
# Ampl Car Example
#
# Shows how to convert a minimize final time optimal control problem
# to a format pyomo.dae can handle by removing the time scaling from
# the ContinuousSet.
#
# min tf
# dxdt = v
# dvdt = a-R*v^2
# x(0)=0; x(tf)=L
# v(0)=0; v(tf)=0
# -3<=a<=1
from pyomo.environ import *
from pyomo.dae import *
m = ConcreteModel()
m.R = Param(initialize=0.001) # Friction factor
m.L = Param(initialize=1000000.0) # Final position
m.tau = ContinuousSet(bounds=(0,1)) # Unscaled time
m.time = Var(m.tau) # Scaled time
m.tf = Var()
m.x = Var(m.tau,bounds=(0,m.L+50))
m.v = Var(m.tau,bounds=(0,None))
m.a = Var(m.tau, bounds=(-3.0,1.0),initialize=0)
m.dtime = DerivativeVar(m.time)
m.dx = DerivativeVar(m.x)
m.dv = DerivativeVar(m.v)
m.obj = Objective(expr=m.tf)
def _ode1(m,i):
if i == 0 :
return Constraint.Skip
return m.dx[i] == m.tf * m.v[i]
m.ode1 = Constraint(m.tau, rule=_ode1)
def _ode2(m,i):
if i == 0 :
return Constraint.Skip
return m.dv[i] == m.tf*(m.a[i] - m.R*m.v[i]**2)
m.ode2 = Constraint(m.tau, rule=_ode2)
def _ode3(m,i):
if i == 0:
return Constraint.Skip
return m.dtime[i] == m.tf
m.ode3 = Constraint(m.tau, rule=_ode3)
def _init(m):
yield m.x[0] == 0
yield m.x[1] == m.L
yield m.v[0] == 0
yield m.v[1] == 0
yield m.time[0] == 0
m.initcon = ConstraintList(rule=_init)
discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(m,nfe=5000,scheme='BACKWARD')
solver = SolverFactory('ipopt')
solver.solve(m,tee=True)
print("final time = %6.2f" %(value(m.tf)))
x = []
v = []
a = []
time=[]
for i in m.tau:
time.append(value(m.time[i]))
x.append(value(m.x[i]))
v.append(value(m.v[i]))
a.append(value(m.a[i]))
import matplotlib.pyplot as plt
plt.subplot(131)
plt.plot(time,x,label='x')
plt.title('location')
plt.xlabel('time')
plt.subplot(132)
plt.plot(time,v,label='v')
plt.xlabel('time')
plt.title('velocity')
plt.subplot(133)
plt.plot(time,a,label='a')
plt.xlabel('time')
plt.title('acceleration')
plt.show()
NOTE: The original source code can be colsulted here to compare with mine modified: https://github.com/Pyomo/pyomo/blob/main/examples/dae/car_example.py
Is there anything I can do about this? May I lower the ipopt tolerance so it keeps finding for an optimal solution?
You can disable the heuristic that makes Ipopt stop with an "acceptable" solution by setting option acceptable_iter to 0. See https://coin-or.github.io/Ipopt/OPTIONS.html#OPT_Termination for all options that determine termination of Ipopt.

Replace values in sympy NDimArray

I would like to replace values in a sympy NDimArray.
I have the following code
import sympy as sp
import numpy as np
e = sp.MatrixSymbol('e',3,3)
E = sp.Matrix(e)
# Make E symmetric
E[1,0] = E[0,1]
E[2,0] = E[0,2]
E[2,1] = E[1,2]
result = sp.tensorproduct(E,E)
E_tst = np.random.rand(3,3)
E_tst[1,0] = E_tst[0,1]
E_tst[2,0] = E_tst[0,2]
E_tst[2,1] = E_tst[1,2]
resultNumeric = np.tensordot(E_tst,E_tst,axes=0)
check = resultNumeric - result.as_mutable().subs({E:sym.Matrix(E_tst)})
I get the error AttributeError: 'MutableDenseNDimArray' object has no attribute 'subs'.
How can I replace the symbols in a NDimArray?
Best Regards
Unfortunately, MutableDenseNDimArray doesn't inherit from Basic, whereas ImmutableDenseNDimArray does, therefore some attributes are not available. Don't ask me about this design decision.
However, you can achieve the same result by creating a substitution dictionary:
# substitution dictionary
d = {k: v for k, v in zip(list(E), list(Matrix(E_tst)))}
check = resultNumeric - result.subs(d)

What is the correct usage of TransformedPiecewiseLinearFunctionND in Pyomo?

Background
I'm trying to use a surrogate model in Pyomo. Given a set of data labeled x, y, and z, I would like to write z as an inexpensive function of x and y.
Issue
Pyomo has tools for multivariate piecewise linear functions. See here. I setup a simple example and my function is evaluating correctly. But there there doesn't seem to be any constraint getting added for Z. I would expect the model value to be equal to the interpolated value below. I'm guessing I did something wroing in setting up TransformedPiecewiseLinearFunctionND, but I couldn't find any examples in the documentation. Any insights would be appreciated.
Code
from pyomo.core import ConcreteModel, Var, Constraint
import pyomo.environ as pe
from pyomo.core.kernel.piecewise_library.transforms_nd import (
PiecewiseLinearFunctionND,
TransformedPiecewiseLinearFunctionND
)
from pyomo.core.kernel.variable import (
variable,
variable_list
)
import pyomo.core.kernel.piecewise_library.util as util
import numpy as np
from scipy.spatial import Delaunay
npts = 100
vlist = variable_list([variable(lb=-1, ub=1),
variable(lb=-1, ub=1)])
tri = util.generate_delaunay(vlist, num=npts)
x, y = tri.points.T
z = np.cos(x) * np.sin(y)
model = ConcreteModel()
model.X = Var(initialize=0)
model.Y = Var(initialize=0)
model.Z = Var(initialize=999)
f = PiecewiseLinearFunctionND(tri, z)
model.g = TransformedPiecewiseLinearFunctionND(
f=f,
input=(model.X, model.Y),
output=model.Z
)
def x_rule(model):
return model.X == 0.5
def y_rule(model):
return model.Y == 0.5
model.x_const = Constraint(rule=x_rule)
model.y_const = Constraint(rule=y_rule)
solver = pe.SolverFactory('ipopt')
solver.solve(model)
z_exact = np.cos(0.5) * np.sin(0.5)
z_interp = f([0.5, 0.5])
x_model = pe.value(model.X)
y_model = pe.value(model.Y)
z_model = pe.value(model.Z)
print(f'Z Exact: {z_exact}')
print(f'Z Interpolated: {z_interp}')
print(f'Model values (X, Y, Z): {x_model}, {y_model}, {z_model}')
Output
Z Exact: 0.42073549240394825
Z Interpolated: 0.42067082611089646
Model values (X, Y, Z): 0.5, 0.5, 999
I've also tried adding a constraint for Z manually. This produces an error:
def z_rule(model):
return model.Z == f([model.X, model.Y])
model.z_const = Constraint(rule=z_rule)
You are mixing modeling components between the pyomo.kernel and pyomo.environ modeling layers. This is not supported (this page has more information).
The multi-dimensional piecewise functionality is currently only available using the pyomo.kernel interface. An example of how to use it can be found here:
https://github.com/Pyomo/pyomo/blob/main/examples/kernel/piecewise_nd_functions.py

trying to use DiscreteUniform as an numpy index

I am trying to use pymc3.DiscreteUniform as an index for a numpy 1D array
This worked with pymc (v2) but I am transitioning to pymc3 and code that worked under pymc don't work under pymc3.
import pymc3 as pm
d0 = pm.DiscreteUniform('d0', lower=0, upper=nDens - 1, testval = nDens//2)
pred = np.zeros(len(box.match), np.float64)
for iwvl, amatch in enumerate(box.match):
pred[iwvl] += amatch['intensitySum'][d0]
I get the following error message:
IndexError: only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices
I have found something that works but in involves going into theano and theano.tensor.
`
import pymc3 as pm
with pm.Model() as model:
em0 = pm.Normal('em0', mu=emLog, sigma=0.2)
d0 = pm.DiscreteUniform('d0', lower = 0, upper = nDens - 1, testval = Dindex)
boundNormal = pm.Bound(pm.Normal, lower=0.0)
wght = boundNormal('wght', mu=0.2, sigma=0.1)
pred = np.zeros((nDens, len(box.match)), np.float64)
for iwvl, amatch in enumerate(box.match):
pred[0:,iwvl] += amatch['intensitySum']
xpred = theano.shared(pred, name='p0')
idx = tensor.as_tensor_variable(d0)
predicted = xpred[idx]*10.**em0
nObs = len(box.match)
intensity = np.zeros(nObs, np.float64)
for iwvl in range(nObs):
intensity[iwvl] = box.match[iwvl]['obsIntensity']
sigma = 0.2
Y_obs = pm.Normal('Y_obs', mu=predicted, sigma=wght*intensity, observed=intensity)
trace = pm.sample(tune=20000, draws=100000, target_accept=0.85)`
and then you can work with the trace
it is even possible to make sigma as pm variable

How to use pymc to find variables in initial state to match the final state to the observation?

I have an initial state which can be represented with Gaussian function, let's say F(x), with three free parameters "amplitude, centroid, sigma".
I have to sum up the F(x) with a transformation function, G(x)= exp(a*x)+b, with two free parameters a and b.
I want to use pymc to find these five free parameters so that the final state, F(x)+G(x), represents a Gaussian function with:
amplitude=3.05
centroid=5.45
sigma=5.47
I've looked at this link and various other questions and answers: Fit two normal distributions (histograms) with MCMC using pymc?
and have written the same code, but I don't know where I should enter the previous three values.
import numpy as np
import matplotlib.pyplot as pl
from scipy.optimize import curve_fit
import pymc as mc
def GaussFunc(x, A, mu, sigma):
return A * np.exp(-0.5 * ((x - mu) / sigma)**2)
def trFunc(x,a,b):
return np.exp(a*x)+b
interval=np.arange(0, 10, 0.05)
A_ini=2.0
mu_ini=3.0
sigma_ini=1.0
initial=GaussFunc(interval, A_ini, mu_ini, sigma_ini, )
intervalT=np.arange(0, np.pi, np.pi/200.0)
a_t=0.2
b_t=-2.0
transf= trFunc(intervalT,a_t,b_t,)
final=np.zeros(200)
final=initial+transf
est_centroid_one = mc.Uniform("est_centroid_one", 0, 10 )
est_sigma_one = mc.Uniform( "est_sigma_one", 0, 5 )
est_height_one = mc.Uniform( "est_height_one", 0, 5 )
est_a_two = mc.Uniform("est_a_two", 0, 1 )
est_b_two = mc.Uniform("est_b_two", -3, 3 )
precision= 1./mc.Uniform("std", 0, 1)**2
#mc.deterministic( trace = False)
def est_profile_1(x = interval, mu = est_centroid_one, sigma = est_sigma_one, A= est_height_one):
return GaussFunc( x, A, mu, sigma )
#mc.deterministic( trace = False)
def est_profile_2(x = intervalT, a = est_a_two, b = est_b_two):
return trFunc( x, a, b )
#mc.deterministic( trace = False )
def mean( profile_1 = est_profile_1, profile_2 = est_profile_2 ):
return profile_1 + profile_2
observations = mc.Normal("obs", mean, precision, value = final, observed = True)
model = mc.Model([est_centroid_one,
est_height_one,
est_sigma_one,
est_a_two,
est_b_two,
precision])
map_ = mc.MAP( model )
map_.fit()
mcmc = mc.MCMC( model )
mcmc.sample( 50000,40000 )
print est_centroid_one,est_height_one,est_sigma_one,est_a_two,est_b_two
Thank you