How can I resolve this binomial equation by coding? - python

I'm having a problem finding out how to discover the write function to solve this problem:
Write a function that will take as an input two numbers (l,m) and return as a tuple the coefficients (a,b,c) for the quadratic equation a x^2 + b x + c found from expanding (x + l) * (x + m).
def func(l,m):
a = 1
equation = (a * (x ** 2)) + (b * x) + c
coef = [a,b,c]
eq2 = (x + m) * (x + l)
coef1 = m + l
coef2 = m * l
if coef1 == coef[1] and coef2 == coef[2]:
return coef
func(2,2)

Just to make it clear:
Your problem states:
return as a tuple the coefficients (a,b,c) for the quadratic equation
a x^2 + b x + c found from expanding (x + l) * (x + m).
Let's find the equation by expanding:
(x + l) * (x + m) =
= x^2 + l*x + m*x + l*m =
= x^2 + (l+m)*x + l*m
Now, by coefficients comparison with a x^2 + b x + c, we get that:
a = 1
b = l + m
c = l * m
So your function can basically return (1, l + m, l * m) directly...

Now that we have your code, I can tell you you're not using Python functions right. You can't create an unknown variable as you can do in math (here you called x)
There are modules who allow such operation with different syntax such as SymPy.
If you don't want to use it and you want to solve it "by-hand" maybe for a school project you'll need to compute a, b and conly from l and m with formulas.
As mentionned Tomerikoo
a = 1
b = l + m
c = l * m

Related

Numpy to solve multi-variable algebraic function

Let's assume we know the following:
a = 1
b = 4
c = 7
d = 2
e = 2
f = 9
With these six variables, we can solve for X, Y, and Z as follows:
X = (b - a) / (d + e)
Y = 2 * np.sin(X/2) * ((c / X) + f)
Z = 2 * np.sin(X/2) * ((a / X) + d)
print(X)
print(Y)
print(Z)
0.75
13.42999273315508
2.4418168605736503
Now, let's flip things around and assume that we're given the values of X, Y, and Z, as well as d, e, and f.
How would we solve for the values of a, b, and c? My algebra is shaky. Is this something that Numpy can handle?
Thanks!
Numpy, no. (Or rather, not as easily, or accurately.)
Sympy, yes.
Declare a, b and c as symbols.
Create expressions that should equal to zero (by moving the left hand side of the equation to the right hand side and changing the sign).
Use sympy.sin instead of math.sin or np.sin.
Use sympy.solve to get the solution of the system.
import sympy
from sympy.abc import a, b, c
X = 0.75
Y = 13.42999273315508
Z = 2.4418168605736503
d = 2
e = 2
f = 9
e1 = (b - a) / (d + e) - X
e2 = 2 * sympy.sin(X/2) * ((c / X) + f) - Y
e3 = 2 * sympy.sin(X/2) * ((a / X) + d) - Z
sympy.solve([e1, e2, e3])
# => {a: 1.00000000000000, b: 4.00000000000000, c: 7.00000000000000}
Solving equations with unknown variables can be done in Sympy.
from sympy import symbols, solve, Eq, sin
a, b, c, d, e, f, X, Y, Z = symbols("a b c d e f X Y Z")
eqns = [
Eq(X, (b - a) / (d + e)),
Eq(Y, 2 * sin(X / 2) * ((c / X) + f)),
Eq(Z, 2 * sin(X / 2) * ((a / X) + d)),
]
assignments = {a: 1, b: 4, c: 7, d: 2, e: 2, f: 9}
print(solve([eq.subs(assignments) for eq in eqns], [X, Y, Z]))
Output:
[(3/4, 110*sin(3/8)/3, 20*sin(3/8)/3)]
To solve for a, b, c just replace X, Y, Z in solve and add their values in the assignments dict.

how to calculate the integral with temporal data?

I would like to compute the integral of discrete signal segment Y (Y=[y1,y2,...y50]) and X is the following datetime64[ns] object:
x=['2018-01-24T13:41:25.057000000' '2018-01-24T13:41:25.069000000'
'2018-01-24T13:41:25.077000000' '2018-01-24T13:41:25.090000000'
'2018-01-24T13:41:25.097000000' '2018-01-24T13:41:25.111000000'
'2018-01-24T13:41:25.117000000' '2018-01-24T13:41:25.130000000'
'2018-01-24T13:41:25.138000000' '2018-01-24T13:41:25.150000000'
'2018-01-24T13:41:25.158000000' '2018-01-24T13:41:25.170000000'
'2018-01-24T13:41:25.178000000' '2018-01-24T13:41:25.199000000'
'2018-01-24T13:41:25.200000000' '2018-01-24T13:41:25.211000000'
'2018-01-24T13:41:25.218000000' '2018-01-24T13:41:25.231000000'
'2018-01-24T13:41:25.238000000' '2018-01-24T13:41:25.250000000'
'2018-01-24T13:41:25.258000000' '2018-01-24T13:41:25.269000000'
'2018-01-24T13:41:25.278000000' '2018-01-24T13:41:25.290000000'
'2018-01-24T13:41:25.298000000' '2018-01-24T13:41:25.311000000'
'2018-01-24T13:41:25.317000000' '2018-01-24T13:41:25.331000000'
'2018-01-24T13:41:25.338000000' '2018-01-24T13:41:25.350000000'
'2018-01-24T13:41:25.358000000' '2018-01-24T13:41:25.370000000'
'2018-01-24T13:41:25.378000000' '2018-01-24T13:41:25.390000000'
'2018-01-24T13:41:25.398000000' '2018-01-24T13:41:25.411000000'
'2018-01-24T13:41:25.418000000' '2018-01-24T13:41:25.430000000'
'2018-01-24T13:41:25.437000000' '2018-01-24T13:41:25.450000000'
'2018-01-24T13:41:25.469000000' '2018-01-24T13:41:25.469000000'
'2018-01-24T13:41:25.479000000' '2018-01-24T13:41:25.493000000'
'2018-01-24T13:41:25.502000000' '2018-01-24T13:41:25.510000000'
'2018-01-24T13:41:25.517000000' '2018-01-24T13:41:25.530000000'
'2018-01-24T13:41:25.537000000' '2018-01-24T13:41:25.550000000']
My attempt is using the following python code:
Case A, with the above x:
f_x_tot_acc = Y
x_n = x[-1]
x_0 = x[0]
h = (x_n - x_0) / (len(f_x_tot_acc) - 1)
print('trapz [' + str(integrate.trapz(f_x_tot_acc, dx=h)) + ']')
The Result is: trapz [6203255447 nanoseconds]
Case B,
x = range(0,50)
f_x_tot_acc = Y
x_n = x[-1]
x_0 = x[0]
h = (x_n - x_0) / (len(f_x_tot_acc) - 1)
print('trapz [' + str(integrate.trapz(f_x_tot_acc, dx=h)) + ']')
The Result is: trapz [616.5507767408332].
Which is the correct one?
Many Thanks in advance,
Best Regards,
Carlo

Having problems making this program run faster for large inputs

def calculate(i,j,m,k,n):
for v in range(1,n+1):
ans = (i*k + j) % m
k = ans
return ans
The program represents a general formula where x = (i * k + j) % m where k is the value of the previous answer. In a sense, it's basically x1 = (i * x0 + j) % m, and x2 = (i * x1 + j) % m, and so forth. The problem I'm having is that it takes a long while to calculate large inputs.
With that in mind, I was thinking along the lines of using an arithmetic series formula such as: a + (n - 1) * d), but I'm unsure on how to implement it in a program such as this.
x1 = (i * x0 + j)
x2 = (i * x1 + j) = i * i * x0 + i * j + j
x3 = i * i * i * x0 + i * i * j + i * j + j
xn = i^n * x0 + sum(i^t for t from 0 to n - 1) * j
= i^n * x0 + (i^n - 1) / (i - 1) * j
Found the last line with Wolfram Alpha.
The formula is nice if m is a prime.
In that case you can perform all the computations modulo that prime,
including the division, to keep the numbers small.
You'd just need to get exponentiation i^n fast.
I suggest you look at https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method and references therein.
This should give you O(log(n)) time complexity, compared to the O(n) of your loop.
If m is not a prime, the division in the above formula is annoying. But you can do something similar to exponentiation by squaring to compute the sum, too. Observe
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+1) =
(1 + i) * (1 + i^2 + i^4 + i^6 + … + i^n)
1 + i + i^2 + i^3 + i^4 + i^5 + i^6 + … + i^(2n+2) =
1 + (i + i^2) * (1 + i^2 + i^4 + i^6 + … + i^n)
so you can half the number of summands in the right parenthesis at each step. Now there is no division, so you can perform modulo operations after each operation.
You can thus define something like
def modpowsum(a, n, m):
"""(1 + a + a^2 + a^3 + ... + a^n) mod m"""
if n == 0:
return 1
if n == 1:
return (1 + a) % m
if n % 2 == 1:
return ((1 + a) * modpowsum((a * a) % m, (n - 1) // 2, m)) % m
return (1 + ((a + a * a) % m) * modpowsum((a * a) % m, n // 2 - 1, m)) % m
The whole computation can be seen at https://ideone.com/Xh0Fuf running some random and some not-so-random test cases against your implementation.

Way to solve constraint satisfaction faster than brute force?

I have a CSV that provides a y value for three different x values for each row. When read into a pandas DataFrame, it looks like this:
5 10 20
0 -13.6 -10.7 -10.3
1 -14.1 -11.2 -10.8
2 -12.3 -9.4 -9.0
That is, for row 0, at 5 the value is -13.6, at 10 the value is -10.7, and at 20 the value is -10.3. These values are the result of an algorithm in the form:
def calc(x, r, b, c, d):
if x < 10:
y = (x * r + b) / x
elif x >= 10 and x < 20:
y = ((x * r) + (b - c)) / x
else:
y = ((x * r) + (b - d)) / x
return y
I want to find the value of r, b, c, and d for each row. I know certain things about each of the values. For example, for each row: r is in np.arange(-.05, -.11, -.01), b is in np.arange(0, -20.05, -.05), and c and d are in np.arange(0, 85, 5). I also know that d is <= c.
Currently, I am solving this with brute force. For each row, I iterate through every combination of r, b, c, and d and test if the value at the three x values is equal to the known value from the DataFrame. This works, giving me a few combinations for each row that are basically the same except for rounding differences.
The problem is that this approach takes a long time when I need to run it against 2,000+ rows. My question is: is there a faster way than iterating and testing every combination? My understanding is that this is a constraint satisfaction problem but, after that, I have no idea what to narrow in on; there are so many types of constraint satisfaction problems (it seems) that I'm still lost (I'm not even certain that this is such a problem!). Any help in pointing me in the right direction would be greatly appreciated.
I hope i understood the task correctly.
If you know the resolution/discretization of the parameters, it looks like a discrete-optimization problem (in general: hard), which could be solved by CP-approaches.
But if you allow these values to be continuous (and reformulate the formulas), it is:
(1) a Linear Program: if checking for feasible values (there needs to be a valid solution)
(2) a Linear Program: if optimizing parameters for minimization of sum of absolute differences (=errors)
(3) a Quadratic Program: if optimizing parameters for minimization of sum of squared differences (=errors) / equivalent to minimizing euclidean-norm
All three versions can be solved efficiently!
Here is a non-general (could be easily generalized) implementation of (3) using cvxpy to formulate the problem and ecos to solve the QP. Both tools are open-source.
Code
import numpy as np
import time
from cvxpy import *
from random import uniform
""" GENERATE TEST DATA """
def sample_params():
while True:
r = uniform(-0.11, -0.05)
b = uniform(-20.05, 0)
c = uniform(0, 85)
d = uniform(0, 85)
if d <= c:
return r, b, c, d
def calc(x, r, b, c, d):
if x < 10:
y = (x * r + b) / x
elif x >= 10 and x < 20:
y = ((x * r) + (b - c)) / x
else:
y = ((x * r) + (b - d)) / x
return y
N = 2000
sampled_params = [sample_params() for i in range(N)]
data_5 = np.array([calc(5, *sampled_params[i]) for i in range(N)])
data_10 = np.array([calc(10, *sampled_params[i]) for i in range(N)])
data_20 = np.array([calc(20, *sampled_params[i]) for i in range(N)])
data = np.empty((N, 3))
for i in range(N):
data[i, :] = [data_5[i], data_10[i], data_20[i]]
""" SOLVER """
def solve(row):
""" vars """
R = Variable(1)
B = Variable(1)
C = Variable(1)
D = Variable(1)
E = Variable(3)
""" constraints """
constraints = []
# bounds
constraints.append(R >= -.11)
constraints.append(R <= -.05)
constraints.append(B >= -20.05)
constraints.append(B <= 0.0)
constraints.append(C >= 0.0)
constraints.append(C <= 85.0)
constraints.append(D >= 0.0)
constraints.append(D <= 85.0)
constraints.append(D <= C)
# formula of model
constraints.append((1.0 / 5.0) * B + R == row[0] + E[0]) # alternate function form: b/x+r
constraints.append((1.0 / 10.0) * B - (1.0 / 10.0) * C == row[1] + E[1]) # alternate function form: b/x-c/x+r
constraints.append((1.0 / 20.0) * B - (1.0 / 20.0) * D == row[2] + E[2]) # alternate function form: b/x-d/x+r
""" Objective """
objective = Minimize(norm(E, 2))
""" Solve """
problem = Problem(objective, constraints)
problem.solve(solver=ECOS, verbose=False)
return R.value, B.value, C.value, D.value, E.value
start = time.time()
for i in range(N):
r, b, c, d, e = solve(data[i])
end = time.time()
print('seconds taken: ', end-start)
print('seconds per row: ', (end-start) / N)
Output
('seconds taken: ', 20.620506048202515)
('seconds per row: ', 0.010310253024101258)

solving equations simultaneously

I have the following set of equations, and I want to solve them simultaneously for X and Y. I've been advised that I could use numpy to solve these as a system of linear equations. Is that the best option, or is there a better way?
a = (((f * X) + (f2 * X3 )) / (1 + (f * X) + (f2 * X3 ))) * i
b = ((f2 * X3 ) / (1 + (f * X) + (f2 * X3))) * i
c = ((f * X) / (1 + (j * X) + (k * Y))) * i
d = ((k * Y) / (1 + (j * X) + (k * Y))) * i
f = 0.0001
i = 0.001
j = 0.0001
k = 0.001
e = 0 = X + a + b + c
g = 0.0001 = Y + d
h = i - a
As noted by Joe, this is actually a system of nonlinear equations. You are going to need more firepower than numpy alone provides.
Solution of nonlinear equations is tricky, and the typical approach is to define an objective function
F(z) = sum( e[n]^2, n=1...13 )
where z is a vector containing a value for each of your 13 variables a,b,c,d,e,f,g,h,i,X,Y and e[n] is the amount by which each of your 13 equations is violated. For example
e[3] = (d - ((k * Y) / (1 + (j * X) + (k * Y))) * i )
Once you have that objective function, then you can apply a nonlinear solver to try to find a z for which F(z)=0. That of course corresponds to a solution to your equations.
Commonly used solvers include:
The Solver in Microsoft Excel
The python library scipy.optimize
Fitting routines in the Gnu Scientific Library
Matlab's optimization toolbox
Note that all of them will work far better if you first alter your set of equations to eliminate as many variables as practical before trying to run the solver (e.g. by substituting for k wherever it is found). The reduced dimensionality makes a big difference.

Categories