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₂
Related
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
I would like to see continued fractions with integers displayed in that form with SymPy, but I cannot seem to make SymPy comply. I found this Stack Overflow question and answer very useful (see farther below), but cannot reach my target goal here:
This is the continued fraction expansion of $\frac{13}{5}$. A common notation for this expansion is to give only the boxed terms as does SymPy below, i.e., $[2,1,1,2]$ from the SymPy continued_fraction_iterator:
Rat_13_5 = list(continued_fraction_iterator(Rational(13, 5)))
print( Rat_13_5 )
Rat_13_5 = list(continued_fraction_iterator(Rational(13, 5)))
( Rat_13_5 )
print( Rat_13_5 )
With output [2, 1, 1, 2].
Pg 37 of the Sympy manual release 1.5 Dec 9, 2019 gives a code snippet to print such an expanded fraction list:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr += i
expr = 1/expr
return l[0] + expr
If you invoke list_to_frac with the Rat_13_5 continued fraction expansion list, SymPy takes off and evaluates it:
print( list_to_frac( Rat_13_5 ) )
with output 13/5
If you use a list of symbols instead, then list_to_frac prints the desired continued fraction, e.g.,
n1, n2, n3, n4, n5, n6, n7, n8, n9 = symbols('n1:10')
cont_frac_list = [n2, n1, n1, n2]
contfrac12201015 = list_to_frac( [n2,n1,n1,n2] )
contfrac122010154
Which produces the desired (I am working in a JupyterLab environment so am actually obtaining typset LaTeX output throughout):
n2 + 1/(n1 + 1/(n1 + 1/n2))
I rewrote list_to_frac to use the UnevaluatedExpr facility presented by Francesco in the StackOverflow question I cited earlier:
def list_to_frac_noEval(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = UnevaluatedExpr(expr + i)
expr = UnevaluatedExpr( 1/expr )
return l[0] + expr
Invoking list_to_frac_noEval on the $\frac{13}{5}$ expansion list:
list_to_frac_noEval( [2,1,1,2] )
I obtain output
2 + (1 + (1 + 2**(-1))**(-1))**(-1)
Some folks use that notation (so I wanted to share list_to_frac_noEval in any case, that being superior to ending up with an evaluated single rational if you want to see the continued fraction), for example Roger Penrose in section $\unicode{x00A7}3.2$ of The Road to Reality (2004), but I still find it annoying that I cannot obtain the explicit continued fraction format when using integers instead of symbols.
I experimented with substituting in integers for symbols with evaluate=False, using both the subs method and the Subs function, looked at various combinations of sympify and srepr and parse_expr with evaluate=False, , but cannot persuade SymPy 1.4 to print the explicit fraction form that I obtain with list_to_frac operating on symbol arguments. Is there a way to accomplish this short of modifying SymPy code or special casing a particular set of numbers?
You can construct the expression explicitly passing evaluate=False to each part of the expression tree:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = Add(i, expr, evaluate=False)
expr = Pow(expr, -1, evaluate=False)
return Add(l[0], expr, evaluate=False)
That gives:
In [2]: nums = list(continued_fraction_iterator(Rational(13, 5)))
In [3]: nums
Out[3]: [2, 1, 1, 2]
In [4]: list_to_frac(nums)
Out[4]:
1
───────────── + 2
1
───────── + 1
1
───── + 1
0 + 2
It looks like it's the wrong way around but that's just the way the printing works with default settings:
In [5]: init_printing(order='old')
In [6]: list_to_frac(nums)
Out[6]:
1
2 + ─────────────
1
1 + ─────────
1
1 + ─────
0 + 2
You can trigger evaluation with doit:
In [7]: _.doit()
Out[7]: 13/5
I have been working on some integrations and even though the system is working, it takes much more time to work than it should.
The problem is that the expressions are many pages, and even though they are 3 variables only, sy.simplify just crashes the Kernel after 4 hours or so.
Is there a way to make such lengthy expressions more compact?
EDIT:
Trying to recreate a test expression, using cse. I can't really substitute the symbols to make a final expression, equal to the 1st one
sy.var('a:c x')
testexp = sp.log(x)+a*(0.5*x)**2+(b*(0.5*x)**2+b+sp.log(x))/c
r, e = sy.cse(testexp)
FinalFunction = sy.lambdify(r[0:][0]+(a,b,c,x),e[0])
Points = sy.lambdify((a,b,c,x),r[0:][1])
FinalFunction(Points(1,1,1,1),1,1,1,1)
>>>NameError: name 'x1' is not defined
cse(expr) is sometimes a way to get a more compact representation since repeated subexpressions can be replaced with a single symbol. cse returns a list of repeated expressions and a list of expressions (a singleton if you only passed a single expression):
>>> from sympy import solve
>>> var('a:c x');solve(a*x**2+b*x+c, x)
(a, b, c, x)
[(-b + sqrt(-4*a*c + b**2))/(2*a), -(b + sqrt(-4*a*c + b**2))/(2*a)]
>>> r, e = cse(_)
>>> for i in r: pprint(Eq(*i))
...
_____________
╱ 2
x₀ = ╲╱ -4⋅a⋅c + b
1
x₁ = ───
2⋅a
>>> for i in e: pprint(i)
...
x₁⋅(-b + x₀)
-x₁⋅(b + x₀)
You are still going to have long expressions but they will be represented more compactly (and more efficiently for computatation) if cse is able to identify repeated subexpressions.
To use this in SymPy you can create two Lambdas: one to translate the variables into the replacement values and the other to use those values:
>>> v = (a,b,c,x)
>>> Pts = Lambda(v, tuple([i[1] for i in r]+list(v)))
>>> Pts(1,2,3,4)
(2*sqrt(2)*I, 1/2, 1, 2, 3, 4)
>>> Func = Lambda(tuple([i[0] for i in r]+list(v)), tuple(e))
>>> Func(*Pts(1,2,3,4))
(-1 + sqrt(2)*I, -1 - sqrt(2)*I)
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) *.
Is there an algorithm or tool to convert regular grammar to regular expression?
Answer from dalibocai:
My goal is to convert regular grammer to DFA. Finally, I found an excellent tool : JFLAP.
A tutorial is available here: https://www2.cs.duke.edu/csed/jflap/tutorial/framebody.html
The algorithm is pretty straightforward if you can compute an automaton from your regular expression. Once you have your automaton. For instance for (aa*b|c), an automaton would be (arrows go to the right):
a
/ \
a \ / b
-> 0 ---> 1 ---> 2 ->
\___________/
c
Then just "enumerate" your transitions as rules. Below, consider that 0, 1, and 2 are nonterminal symbols, and of course a, b and c are the tokens.
0: a1 | c2
1: a1 | b2
2: epsilon
or, if you don't want empty right-hand sides.
0: a1 | c
1: a1 | b
And of course, the route in the other direction provides one means to convert a regular grammar into an automaton, hence a rational expression.
From a theoretical point of view, an algorithm to solve this problem works by creating a regular expression from each rule in the grammar, and solving the resulting system of equations for the initial symbol.
For example, for regular grammar ({S,A},{a,b,c},P,S):
P:
S -> aA | cS | a | c
A -> aA | a | bS
Take each non-termimal symbol and generate regular expression from right hand:
S = aA + cS + a + c
A = aA + bS + c
Solve equation system for initial symbol S:
A = a(aA + bS + c) + bS + c
A = a⁺bS + a⁺c + bS + c
S = aA + c(aA + cS + a + c)
S = aA + c⁺aA + c⁺a + c⁺
S = a(a⁺bS + a⁺c + bS + c) + c⁺a(a⁺bS + a⁺c + bS + c) + c⁺a + c⁺
S = a⁺bS + a⁺c + c⁺a⁺bS + c⁺a⁺c + c⁺a + c⁺
S = (c⁺ + ε)a⁺bS + a⁺c + c⁺(a⁺c + a + ε)
substitution: x = (c⁺ + ε)a⁺b
S = x(xS + a⁺c + c⁺(a⁺c + a + ε)) + a⁺c + c⁺(a⁺c + a + ε)
S = x⁺a⁺c + x⁺c⁺(a⁺c + a + ε) + a⁺c + c⁺(a⁺c + a + ε)
S = x*(a⁺c + c⁺(a⁺c + a + ε))
S = ((c⁺ + ε)a⁺b)*(⁺a⁺c + c⁺(a⁺c + a + ε))
Because all modifications were equivalent, ((c⁺ + ε)a⁺b)*(⁺a⁺c + c⁺(a⁺c + a + ε)) is a regular expression equivalent to all words which can be produced from the initial symbol. Thus the value of this expression must be equivalent to the language generated by the grammar whose initial symbol is S.
It ain't pretty, but i purposefully picked a grammar including cycles to portray the way the algorithm works. The hardest part is recognizing that S = xS | x is equivalent to S = x⁺, then just doing the substitutions.
I'll leave this as an answer to this old question, in case that anybody finds it useful:
I have recently released a library for exactly that purpose:
https://github.com/rindPHI/grammar2regex
You can precisely convert regular grammars, but also compute approximate regular expressions for more general general context-free grammars. The output format can be configured to be a custom ADT type or the regular expression format of the z3 SMT solver (z3.ReRef).
Internally, the tool converts grammars to finite automata. If you're interested in the automaton itself, you can call the method right_linear_grammar_to_nfa.