Simplify an expression with inequalities assuming a symbol is an integer - sympy

I'm using SymPy to create a Kakuro solver but I'm having trouble enforcing that the symbols need to be integers. I've come so far that I get an inequality expression which look like this:
((1 <= x) & (x < 3/2)) | ((3/2 < x) & (x < 2))
The symbol x should equal to 1 so the expression is correct since 1 is the only possible integer.
How can I force x to be an integer?
I know there is diophantine solvers available in SymPy but these seem to only handle equations, not inequalities. I've tried creating the symbols using:
x = Symbol('x', integer=True)
but no luck.

There doesn't seem to be a built-in way, but I wrote a function to simplify a relation of the kind you mentioned, assuming we work with integers.
There are eight rewrite rules: for example, x <= number is replaced by x <= floor(number), and x < number is replaced by x <= ceiling(number) - 1, etc.
After these rules are applied, any remaining And parts of the expression are subjected to reduce_inequalities. Example:
expr = ((1 <= x) & (x < 3 / 2)) | ((3 / 2 < x) & (x < 2))
simplify_integer_relation(expr) # returns Eq(x, 1)
Caveat: the rewrite rules assume we don't get do anything like x/2 in the expression, creating an unknown fractional number. The assumption is that everything involving the unknown is an integer.
Code:
def simplify_integer_relation(expr):
rewrite_rules = {
GreaterThan: {
"lhs": lambda z: floor(z),
"rhs": lambda z: ceiling(z),
"rel": GreaterThan,
},
LessThan: {
"lhs": lambda z: ceiling(z),
"rhs": lambda z: floor(z),
"rel": LessThan,
},
StrictGreaterThan: {
"lhs": lambda z: ceiling(z) - 1,
"rhs": lambda z: floor(z) + 1,
"rel": GreaterThan,
},
StrictLessThan: {
"lhs": lambda z: floor(z) + 1,
"rhs": lambda z: ceiling(z) - 1,
"rel": LessThan,
},
}
for rel in rewrite_rules:
rule = rewrite_rules[rel]
for atom in expr.atoms(rel):
if atom.lhs.is_number:
new_atom = rule["rel"](rule["lhs"](atom.lhs), atom.rhs)
expr = expr.subs(atom, new_atom)
elif atom.rhs.is_number:
new_atom = rule["rel"](atom.lhs, rule["rhs"](atom.rhs))
expr = expr.subs(atom, new_atom)
for system in expr.atoms(And):
expr = expr.subs(system, reduce_inequalities(system.args))
return expr

Related

Why is the output 0 (=false)?

I'm exercising opreators in C++ and I don't understand the output of the code bellow
int x = 21, z = 33, y = 43;
cout << (!(z < y&& x < z) || !(x = z - y)) << endl;
I wrote it with the thought to be true and I understand it as "it's not the case z is less than y and x is less than z (which is false) or it's not the case x is equal to the difference of z and y (which is true)" so I expected output 1 (=true) and I'm confused that's not the case. Can you explain me where I'm making a mistake?
edit: Thanks for the answers, it's funny how I made such trivial mistakes I actually read about.
The part that you misinterpreted:
!(x = z - y))
x = z - y is assignment. It yields -10 as result. -10 is not 0, hence negating it yields false.
Now, first part of the expression:
!(z < y&& x < z)
!(33 < 43 && 21 < 33)
!(true && true)
!(true)
false
Putting it together:
(false || false) == false
This = is an assignment operator. It assigns values.
This == is a comparison operator. It is used to compare two values.
int value = 5, value2 = 12;
if(value == value2)
{
// do something if value and value2 are EQUAL (which they are not)
}
See this link for more information on operators in C++.

Mixing integer arithmetic with boolean - Z3 prover

Before reading this question please consider that it is intended for use with the Z3 solver tool and it's c++ api (everything is redefined so it's not normal c++ syntax)
Can someone explain how do I mix boolean logic with integers (programing wise)?
Example:
y = (x > 10 and x < 100) //y hsould be true or false (boolean)
z = (y == true and k > 20 and k < 200)
m = (z or w) //suppose w takes true of false (boolean)
I tried with the examples given in the c++ file but I can't figure out how it works when mixing integer arithmetic and boolean.
Writing answer assuming you a beginner of c++.
May be you are looking for this.
bool y,z,m,w;
int x, k;
y = (x>10 && x<100);
z = (y == true && k > 20 && k < 200);
m = (z || w);
Let see what this line means:
y = (x>10 && x<100);
here if x is greater than 10 x>10 results true. In the same way if x is less than 100 x<100 results true. if both of them are true, the right side results true, which will be assigned to y.
|| means or.

Finding roots but not asymptotes of a function

I writing a program to numerically find the roots of functions with irrational roots by various methods.
For methods such as linear interpolation, you need to find the approximate range in which a root lies, for this I wrote this code:
bool fxn1 = false;
bool fxn2 = false;
vector<float> root_list;
if(f_x(-100) < 0)
{
fxn2 = true;
}
for(float i = -99.99; i < 100.01; i += 0.01)
{
fxn1 = fxn2;
if(f_x(i) < 0)
{
fxn2 = true;
}
else
{
fxn2 = false;
}
if((fxn1 == false && fxn2 == true) || (fxn1 == true && fxn2 == false))
{
root_list.push_back(i-0.01);
root_list.push_back(i);
}
}
However, for non-continuous functions (i.e. functions with asymptotes), this code will also be triggered when the function swaps from positive to negative values either side of the asymptote.
Is there a way to get the program to tell the difference between a root and an asymptote?
Thanks in advance
If the function, f(x), is converging on a point inside [a,b] then the half-way point (a + b) / 2 should be closer to zero than a or b.
This observation leads to the following procedure:
Let mid = (a + b) / 2
If |f(mid)| < |f(a)| AND |f(mid)| < |f(b)| Then
Algorithm has converged to a root
Else
Algorithm has converged to an asymptote
End
In this pseudo code |.| denotes floating-point absolute value.
Finding numerically a root only make sense if the function has nice properties, and at least is continuous. What would you think about this one:
f: x -> f(x) defined by:
2 * i < x < 2 * i + 1 (i element of Z) : f(x) = x
2 - i + 1 < x < 2 * i (i element of Z) : f(x) = -x
x = i (i element of Z) : f(x) = 1
It is perfectly defined on R, is bounded on any bounded interval, has positive and negative values on any interval of size > 1, and is continuous on any non integer point, but it has no root.
It is simply because the rule that a root must exist on segment ]x, y[ if x < 0 < y or y < 0 < x only applies if the function is continuous on the interval.
And good luck if you want to numerically test for continuity of a function...

Graphtheory. How to approach these kinds of problems? I want to know the logic and the way one needs to think while trying to solve this.

Find the number of paths on the Cartesian plane from (0, 0) to (n, n), which never raises above the y = x line. It is possible to make three types of moves along the path:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
the right-up move, i.e. from (i, j) to (i + 1, j + 1)
Path count 101
First, we solve a simpler problem:
Find the number of paths on the Cartesian plane from (0, 0) to (n, n) with:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
and we can go to grid which x < y.
How to solve it? Too Hard? Okay, we try to find the number of paths from (0, 0) to (2, 2) first. We could draw all paths in a grid:
We define
f(x,y) => the number of paths from (0, 0) to (x, y)
You can see the path to (2, 2) from either (1, 2) or (1, 2), so we can get:
f(2, 2) = f(2, 1) + f(1, 2)
And then you will notice for point(x, y), its path from either (x, y - 1) or (x - 1, y). That's very natural, since we have only two possible moves:
move up, i.e. from (i, j) to (i, j + 1);
move to the right, i.e. from (i, j) to (i + 1, j);
I draw a larger illustration for you, and you can check our conclusion:
So we can get that:
f(x, y) = f(x, y - 1) + f(x - 1, y)
Wait... What if x = 0 or y = 0? That's quite direct:
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
The last... How about f(0, 0)? We define:
f(0, 0) = 1
since there just 1 path from (0,0) to (1,0) and (0, 1).
OK, summarise:
f(x, y) = f(x, y - 1) + f(x - 1, y)
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
f(0, 0) = 1
And by recursion, we can solve that problem.
Your problem
Now let's discuss your original problem, just modify our equations a little bit:
f(x, y) = f(x, y - 1) + f(x - 1, y) + f(x - 1, y - 1)
if x = 0 => f(x, y) = f(x, y - 1)
if y = 0 => f(x, y) = f(x - 1, y)
if x < y => f(x, y) = 0
f(0, 0) = 1
and it will result my code.
The last thing I add to my code is Memoization. In short, Memoization can eliminate the repeat calculation -- if we have calculated f(x,y) already, just store it in a dictionary and never calculate it again. You can read the wiki page for a further learning.
So, that's all of my code. If you still get some questions, you can leave a comment here, and I will reply it as soon as possible.
Code:
d = {} # Memoization
def find(x, y):
if x == 0 and y == 0:
return 1
if x < y:
return 0
if d.get((x, y)) is not None:
return d.get((x, y))
ret = 0
if x > 0:
ret += find(x - 1, y)
if y > 0:
ret += find(x, y - 1)
if x > 0 and y > 0:
ret += find(x - 1, y - 1)
d[(x, y)] = ret
return ret
print find(2, 1) # 4
For additional ideas for solving problems such as this one, there is a mathematical curiosity that is in 1-1 correspondence with not only the sequences produced by lattice walks where one's steps must remain below the line x = y, but a veritable plethora, of fantastical mathematical beasts that cut a wide swath of applicability to problem solving and research.
What are these curiosities?
Catalan Numbers:
C_n = 1/(n+1)*(2n)Choose(n), n >= 0, where if n = 0, C_0 = 1.
They also count:
The number of expressions containing $n$ pairs of parentheses
eg. n = 3: ((())), (()()), (())(), ()(()), ()()()
Number of plane trees with n + 1 vertices
Number of Triangulations of a convex (n + 2)-gon
Monomials from the product: p(x1, ..., xn) = x1(x1 + x2)(x1 + x2 + x3) ... (x1 + ... + xn)
bipartite vertices of rooted planar trees
And soooo many more things
These object appear in a lot of active research in mathematical physics, for instance, which is an active area of algorithms research due to the enormous data sets.
So you never know what seemingly far flung concepts are intimately linked in some deep dark mathematical recess.

rotating coordinate systems sympy

I'm a complete beginner with sympy, so it may be I'm overlooking something basic. I would like to rotate my coordinate system so I can build a hyperbola in standard position and then transform it to the arbitrary case. First I set up my equation:
> x, y, a, b, theta = symbols('x y a b theta')
> f = Eq(x ** 2/a ** 2 - y ** 2/b ** 2, 1)
> f1 = f.subs({a: 5, b: 10})
> f1
> x**2/25 - y**2/100 == 1
Next I want to rotate it, which I try to do by using a sub:
> f1.subs({x: x*cos(theta) - y*sin(theta), y: x*sin(theta) + y*cos(theta)})
> -(x*sin(theta) + y*cos(theta))**2/100 + (x*cos(theta) - (x*sin(theta) + y*cos(theta))*sin(theta))**2/25 == 1
But that doesn't work because apparently the substitution for x is made before the one for y, and the value of x substituted in is already updated. There must be some way to do this substitution, right?
Or is there a better tool than sympy to do this in? Once I get my hyperbolas I will want to find points of intersection between different ones.
Thanks for any suggestions.
One simple solution is to use temporary symbols :
x_temp, y_temp = symbols('x_temp y_temp')
f1.subs({x: x_temp*cos(theta) - y_temp*sin(theta), y: x_temp*sin(theta) + y_temp*cos(theta)}).subs({x_temp: x, y_temp: y})
> -(x*sin(theta) + y*cos(theta))**2/100 + (x*cos(theta) - y*sin(theta))**2/25 == 1
I think sympy can do what you want. There is a polysys modules in sympy.solvers :
"""
Solve a system of polynomial equations.
Examples
========
>>> from sympy import solve_poly_system
>>> from sympy.abc import x, y
>>> solve_poly_system([x*y - 2*y, 2*y**2 - x**2], x, y)
[(0, 0), (2, -sqrt(2)), (2, sqrt(2))]
"""
You can set simultaneous=True in the .subs( ) method to force SymPy to replace all variables at once (practically, SymPy internally creates temporary variables, proceeds with the substitution, then restores the old variables).
In [13]: f1.subs({x: x*cos(theta) - y*sin(theta),
y: x*sin(theta) + y*cos(theta)}, simultaneous=True)
Out[13]:
2 2
(x⋅sin(θ) + y⋅cos(θ)) (x⋅cos(θ) - y⋅sin(θ))
- ────────────────────── + ────────────────────── = 1
100 25
Otherwise use .xreplace( ... ) instead of .subs( ... )
In [11]: f1.xreplace({x: x*cos(theta) - y*sin(theta),
y: x*sin(theta) + y*cos(theta)})
Out[11]:
2 2
(x⋅sin(θ) + y⋅cos(θ)) (x⋅cos(θ) - y⋅sin(θ))
- ────────────────────── + ────────────────────── = 1
100 25