Multiplying two variables in CVXPY [duplicate] - python

This question already has an answer here:
How to convert quadratic to linear program?
(1 answer)
Closed 7 years ago.
I'm in need of an LP where you can multiply two non-constants. Here is the following code that I am trying to perform:
import cvxpy as cvx
a = cvx.Variable()
b = cvx.Variable()
c = cvx.Variable()
obj = cvx.Maximize(((0.4270437386 * a) + (0.1737677971 * b) + (0.21763175116 * c) - 0.03) / (((((2 * a * 0.424718270) * b) * (0.195770376 ** 0.5)) * (0.022090814 ** 0.5)) * ((2 * c * -0.041137487) * b * (0.194241184 ** 0.5) * (0.022090814 ** 0.5)) * (2 * a * 0.363033596 * c * (0.195770376** 0.5) * (0.194241184 ** 0.5))))
Unfortunately this raises an error:
cvxpy.error.DCPError: Cannot multiply two non-constants.
This stems from several areas in the denominator of obj, such as (2 * a * 0.424718270) * b).
I was wondering if anyone knew of any LP programs where we can do this sort of thing? Is it even possible.

The issue is that you are asking a linear programming package to optimize for a non-linear objective function. This is much more than a technical issue. The methods used to solve linear programming problems do not make sense and cannot be tweaked.

Related

Sympy integration running into error, but Mathematica works fine

I'm trying to integrate an equation using sympy, but the evaluation keeps erroring out with:
TypeError: cannot add <class 'sympy.matrices.immutable.ImmutableDenseMatrix'> and <class 'sympy.core.numbers.Zero'>
However, when I integrate the same equation in Mathematica, I get the result I'm looking for. I'm hoping someone can explain what is happening under the hood with sympy and how its integration differs from mathematica's.
Because there are a lot of equations involved, I am only going to post the Python representation of the equations which are used to make up the variables called in the integration. To know for certain that the integration is an issue, I have independently checked each equation involved and made sure the results match between Python and Mathematica. I can confirm that only the integration fails.
Integration variable setup in Python:
import numpy as np
import sympy as sym
from sympy import I, Matrix, integrate
from sympy.integrals import Integral
from sympy.functions import exp
from sympy.physics.vector import cross, dot
c_speed = 299792458
lambda_u = 0.01
k_u = (2 * np.pi)/lambda_u
K_0 = 0.2
gamma_0 = 2.0
beta_0 = sym.sqrt(1 - 1 / gamma_0**2)
t = sym.symbols('t')
t_start = (-2 * lambda_u) / c_speed
t_end = (3 * lambda_u) / c_speed
beta_x_of_t = sym.Piecewise( (0.0, sym.Or(t < t_start, t > t_end)),
((-1 * K_0)/gamma_0 * sym.sin(k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)) )
beta_z_of_t = sym.Piecewise( (beta_0, sym.Or(t < t_start, t > t_end)),
(beta_0 * (1 - K_0**2/ (4 * beta_0 * gamma_0**2)) + K_0**2 / (4 * beta_0 * gamma_0**2) * sym.sin(2 * k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)) )
beta_xp_of_t = sym.diff(beta_x_of_t, t)
beta_zp_of_t = sym.diff(beta_z_of_t, t)
Python Integration:
n = Matrix([(0, 0, 1)])
beta = Matrix([(beta_x_of_t, 0, beta_z_of_t)])
betap = Matrix([(beta_xp_of_t, 0, beta_zp_of_t)])
def rad(n, beta, betap):
return integrate(n.cross((n-beta).cross(betap)), (t, t_start, t_end))
rad(n, beta, betap)
# Output is the error above
Mathematica integration:
rad[n_, beta_, betap_] :=
NIntegrate[
Cross[n, Cross[n - beta, betap]]
, {t, tstart, tend}, AccuracyGoal -> 3]
rad[{0, 0, 1}, {betax[t], 0, betaz[t]}, {betaxp[t], 0, betazp[t]}]
# Output is {0.00150421, 0., 0.}
I did see similar question such as this one and this question, but I'm not entirely sure if they are relevant here (the second link seems to be a closer match, but not quite a fit).
As you're working with imprecise floats (and even use np.pi instead of sym.pi), while sympy tries to find exact symbolic solutions, sympy's expressions get rather wild with constants like 6.67e-11 mixed with much larger values.
Here is an attempt to use more symbolic expressions, and only integrate the x-coordinate of the function.
import sympy as sym
from sympy import I, Matrix, integrate, S
from sympy.integrals import Integral
from sympy.functions import exp
from sympy.physics.vector import cross, dot
c_speed = 299792458
lambda_u = S(1) / 100
k_u = (2 * sym.pi) / lambda_u
K_0 = S(2) / 100
gamma_0 = 2
beta_0 = sym.sqrt(1 - S(1) / gamma_0 ** 2)
t = sym.symbols('t')
t_start = (-2 * lambda_u) / c_speed
t_end = (3 * lambda_u) / c_speed
beta_x_of_t = sym.Piecewise((0, sym.Or(t < t_start, t > t_end)),
((-1 * K_0) / gamma_0 * sym.sin(k_u * c_speed * t), sym.And(t_start <= t, t <= t_end)))
beta_z_of_t = sym.Piecewise((beta_0, sym.Or(t < t_start, t > t_end)),
(beta_0 * (1 - K_0 ** 2 / (4 * beta_0 * gamma_0 ** 2)) + K_0 ** 2 / (
4 * beta_0 * gamma_0 ** 2) * sym.sin(2 * k_u * c_speed * t),
sym.And(t_start <= t, t <= t_end)))
beta_xp_of_t = sym.diff(beta_x_of_t, t)
beta_zp_of_t = sym.diff(beta_z_of_t, t)
n = Matrix([(0, 0, 1)])
beta = Matrix([(beta_x_of_t, 0, beta_z_of_t)])
betap = Matrix([(beta_xp_of_t, 0, beta_zp_of_t)])
func = n.cross((n - beta).cross(betap))[0]
print(integrate(func, (t, t_start, t_end)))
This doesn't give an error, and outputs just zero.
Lambdify can be used to convert the function to numpy, and plot it.
func_np = sym.lambdify(t, func)
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import quad
t_start_np = float(t_start.evalf())
t_end_np = float(t_end.evalf())
ts = np.linspace(t_start_np, t_end_np, 100000)
plt.plot(ts, func_np(ts))
print("approximate integral (np.trapz):", np.trapz(ts, func_np(ts)))
print("approximate integral (scipy's quad):", quad(func_np, t_start_np, t_end_np))
This outputs:
approximate integral (np.trapz): 0.04209721470548062
approximate integral (scipy's quad): (-2.3852447794681098e-18, 5.516333374450447e-10)
Note the huge values on the y-axis, and the small values on the x-axis. These values, as well as matematica's, could well be rounding errors.

Difficult case with TypeError: only size-1 arrays can be converted to Python scalars

I am trying to use plotly to graph a huge function which is in turn a sum of other functions - I want to append the smaller functions to arrays and add them up to the final function. Process with simple functions works, e.g.:
import numpy as np
import plotly.graph_objects as go
pi = math.pi
X, Y, Z = np.mgrid[-2:2:100j, -2:2:100j, -2:2:100j]
x=[pi*2,4]
values1 = pi*X*X+Y*Y
values2 = Z*Z
values.append(values1*x[0])
values.append(values2*x[1])
valuestot=values[0]+values[1]
fig = go.Figure(data=go.Isosurface(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=valuestot.flatten(),
isomin=-0.1,
isomax=0.1
))
fig.show()
However, problem occurs when I use a longer function (respective to values1), for example:
n1s2 = nns21 * (((3 * nas21 / pi) ** (1 / 4)) * math.exp( -nas21 * ((X + cXN1) ** 3 + (Y + cYN1) ** 2 + (Z + cZN1) ** 2))) + nns22 * ( ((2 * nas22 / pi) ** (1 / 4)) * math.exp( -nas22 * ((X + cXN1) ** 2 + (Y + cYN1) ** 3 + (Z + cZN1) ** 2)))
gives the TypeError: only size-1 arrays can be converted to Python scalars error for the line of the function in the code.
I tried all the solutions with np.vectorize() given on different forums, yet that does not help, as python presumably reads the long line as a list of items. How could I make the line read as a single function which is recognized by python? Thank you for your help.
Succeeded - got a suggestion from a brilliant CS student to change math.exp() to np.exp() so that different exponents account for separate mgrid vectors (X,Y,Z).

Convert equations to Python language

How can I convert this equation to Python code
enter image description here
You can need to learn about operator precedence and associativity in Programming Languages. That way you can strengthen your understanding of how to perform complex calculations in Python.
Apart from that try to break the problem into smaller subproblems and combine the smaller subproblems to generate solution for the larger problem.
[0.38C(1-g/C)2] = (0.38 * C) * (1 - (g/C) * 2)
[1-(g/C)(X)] = (1 - (g/C) * X)
173X2 = 173 * 2
[(X-1)+[(X-1)2 + (16X/C)]1/2] = ((X-1)+((X-1)*2 + (16*X/C))* 1/2)
Now put all values in the equation:
"d=[0.38C(1-g/C)2]/[1-(g/C)(X)]+173X2[(X-1)+[(X-1)2 + (16X/C)]1/2]"
d = (((0.38 * C)*(1 - (g/c)) * 2 ) / (1 - (g/C) * X)) + 172 * 2 *((X-1) +((X-1)+((X-1)*2 + (16*X/C))* 1/2)

How can I run a odeint function with a for loop at the same time?

I need to run 3 variables that vary through time inside a odeint function. I have 3 arrays with multiple elements and I want the odeint function to use the 1st element of the arrays for t=0, the 2nd element of the array for t=1...
I have tried placing the "for" inside "def" which results in it using only the first element of the arrays and if I place "def" inside "for" results in it only using the last element of the array
The arrays with multiple elements are: ur; utheta; uphi and they are calculated elsewhere in the code
here I can set up how many elements the arrays have and the time of simulation
The arrays with multiple elements are: ur; utheta; uphi and they are calculated elsewhere in the code
The number of elements is the same number as "time" given in the code
time=10
def c(zc,t):
for cc in range(0, time):
x1=zc[0]
x2=zc[1]
x3=zc[2]
x4=zc[3]
x5=zc[4]
x6=zc[5]
dx1dt=x2
dx2dt= x1 * (x4 ** 2) * (sin(x5) ** 2) + x1 * (x6 ** 2) - (mu / (x1 ** 2)) + (3 / 2) * mu * J2 * (ae ** 2) * (3 * (((cos(x5)) ** 2) - 1) / (x1 ** 4)) + ur[cc]
dx3dt=x4
dx4dt= -((2*x2*x4) / x1) - 2 * x4 * x6 * cot(x5) + (utheta[cc] / (x1 * sin(x5)))
dx5dt=x6
dx6dt= -((2*x2*x6) / x1) + (x4 ** 2) * sin(x5) * cos(x5) + 3 * mu * J2 * ((ae ** 2) / (x1 ** 5)) * cos(x5) * sin(x5) + (uphi[cc] / x1)
print(ur[cc])
return [dx1dt, dx2dt, dx3dt, dx4dt, dx5dt, dx6dt]
z0 = [r, rdot, theta, thetadot, phi, phidot] #initial conditions provided elsewhere
t=np.linspace(0,time,time)
zc=odeint(c,z0,t)
using "print(ur[cc])" I can see that "ur" is not varying through time like I want it to
First and foremost: Providing a runnable example will help answerers of your question.
I'm assuming you're using scipy's odeint function
A few issues:
time is not an input to your function, but you use it in your function. While things may work for now, this is going to lead to unexpected behavior down the line.
You have a return statement inside your for-loop. So, you're only actually every running the case where cc = 0.
Rather than a for-loop, you should try vectorizing your code. Here's an article which has some examples (NOTE: I skimmed it, but didn't read it in full).
The docs indicate you should use scipy.integrate.solve_ivp instead of scipy.integrate.odeint

What's wrong with this function to solve cubic equations?

I am using Python 2 and the fairly simple method given in Wikipedia's article "Cubic function". This could also be a problem with the cube root function I have to define in order to create the function mentioned in the title.
# Cube root and cubic equation solver
#
# Copyright (c) 2013 user2330618
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://www.mozilla.org/MPL/2.0/.
from __future__ import division
import cmath
from cmath import log, sqrt
def cbrt(x):
"""Computes the cube root of a number."""
if x.imag != 0:
return cmath.exp(log(x) / 3)
else:
if x < 0:
d = (-x) ** (1 / 3)
return -d
elif x >= 0:
return x ** (1 / 3)
def cubic(a, b, c, d):
"""Returns the real roots to cubic equations in expanded form."""
# Define the discriminants
D = (18 * a * b * c * d) - (4 * (b ** 3) * d) + ((b ** 2) * (c ** 2)) - \
(4 * a * (c ** 3)) - (27 * (a ** 2) * d ** 2)
D0 = (b ** 2) - (3 * a * c)
i = 1j # Because I prefer i over j
# Test for some special cases
if D == 0 and D0 == 0:
return -(b / (3 * a))
elif D == 0 and D0 != 0:
return [((b * c) - (9 * a * d)) / (-2 * D0), ((b ** 3) - (4 * a * b * c)
+ (9 * (a ** 2) * d)) / (-a * D0)]
else:
D1 = (2 * (b ** 3)) - (9 * a * b * c) + (27 * (a ** 2) * d)
# More special cases
if D != 0 and D0 == 0 and D1 < 0:
C = cbrt((D1 - sqrt((D1 ** 2) - (4 * (D0 ** 3)))) / 2)
else:
C = cbrt((D1 + sqrt((D1 ** 2) - (4 * (D0 ** 3)))) / 2)
u_2 = (-1 + (i * sqrt(3))) / 2
u_3 = (-1 - (i * sqrt(3))) / 2
x_1 = (-(b + C + (D0 / C))) / (3 * a)
x_2 = (-(b + (u_2 * C) + (D0 / (u_2 * C)))) / (3 * a)
x_3 = (-(b + (u_3 * C) + (D0 / (u_3 * C)))) / (3 * a)
if D > 0:
return [x_1, x_2, x_3]
else:
return x_1
I've found that this function is capable of solving some simple cubic equations:
print cubic(1, 3, 3, 1)
-1.0
And a while ago I had gotten it to a point where it could solve equations with two roots. I've just done a rewrite and now it's gone haywire. For example, these coefficients are the expanded form of (2x - 4)(x + 4)(x + 2) and it should return [4.0, -4.0, -2.0] or something similar:
print cubic(2, 8, -8, -32)
[(-4+1.4802973661668753e-16j), (2+2.9605947323337506e-16j), (-2.0000000000000004-1.1842378929335002e-15j)]
Is this more a mathematical or a programming mistake I'm making?
Update: Thank you, everyone, for your answers, but there are more problems with this function than I've iterated so far. For example, I often get an error relating to the cube root function:
print cubic(1, 2, 3, 4) # Correct solution: about -1.65
...
if x > 0:
TypeError: no ordering relation is defined for complex numbers
print cubic(1, -3, -3, -1) # Correct solution: about 3.8473
if x > 0:
TypeError: no ordering relation is defined for complex numbers
Wolfram Alpha confirms that the roots to your last cubic are indeed
(-4, -2, 2)
and not as you say
... it should return [4.0, -4.0, -2.0]
Not withstanding that (I presume) typo, your program gives
[(-4+1.4802973661668753e-16j), (2+2.9605947323337506e-16j), (-2.0000000000000004-1.1842378929335002e-15j)]
Which to accuracy of 10**(-15) are the exact same roots as the correct solution. The tiny imaginary part is probably due, as others have said, to rounding.
Note that you'll have to use exact arithmetic to always correctly cancel if you are using a solution like Cardano's. This one of the reasons why programs like MAPLE or Mathematica exist, there is often a disconnect from the formula to the implementation.
To get only the real portion of a number in pure python you call .real. Example:
a = 3.0+4.0j
print a.real
>> 3.0
Hooked's answer is the way to go if you want to do this numerically. You can also do it symbolically using sympy:
>>> from sympy import roots
>>> roots('2*x**3 + 8*x**2 - 8*x - 32')
{2: 1, -4: 1, -2: 1}
This gives you the roots and their multiplicity.
You are using integer values - which are not automatically converted to floats by Python.
The more generic solution will be to write coefficients in the function as float numbers - 18.0 instead of 18, etc. That will do the trick
An illustration - from the code:
>>> 2**(1/3)
1
>>> 2**(1/3.)
1.2599210498948732
>>>

Categories