Sympy: Using "assumptions" to evaluate Piecewise, specifically for IndexedBase - sympy

I am trying to evaluate a certain expression under consideration of assumption. Specifically my problem is related to indexedBase objects.
See the following code:
from sympy import *
init_printing(use_latex="mathjax")
ntot = symbols("n_tot", integer = True)
i = Idx("i",(1,ntot))
k = Idx("k", (1,ntot))
j = Idx("j",(1,ntot))
x = IndexedBase("x")
As an example let's take the derivative of two summations over x[i].
expr = Sum(Sum(x[i],(i,1,ntot)),(k,1,ntot)).diff(x[j])
(NOTE: this is not possible in the current SymPy version 1.0, it is possible with the development version and will be available in future SymPy stable versions.)
I want to evaluate the expression and get a piecewise answer:
print(expr.doit())
OUTPUT: n_tot*Piecewise((1, And(1 <= j, j <= n_tot)), (0, True))
So my problem is, how can I tell sympy that I know for certain that j is between 1 and ntot. So that my result is 1:
I tried the following but with no luck:
with assuming(j==2):
expr=Sum(Sum(x[i],(i,1,ntot)),(k,1,ntot)).diff(x[j]).doit()

Assumptions on inequalities are a sorely missed feature in SymPy.
Technically the Idx object was created to allow a symbol to contain a definition range, so as to put limits on indexed symbols. Your j already has this information:
In [28]: j.upper
Out[28]: n_tot
In [29]: j.lower
Out[29]: 1
Unfortunately, the inequality class is not meant to handle Idx objects, so its range gets disregared.
You could actually try:
In [32]: simplify(expr.doit()).args[0][0]
Out[32]: n_tot
This manually extracts the first term of the Piecewise expression.
Obviously, the current algorithm needs improvement, it should already tell to Sum that j is within the correct range in order to give 1 as a result.

Related

How to find if expression contains complex number I in it in SymPy?

Given an expression, how do I find (after simplifications if needed) if the expression contains the complex number I which is the square root of −1?
In Maple, this is done using the check has(expression,I); see its help page.
In Mathematica, this is done using the check If[FreeQ[expression, Complex], for example: How to check if expression contains a Complex expression?
But I am not sure how to do similar thing in SymPy.
Using expression.is_complex does not return True even if I in the expression. Also since real is subset of complex, this is not a correct test anyway.
I need to check for an explicit I that shows up in the expression anywhere (after simplification).
Here is an example: I am using SymPy 1.5.
from sympy import *
from sympy.abc import z
ex1=(-(((1 + 3*I) + sqrt(2))*cos(z/2)) + ((1 + I) - I*sqrt(2))*sin(z/2))/(((1 + I) + sqrt(2))*cos(z/2) + I*((-1 -I) + sqrt(2))*sin(z/2))
print(ex1.is_complex)
#None
print(simplify(ex1).is_complex)
#None
This is in Maple, for reference:
restart;
result:=(-(((1 + 3*I) + sqrt(2))*cos(z/2)) + ((1 + I) - I*sqrt(2))*sin(z/2))/(((1 + I) + sqrt(2))*cos(z/2) + I*((-1 -I) + sqrt(2))*sin(z/2));
has(simplify(result),I)
Which gives
How to do the above in SymPy?
has checks whether an expression contains some subexpression, such as I:
ex1.has(I) # True
sin(z).has(I) # False
(sin(z)+I).has(I) # True
Note that this does not take into account simplifications that might get rid of the I.
As for checks like is_complex, they consider all possible values of the input variable and return None if there is no clear answer (or if SymPy does not see a relevant simplification). Also, in your case, you want to use is_real (since real numbers are also complex in SymPy’s sense, as you noted). For illustration, consider the following:
z = Symbol("z")
(z+1).is_real # None
(z+I).is_real # None
z = Symbol("z", real=True)
(z+1).is_real # True
(z+I).is_real # False

how I can use if condition in ampl?

I am wondering can I use if operator in ampl? I have a set of variable x_{1},...,x_{n} and some constraints. now I have some constraints whose are valid under some circumstances. for example if x_{1}+...+x_{n}=kn+1 where `k is an integer then constraint A is valid.
is there any way that I can write it in ampl?
In other words the problem is that I want to search layer by layer in feasible reign. the layer is dot product between a point x=(x1,...,xn) and the vector 1=(1,1,1,...1) .
so
if < x,1>=1 then x has to satisfy the constraint A<1,
if =2 then x has to satisfy the constraint B<2,
.
.
.
this is what I found in AMPL website but it does not work! (n is dimension of x and k arbitrary integer)
subject to Time {if < x,1 > =kn+1}:
s.t. S1: A<1;
I'm not clear whether your example means "constraint A requires that x_[1]+...+x_[n]=4m+1 where m is an integer", or "if x_[1]+...+x_[n]=4m+1 where m is an integer, then constraint A requires some other condition to be met".
The former is trivial to code:
var m integer;
s.t. c1: sum{i in 1..n} x_[i] = 4m+1;
It does require a solver with MIP capability. From your tags I assume you're using CPLEX, which should be fine.
For the latter: AMPL does have some support for logical constraints, documented here. Depending on your problem, it's also sometimes possible to code logical constraints as linear integer constraints.
For example, if the x[i] variables in your example are also integers, you can set things up like so:
var m integer;
var r1 integer in 0..1;
var r2 integer in 0..2;
s.t. c1: r2 <= 2*r1; # i.e. r2 can only be non-zero if r1 = 1
s.t. c2: sum{i in 1..n} x_[i] = 4m+r1+r2;
var remainder_is_1 binary;
s.t. c3: remainder_is_1 >= r1-r2;
s.t. c4: remainder_is_1 <= 1-r2/2;
Taken together, these constraints ensure that remainder_is_1 equals 1 if and only if sum{i in 1..n} x_[i] = 4m+1 for some integer m. You can then use this variable in other constraints. This sort of trick can be handy if you only have a few logical constraints to deal with, but if you have many, it'll be more efficient to use the logical constraint options if they're available to you.

sympy args unexpected answer

I the following code
f = lambda x: 2**(x+1)
f_sym = f(sympy.symbol.symbols('x'))
print f_sym.args
The output is (2, x+1).
Why the output is not x?
I have some functions composed with functions like the previous one and the final expressions do not simplify:
f = lambda x, y: (x/y)**.5
f_sym = f(sympy.symbol.symbols('x'), sympy.symbol.symbols('y'))
symbols = f_sym.free_symbols
aux = np.asarray([sympy.derive_by_array(f_sym, symbol) for symbol in [symbols]])
uc_matrix = np.diag(sympy.symbols(','.join(['u_{%s}'%symbol for symbol in symbols])))**2
uf = ((np.dot(np.dot(aux,uc_matrix), aux.T))**.5)[0][0]
y = uf/f_sym
print (y**2).expand().simplify()
In SymPy terms, f_sym is the expression
Pow(Integer(2), Add(Symbol('x'), Integer(1)))
as you can find from srepr(f_sym). So, the function is "raising to power" and the arguments of that function are 2 and x+1.
If you want specifically the exponent, f_sym.args[1] will return that.
It's important to recognize that f_sym is not a function. It does not take any arguments and does not return anything. It's a SymPy expression. There is no special meaning of x+1 within this expression: it's just one of its parts, like the number 2 is.
To answer your follow-up question: the expression will simplify to
u_{x}**2/(4*x**2) + u_{y}**2/(4*y**2)
if you use the rational number sympy.Rational(1, 2) instead of floating-point number .5 in the exponent. Floating point numbers are poison for SymPy. Other ways to achieve the same effect, with less to type:
use sympy.sqrt function instead of raising to power 1/2.
write sympy.S(1)/2 which creates the same Rational object because 1 is turned into a SymPy object prior to division.
Reference: Python numbers vs. SymPy Numbers

Summation under a given assumption (returning piecewise function)

I am looking to evaluate the sum an infinite geometric series in SymPy, and want to use the fact that I know the sum has to converge. (Similar to this post: How to Sum with conditions on Sympy?)
My code:
import sympy as sp
from sympy import oo
from sympy.assumptions import assuming, Q
from sympy.assumptions.assume import global_assumptions
x,k = sp.symbols('x k')
#global_assumptions.add(Q.is_true(sp.Abs(x)<1))
with assuming(Q.is_true(sp.Abs(x)<1)):
y = sp.Sum(x**k,(k,0,oo)).doit()
print y
The result is:
Piecewise((1/(-x + 1), Abs(x) < 1), (Sum(x**k, (k, 0, oo)), True))
So it seems the assumption that abs(x)<1 is not taken into account.
Using the global_assumptions (commented out here) does not give the desired result.
Concretely, how do I evaluate the sum such that the result would be 1/(1-x)?
At present, the assumptions made by the assumptions module are not used by the rest of SymPy modules, which makes them less useful than one might hope.
You can sort of fake it by using .subs like this:
y = sp.Sum(x**k, (k,0,oo)).doit().subs(sp.Abs(x) < 1, True)
which returns 1/(-x + 1).
I think this is the best one can do at present. Because this is just a literal substitution of True for a condition, rather than a logical inference, it won't work when the assumption doesn't exactly match a condition in Piecewise:
y = sp.Sum(x**k, (k,0,oo)).doit().subs(sp.Abs(x) < 1/2, True) # alas :(

Solving a linear equation in one variable

What would be the most efficient algorithm to solve a linear equation in one variable given as a string input to a function? For example, for input string:
"x + 9 – 2 - 4 + x = – x + 5 – 1 + 3 – x"
The output should be 1.
I am considering using a stack and pushing each string token onto it as I encounter spaces in the string. If the input was in polish notation then it would have been easier to pop numbers off the stack to get to a result, but I am not sure what approach to take here.
It is an interview question.
Solving the linear equation is (I hope) extremely easy for you once you've worked out the coefficients a and b in the equation a * x + b = 0.
So, the difficult part of the problem is parsing the expression and "evaluating" it to find the coefficients. Your example expression is extremely simple, it uses only the operators unary -, binary -, binary +. And =, which you could handle specially.
It is not clear from the question whether the solution should also handle expressions involving binary * and /, or parentheses. I'm wondering whether the interview question is intended:
to make you write some simple code, or
to make you ask what the real scope of the problem is before you write anything.
Both are important skills :-)
It could even be that the question is intended:
to separate those with lots of experience writing parsers (who will solve it as fast as they can write/type) from those with none (who might struggle to solve it at all within a few minutes, at least without some hints).
Anyway, to allow for future more complicated requirements, there are two common approaches to parsing arithmetic expressions: recursive descent or Dijkstra's shunting-yard algorithm. You can look these up, and if you only need the simple expressions in version 1.0 then you can use a simplified form of Dijkstra's algorithm. Then once you've parsed the expression, you need to evaluate it: use values that are linear expressions in x and interpret = as an operator with lowest possible precedence that means "subtract". The result is a linear expression in x that is equal to 0.
If you don't need complicated expressions then you can evaluate that simple example pretty much directly from left-to-right once you've tokenised it[*]:
x
x + 9
// set the "we've found minus sign" bit to negate the first thing that follows
x + 7 // and clear the negative bit
x + 3
2 * x + 3
// set the "we've found the equals sign" bit to negate everything that follows
3 * x + 3
3 * x - 2
3 * x - 1
3 * x - 4
4 * x - 4
Finally, solve a * x + b = 0 as x = - b/a.
[*] example tokenisation code, in Python:
acc = None
for idx, ch in enumerate(input):
if ch in '1234567890':
if acc is None: acc = 0
acc = 10 * acc + int(ch)
continue
if acc != None:
yield acc
acc = None
if ch in '+-=x':
yield ch
elif ch == ' ':
pass
else:
raise ValueError('illegal character "%s" at %d' % (ch, idx))
Alternative example tokenisation code, also in Python, assuming there will always be spaces between tokens as in the example. This leaves token validation to the parser:
return input.split()
ok some simple psuedo code that you could use to solve this problem
function(stinrgToParse){
arrayoftokens = stringToParse.match(RegexMatching);
foreach(arrayoftokens as token)
{
//now step through the tokens and determine what they are
//and store the neccesary information.
}
//Use the above information to do the arithmetic.
//count the number of times a variable appears positive and negative
//do the arithmetic.
//add up the numbers both positive and negative.
//return the result.
}
The first thing is to parse the string, to identify the various tokens (numbers, variables and operators), so that an expression tree can be formed by giving operator proper precedences.
Regular expressions can help, but that's not the only method (grammar parsers like boost::spirit are good too, and you can even run your own: its all a "find and recourse").
The tree can then be manipulated reducing the nodes executing those operation that deals with constants and by grouping variables related operations, executing them accordingly.
This goes on recursively until you remain with a variable related node and a constant node.
At the point the solution is calculated trivially.
They are basically the same principles that leads to the production of an interpreter or a compiler.
Consider:
from operator import add, sub
def ab(expr):
a, b, op = 0, 0, add
for t in expr.split():
if t == '+': op = add
elif t == '-': op = sub
elif t == 'x': a = op(a, 1)
else : b = op(b, int(t))
return a, b
Given an expression like 1 + x - 2 - x... this converts it to a canonical form ax+b and returns a pair of coefficients (a,b).
Now, let's obtain the coefficients from both parts of the equation:
le, ri = equation.split('=')
a1, b1 = ab(le)
a2, b2 = ab(ri)
and finally solve the trivial equation a1*x + b1 = a2*x + b2:
x = (b2 - b1) / (a1 - a2)
Of course, this only solves this particular example, without operator precedence or parentheses. To support the latter you'll need a parser, presumable a recursive descent one, which would be simper to code by hand.