Sympy Differential Equation : How to mowe some lhs terms to rhs? - sympy

I have the following differential equation : eq1
t = sp.Symbol("t")
f1=sp.Function("f1")(t)
f2=sp.Function("f2")(t)
eq1=sp.Eq(f1+f1.diff(t,2)-f2+f2.diff(t,1),0)
To move f2 terms from the lhs to the rhs, I used this code :
eq2=sp.Eq(eq1.lhs.subs(f2,0).doit(),eq1.lhs.subs(f1,0).doit()*-1)
Is it the right way to do that or is there a simpler solution ?
Thanks for answer.

That might fail if e.g. you have a 1/f1 somewhere. I'd do it like this:
In [18]: eq1
Out[18]:
2
d d
f₁(t) - f₂(t) + ───(f₁(t)) + ──(f₂(t)) = 0
2 dt
dt
In [19]: lhs, neg_rhs = (eq1.lhs - eq1.rhs).as_independent(f2, as_Add=True)
In [20]: eq2 = Eq(lhs, -neg_rhs)
In [21]: eq2
Out[21]:
2
d d
f₁(t) + ───(f₁(t)) = f₂(t) - ──(f₂(t))
2 dt
dt
https://docs.sympy.org/latest/modules/core.html#sympy.core.expr.Expr.as_independent

Related

How to replace log(x) by log(abs(x)) automatically in SymPy

I am trying to solve differential equation y'=cot(x) using Sympy:
x = symbols("x")
y = Function("y")(x)
dsolve(diff(y, x) - cot(x))
It gives me solution with logarithm: y(x) = C1 + log(sin(x)).
How I can replace in this expression log by combination log + abs: log(sin(x)) -> log(abs(sin(x)))? I can do it manually, but it's not very convenient. Is there any way to do it with SymPy tools (something like subs command)?
Note that the abs isn't actually needed: the integration constant C1 can include I*pi. The form without abs is valid for all complex x whereas the abs form is only valid for real x.
In any case, you can do it like this:
In [6]: sol
Out[6]: y(x) = C₁ + log(sin(x))
In [7]: sol.replace(log, lambda e: log(abs(e)))
Out[7]: y(x) = C₁ + log(│sin(x)│)

SYMPY : How to simplify expression with exponential functions?

I have expression with exponential functions and I would like to simplify them. Some of the exponential functions have a negative parameters.
To sum up my problem with a very trivial example :
a,b,c,d=sp.symbols("a b c d",real=True, positive=True)
myExpr=(sp.exp(c)+sp.exp(d))*sp.exp(-c-d)
myExpr.simplify() gave a simplified expression. That is perfect.
BUT, with a denominator in the expression, exponential functions with a negative parameter are not simplified :
a,b,c,d=sp.symbols("a b c d",real=True, positive=True)
myExpr=(sp.exp(c)+sp.exp(d))*sp.exp(-c-d)/a
How can I simplify it ?
As suggested in the comments, I submit a more complicated example :
import sympy as sp
a, b, c, d, e, f, c1, c2, t = sp.symbols("a b c d e f c_1 c_2 t", real=True, positive = True)
myExpr=((c1*sp.exp((a+b+c)*t)+c2*sp.exp((d+e+f)*t)))/(c1+c2)*sp.exp(-(a+b+c+d+e+f)*t)
And I would like an output as this one :
output= ((c1*sp.exp(-(e+d+f)*t)+c2*sp.exp(-(a+b+c)*t)))/(c1+c2)
Rq : with (a+b+c) in the same exp : exp ( -(a+b+c)*t ) and not as a product of exp : exp(-a*t)*exp(-b*t)*exp(-c*t), similarly for (d+e+f)
Thanks for answer.
Okay, I see the problem. When you have an Add in the numerator and the denominator expand distributes a "negative" power into the denominator:
In [45]: expr = (a*x + b*x)*(1/x)*(1/(c + d))
In [46]: expr
Out[46]:
a⋅x + b⋅x
─────────
x⋅(c + d)
In [47]: expand(expr)
Out[47]:
a⋅x b⋅x
───────── + ─────────
c⋅x + d⋅x c⋅x + d⋅x
It's less obvious with the exponential function because it shows in the numerator
In [48]: expr.subs(x, exp(t))
Out[48]:
⎛ t t⎞ -t
⎝a⋅ℯ + b⋅ℯ ⎠⋅ℯ
─────────────────
c + d
however expand still treats it as belonging to the denominator just as a power E**(-t) would.
In [51]: expand_mul(expr.subs(x, exp(t)))
Out[51]:
t t
a⋅ℯ b⋅ℯ
─────────── + ───────────
t t t t
c⋅ℯ + d⋅ℯ c⋅ℯ + d⋅ℯ
I can't think of an easier way to do it than this:
In [84]: factor_terms(sum(powsimp(factor_terms(cancel(a))) for a in Add.make_args(myExpr.expand())))
Out[84]:
-t⋅(d + e + f) -t⋅(a + b + c)
c₁⋅ℯ + c₂⋅ℯ
───────────────────────────────────────
c₁ + c₂

converting DFA to regular expression using Transitive closure method

The following example shows a simple DFA with one accepting state q2 :
Based on the R(i,j,k) Algorithm shown above i want to convert this DFA to regular expression, unfortunately i can't find a good definition of the K. My question is what does the K mean ?
is it the number of states (in this case 3) or something else?
Then, we solve those equations to get the equation for qi in terms of α ij and that expression is the required solution, where qi is a final state. It is shown below −
q 1= q a + q3a + € ( € move is because q1is the initial state)
q2 = q1b + q2b + q3b
q3 = q2a
Now, we will solve these equations, as shown below−
. q2 = q1b + q2b + q3b
= q1b + q2b + (q2a)b (Substituting value of q3)
= q1b + q2(b + ab)
= q1b (b + ab) * (Applying Arden's Theorem)
. q1 = q1a + q3a + €
= q1a + q2aa + € (Substituting value of q3)
= q1a + q1b(b + ab*)aa + € (Substituting value of q2)
= q1(a + b(b + ab) *aa) + €
= € (a+ b(b + ab) *aa) *
= (a + b(b + ab) *aa) *
Hence, the regular expression is (a + b(b + ab) *aa) *.

Matching coefficients with sympy

I am attempting to work a problem from a textbook in sympy, but sympy fails to find a solution which appears valid. For interest, it is the design of a PID controller using direct synthesis with a second order plus dead time model.
The whole problem can be reduced to finding K_C, tau_I and tau_D which will make
K_C*(s**2*tau_D*tau_I + s*tau_I + 1)/(s*tau_I)
= (s**2*tau_1*tau_2 + s*tau_1 + s*tau_2 + 1)/(K*s*(-phi + tau_c))
for given tau_1, tau_2, K and phi.
I have tried to solve this by matching coefficients:
import sympy
s, tau_c, tau_1, tau_2, phi, K = sympy.symbols('s, tau_c, tau_1, tau_2, phi, K')
target = (s**2*tau_1*tau_2 + s*tau_1 + s*tau_2 + 1)/(K*s*(-phi + tau_c))
K_C, tau_I, tau_D = sympy.symbols('K_C, tau_I, tau_D', real=True)
PID = K_C*(1 + 1/(tau_I*s) + tau_D*s)
eq = (target - PID).together()
eq *= sympy.denom(eq).simplify()
eq = sympy.poly(eq, s)
sympy.solve(eq.coeffs(), [K_C, tau_I, tau_D])
This returns an empty list. However, the textbook provides the following solution:
booksolution = {K_C: 1/K*(tau_1 + tau_2)/(tau_c - phi),
tau_I: tau_1 + tau_2,a
tau_D: tau_1*tau_2/(tau_1 + tau_2)}
Which appears to satisfy the equations I'm trying to solve:
[c.subs(booksolution).simplify() for c in eq.coeffs()]
returns
[0, 0, 0]
Can I massage this into a form which sympy can solve? What am I doing wong?
Edit: This finds the correct solution, but requires a little too much thought from my side to order the equations:
eqs = eq.coeffs()
solution = {}
solution[K_C] = sympy.solve(eqs[1], K_C)[0]
solution[tau_D] = sympy.solve(eqs[0], tau_D)[0].subs(solution)
solution[tau_I] = sympy.solve(eqs[2], tau_I)[0].subs(solution).simplify()
In SymPy 1.0 (to be released soon) I get this answer
In [25]: sympy.solve(eq.coeffs(), [K_C, tau_I, tau_D])
Out[25]:
⎡ ⎧ -(τ₁ + τ₂) τ₁⋅τ₂ ⎫⎤
⎢{K_C: 0, τ_I: 0}, ⎨K_C: ───────────, τ_D: ───────, τ_I: τ₁ + τ₂⎬⎥
⎣ ⎩ K⋅(φ - τ_c) τ₁ + τ₂ ⎭⎦
which looks like your textbook's solution.

Combining values from an arbitrary number of pandas columns into a new column — a 'join' in the not-SQL sense

I'm trying to do what's described here, but it's not the case that only one of my columns is populated, and I want to have a delimiter.
The code I'd like to replace (with something that will take an arbitrary number of k's) is:
raw_df["all ks"] = raw_df["k1"].fillna("") + "/" + \
raw_df["k2"].fillna("") + "/" + \
raw_df["k3"].fillna("") + "/" + \
raw_df["k4"].fillna("")
I wondered if this solution could be somehow responsive, but I'm hoping for something simpler.
Thanks for any helpful suggestions. Searching the web has been frustrating because I'm trying to do a join (in the pythonic sense) and most search results relate to joining columns in the database sense (including as adapted in pandas).
You could use the cat string method to concatenate the string values. With this method you can specify the delimiter and what the NaN values should be replaced with.
For example, here's a DataFrame:
>>> df = pd.DataFrame({'a': ['x', np.nan, 'x'],
'b': ['y', 'y', np.nan],
'c': ['z', 'z', np.nan]})
a b c
0 x y z
1 NaN y z
2 x NaN NaN
Then starting with column a and passing in the remaining columns using a list comprehension:
>>> df['a'].str.cat(others=[df[col] for col in df.columns[1:]],
sep='/', na_rep='')
0 x/y/z
1 /y/z
2 x//
So this is what I came up. It uses Apply() and a function. Not as concise as I hoped, but it works with an arbitrary number of Ks. Maybe someone will come up with something better
Generating a dataframe
d = {'k1' : [np.nan,'a','b'], 'k2' : ['c', np.nan, 'c'], 'k3' : ['r','t',np.nan], 'k4': [np.nan,'t','e']}
raw_df = pd.DataFrame(d)
raw_df
k1 k2 k3 k4
0 Nan c r Nan
1 a Nan t t
2 b c Nan e
define a function
def concatKs(s):
allK = ''
for k in s:
if k is not np.nan:
allK += k + '/'
else:
allK += '' + '/'
return allK
then the apply() and passing our function
raw_df['all ks'] = raw_df.apply(concatKs, axis=1)
raw_df
k1 k2 k3 k4 all ks
0 NaN c r NaN /c/r//
1 a NaN t t a//t/t/
2 b c NaN e b/c//e/