I need to get 3 values from 3 equations as part of an error correcting method for S-parameters. The equations are shown below.
The matlab code went as follows.
syms a b c
eqn1 = (G_A1*a)+(b)-(G_A1*G_M1*c) == G_M1; %short
eqn2 = (G_A2*a)+(b)-(G_A2*G_M2*c) == G_M2; %load
eqn3 = (G_A3*a)+(b)-(G_A3*G_M3*c) == G_M3; %open
%[A,B] = equationsToMatrix([eq1, eq2, eq3], [a, b, c]);
%res = linsolve(A,B);
sol = solve([eqn1, eqn2, eqn3], [a, b, c]);
aSol = sol.a;
bSol = sol.b;
cSol = sol.c;
Giving me the results:
4.9284 - 2.8505i
-11.1951 -37.7373i
-31.2705 -64.5481i
The code used in Python was
a = np.array([[G_A1,G_A2,G_A3], [1,1,1], [(-G_A1*G_M1),(-G_A2*G_M2),(-G_A3*G_M3)]])
b = np.array([G_M1,G_M2,G_M3])
x = np.linalg.solve(a, b)
Giving
-0.24421332 -0.021397452j
-10.1681071 -37.679968ej
-0.77652264 -0.0377357202j
It the code used in Python incorrect?
You need to switch columns and rows in your a-matrix. Try the following change to your python code and you should get the same results as in matlab.
a = np.array([[G_A1,G_A2,G_A3], [1,1,1], [(-G_A1*G_M1),(-G_A2*G_M2),(-G_A3*G_M3)]])
a = a.transpose()
b = np.array([G_M1,G_M2,G_M3])
x = np.linalg.solve(a, b)
To understand this, consider your example, and take the first row of a*x.
This would result in
G_A1*x1+G_A2*x2+G_A3*x3 = G_M1
Looking at your picture, what you want is a.transpose()*x.
Related
Hello wonderful people,
I am building a physics model for some project. I have found a nice equation for my interest variable, but I would like to be able to solve the problem repeatedly with different parameters. What I would like to do is to save my equation as an object in a file (using pickle for example), then loading it at runtime and feed it the parameters it needs.
How would you achieve this?
With a simple example, the whole process would look like this:
(in a jupyter notebook)
import sympy as sp
import pickle
a, b, c = symbols("a b c")
eqn = sp.Eq(b + c, a) #for a real equation I would simplify it before using sympy
with open("eqn.txt") as f:
pickle.dump(eqn, f)
and then later in the app's code:
...
with open("eqn.txt") as f:
eqn = pickle.load(f)
b = 1
c = 2
#magic line to put b and c into the equation
a = sp.solve(eqn, a)
print(a) # 3
Implementing the whole equation directly in a function is probably not an option although I am considering how to implement it manually. It just looks really, really hard to do and if I could do it in two lines using simpy, that'd be great.
Thanks for your time!
with open("eqn.txt") as f:
eqn = pickle.load(f)
b, c = 1, 2 # b,c are python symbols here
reps = dict(zip(symbols('b c'), (b, c))) # keys are SymPy Symbols, values are 1,2
eqn = eqn.xreplace(reps) #magic line to put b and c into the equation
a = sp.solve(eqn, a)
print(a) # 3
It is important to keep in mind the distinction between b = 1 and b = Symbol('b'). The left hand side of the expressions are Python variables and on the right, an int or a SymPy Symbol, respectively. In a SymPy expression you might reference a Python variable and its value will be included in the equation:
>>> from sympy import *
>>> b = 1
>>> b + 1
2
>>> b = Symbol('b')
>>> b + 1
b + 1
>>> eq = _
>>> eq.subs(b,1)
2
>>> b=2 # assigning a new value to b does not change the object in eq
>>> eq
b + 1
>>> eq.subs(b, 2) # i.e., eq.subs(2,2) doesn't work -- no 2 in eq
b + 1
>>> eq.subs(Symbol('b'), 2) # replace the Symbol with value of 2 works
3
So in reps above, zipping the symbols to their corresponding values creates a mapping that can be used to do the replacement.
There is more discussion of such issues in the documentation gotchas file, but this should help with your current issue.
I'm trying to implement the multivariate chain rule using python, when I try to substitute one of the elements using the built-in sympy function expr.subs() I won't get an answer.
The exercise goes as follows:
Compute df/dx of the following function using the chain rule:
a = x^2
b = exp(a)
c = a + b
d = log(c)
e = sin(c)
f = d + e
And this is the code:
a, b, c, d, e, f = sym.symbols('a b c d e f')
f = d + e
dfd = sym.diff(f, d)
dfe = sym.diff(f, e)
df = sym.Matrix([[dfd, dfe]])
d = sym.log(c)
e = sym.sin(c)
ddc = sym.diff(d)
dde = sym.diff(e)
dd = sym.Matrix([[ddc],[dde]])
dfdd = df#dd
c = a + b
dca = sym.diff(c, a)
dcb = sym.diff(c, b)
dc = sym. Matrix([[dca, dcb]])
dfdc = dfdd#dc
a = x**2
b = sym.exp(a)
result = dfdc.subs(c, (a + b))
result
The result the function .subs() doesn't substitute anything and I don't know why, I tried substituting it using other ways to write the function, like:
dfdc.subs({c : (a + b)})
dfdc.subs(c, a + b)
And even tried to just substitute it for an integer to see it that would work and neither does it.
What am I doing wrong?
The c in your dfdc expression was created before you set c=a+b. So it still appears as c in dfdc. However, by the time you want to do your subs, the c symbol is declared as c=a+b, and so your substitute really reads
dfdc.subs(a+b, a+b)
And that does nothing.
In order to really use c there, do
dfdc.subs(sym.Symbol('c'), a+b)
I want to achieve this function in Python like Matlab
in matlab, the code is
A = [];
for ii = 0:9
B = [ii, ii+1, ii**2];
C = [ii+ii**2, ii-5];
A = [A, B, C];
end
but in Python, use np.hstack or np.concatenate, the ndarray must have same number of dimensions
if the A in first loop is empty, the code will make mistake as following:
for ii in range(10):
B = np.array([ii, ii+1, ii**2])
C = np.array([ii+ii**2, ii-5])
if ii == 0:
A = np.hstack([B, C])
else:
A = np.hstack([A, B, C])
and, that is my Python code, B and C are variable, not repeat the ndarray, plz don't close my question!
for ii in range(10):
B = np.array([ii, ii+1, ii**2])
C = np.array([ii+ii**2, ii-5])
if ii == 0:
A = np.hstack([B, C])
else:
A = np.hstack([A, B, C])
but, i think it a little troublesome and unreadable.
how can i rewrite it?(It's better to use only one line of code)
Without knowing what the result Should be - I think this is close
import numpy as np
q = np.arange(10)
bs = np.vstack((q,q+1,q**2)).T
cs = np.vstack((q,q**2,q-5)).T
a = np.hstack((bs,cs))
Or maybe:
a = np.hstack((bs,cs)).ravel()
I have written the following implementation of the Extended Euclidean Algorithm:
def extended_euclid(a, b):
x_k = 1 # read x_k
x_k1 = 0 # read x_(k+1)
y_k = 0 # read y_k
y_k1 = 1 # read y_(k+1)
sign = 1
while b != 0:
q = a//b
r = a - q*b
a = b
b = r
xx = x_k1
yy = y_k1
x_k1 = q*x_k1 + x_k
y_k1 = q*y_k1 + y_k
x_k = xx
y_k = yy
sign = -sign
x = sign*x_k
y = sign*y_k
return [a, x, y]
It works as exptected but when I try to print out the result of a function call using the standard function "print" the output gets printed twice. So when I do
print(extended_euclid(15,10))
I get the output
[5, 1, 1]
[5, 1, 1]
I do not understand why the output gets printed twice, could you explain that to me.
Also when I do
a = extended_euclid(15,10)
print(a[1])
I get
1
1
which I do not understand either.
EDIT: The problem was that I mistakenly imported a file twice, which led to some unexpected results. Maybe this helps somebody.
Check the rest of your code, if you print this euclid function somewhere, delete that print and just call function instead. On my machine this code prints only one result.
This question already has answers here:
Multiple assignment and evaluation order in Python
(11 answers)
Closed 9 years ago.
2 questions...
1) I am trying to wrap my brain around this...
I am to understand that variables can take values using such code syntax as this:
a ,b = 2, 3
and that this would be the same as coding:
a = 2
b = 3
I hope this is correct.
So here is my puzzlement. I have the following code using a generator:
def fibonacci_generator() :
a = b = 1
while True :
yield a
a , b = b , a + b
fib = fibonacci_generator()
for i in fib :
if i > 100 :
break
else :
print ('Generated: ', i)
print (next(fib))
(yes this is code from a python learning book)
If I were to rewrite this code and instead assign my a and b variables like so:
yield a
a = b
b = a + b
then I get different returns for a.
I am not understanding why this is??? Super frustrated about it!
2) When I run the code as written the first time above, I get the number 233 printed at the end. I also cannot figure out why??!!
In this code:
a, b = b, a + b
a is set to b, and b is set to a+b.
In this code:
a = b
b = a + b
a is set to b, and b is afterwards set to a+b. But since a is already set to b, then b is in fact set to b+b.
a , b = b , a + b
is not the same as
a = b
b = a + b
Because, when you say
a, b = b, a + b
It will first prepare the values on the right side b, a + b and assign them to the variables on the left.
Python computes the right hand side first and then assigns the value (or unpacks it) on the left hand side. So, in the example:
a, b = b, a+b
compared to:
a = b
b = a + b
You have different values for a when you go to compute a + b. In the second example, when you compute a + b it is equivalent to computing b + b!
You are probably missing the flow of data.
a = b ...eqI
b = a+b ...eqII
here, before executing b eqII, a has already stored bas a value of itself. Now when yow try execute b of eqII it comes like b=b+b. Because after executing eqI when it comes to eqII, a is bnow.
But in python you can avoid this conflict if you try a, b = b, a+b.
For your second question:
I am not sure about your code but this one will work fine in the sense of your code...
a = b = 1
while True :
a , b = b , a + b
if a and b > 100:
break
else: print a, b
try it !!
In an assignment statement, the right-hand side is always evaluated fully before doing the actual setting of variables. Because that you get different results
a, b = b, a+b
This line computes b and a+b before performing any assignment. Strictly speaking, it computes a tuple (b, a+b) and then unpacks the elements of the tuple to assign them to a and b.
a = b
b = a+b
This assigns a, then computes a+b using the new value of a.