simplify a simple inequity with Sympy - python

Let's say that I know that x is bigger than y and both x and y are bigger than 0.
Can someone please help me write a function that takes two linear formulas (+/- only) and returns which one is bigger?
For example:
foo("x+y","2*x") #should return 2
foo("2*x","x+y") #should return 1
foo("x","2*y") #should return 0 (can't decide)
thanks alot!

The best way to do this in SymPy is to use the assumptions system.
First off, don't try to do tokenizing. Just use sympify if you have to input as strings, and if you don't have to, just create the expressions using symbols, like
x, y = symbols('x y')
a = x - y
b = 2*x
Please read the SymPy tutorial for more information.
The assumptions system doesn't support inequalities directly yet, so to represent x > y, you need to state that x - y is positive. To ask if 2*x > x - y, i.e., if 2*x - (x - y) is positive, given that x, y, and x - y are positive, do
In [27]: ask(Q.positive((2*x) - (x - y)), Q.positive(x) & Q.positive(y) & Q.positive(x - y))
Out[27]: True
The first argument to ask is what you are asking and the second argument is what you are assuming. & is logical and, so Q.positive(x) & Q.positive(y) & Q.positive(x - y) means to assume all three of those things.
It will return False if it knows it is false, and None if it can't determine. Note that SymPy works in a complex domain, so not positive doesn't necessarily mean negative. Hence, you should probably call ask on the negated expression as well if you get None, or call it again with negative instead of positive. If you want to include 0 (i.e., use >= instead of >, use nonnegative instead of positive and nonpositive instead of negative.
It isn't as smart as it could be yet, so you'll get a lot of Nones now when the answer could be known. In particular, I don't think it will really use the x > y fact very well at this point.

Related

Anyway to get rid of `math.floor` for positive odd integers with `sympy.simplify`?

I'm trying to simplify some expressions of positive odd integers with sympy. But sympy refuses to expand floor, making the simplification hard to proceed.
To be specific, x is a positive odd integer (actually in my particular use case, the constraint is even stricter. But sympy can only do odd and positive, which is fine). x // 2 should be always equal to (x - 1) / 2. Example code here:
from sympy import Symbol, simplify
x = Symbol('x', odd=True, positive=True)
expr = x // 2 - (x - 1) / 2
print(simplify(expr))
prints -x/2 + floor(x/2) + 1/2. Ideally it should print 0.
What I've tried so far:
Simplify (x - 1) // 2 - (x - 1) / 2. Turns out to be 0.
Multiply the whole thing by 2: 2 * (x // 2 - (x - 1) / 2). Gives me: -x + 2*floor(x/2) + 1.
Try to put more weights on the FLOOR op by customizing the measure. No luck.
Use sympy.core.evaluate(False) context when creating the expression. Nuh.
Tune other parameters like ratio, rational, and play with other function like expand, factor, collect. Doesn't work either.
EDIT: Wolfram alpha can do this.
I tried to look like the assumptions of x along with some expressions. It surprises me that (x - 1) / 2).is_integer returns None, which means unknown.
I'm running out of clues. I'm even looking for alternativese of sympy. Any ideas guys?
I fail to see why sympy can't simplify that.
But, on another hand, I've discovered the existence of odd parameter just now, with your question.
What I would have done, without the knowledge of odd is
k = Symbol('k', positive=True, integer=True)
x = 2*k-1
expr = x // 2 - (x - 1) / 2
Then, expr is 0, without even the need to simplify.
So, can't say why you way doesn't work (and why that odd parameter exists if it is not used correctly to guess that x-1 is even, and therefore (x-1)/2 integer). But, in the meantime, my way of defining an odd integer x works.
There is some reluctance to make too much automatic in SymPy, but this seems like a case that could be addressed (since (x-1)/2 is simpler than floor(x/2). Until then, however, you can run a replacement on your expression which makes this transformation for you.
Let's define a preferred version of floor:
def _floor(x):
n, d = x.as_numer_denom()
if d == 2:
if n.is_odd:
return (n - 1)/2
if n.is_even:
return n/2
return floor(x)
When you have an expression with floor that you want to evaluate, replace floor with _floor:
>>> x = Symbol('x', odd=True)
>>> eq=x // 2 - (x - 1) / 2
>>> eq.replace(floor, _floor)
0

Find numpy array in bigger array, testing for approximate equality [duplicate]

I have two numpy arrays with floating point values and I am trying to find the indices where the numbers are approximately equal (floating point comparisons).
So something like:
x = np.random.rand(3)
y = np.random.rand(3)
x[2] = y[2]
# Do the comparison and it should return 2 as the index
I tried something like
np.where(np.allclose(x, y))
However, this returns an empty array. If I do:
np.where(x == y) # This is fine.
I tried using a combination of numpy.where and numpy.allclose but could not make it work. Of course, I can do it with a loop but that seems tedious and unpythonic.
What you look for is np.isclose:
np.where(np.isclose(x, y))
You can always use something relying on:
np.where( np.abs(x-y) < epsilon )

While solving a cubic equation, how do I divide a cubic polynomial by a linear one (Python 3)?

I'm making a solver of cubic equations in Python that includes division of polynomials.
from sympy import symbols
# Coefficients
a = int(input("1st coef: "))
b = int(input("2nd coef: "))
c = int(input("3rd coef: "))
d = int(input("Const: "))
# Polynomial of x
def P(x):
return a*x**3 + b*x**2 + c*x + d
x = symbols('x')
# Find 1 root by Cardano
R = (3*a*c - b**2) / (9*a**2)
Q = (3*b**3 - 9*a*b*c + 27*a**2*d) / (54*a**3)
Delta = R**3 + Q**2
y = (-Q + sqrt(Delta))**(1/3) + (-Q - sqrt(Delta))**(1/3)
x_1 = y - b/(3*a)
# Division
P(x) / (x - x_1) = p(x)
print(p(x)) # Just a placeholder
The program returns an error: "cannot assign to operator" and highlights the P(x) after the # Division comment (worded poorly, yes, but I'm from Russia so idc).
What I tried doing was to assign a variable to a polynomial and then dividing:
z = P(x)
w = x - x_1
p = z / w
print(p)
But alas: it just returns a plain old quotient (a = 1, b = 4, c = -9, d = -36):
(x**3 + 4*x**2 - 9*x - 36)/(x - 2.94254537742264)
Does anyone out here knows what to do in this situation (not to mention the non-exact value of x_1: the roots of x^3+4x^2-9x-36=0 are 3, -4, and -3, no floaty-irrational-messy-ugly things in sight)?
tl;dr: Polynomial division confusion and non-exact roots
I am not sure what exactly your question is but here is an attempt at an answer
The line
P(x) / (x - x_1) = p(x)
is problematic for multiple reasons. First of all it's important to know that the = operator in python (and a lot of other modern programming languages) is an assignment operator. You seem to come from more of a math background, so consider it to be something like the := operator. The direction of this is always fixed, i.e. with a = b you are always assigning the value of b to the variable a. In your case you are basically assigning an expression the value of p which does not make much sense:
Python can't assign anything to an expression (At least not as far as I know)
p(x) is not yet defined
The second problem is that you are mixing python functions with math functions.
A python function looks something like this:
def some_function(some_parameter)
print("Some important Thing!: ", some_parameter)
some_return_value = 42
return some_return_value
It (can) take some variable(s) as input, do a bunch of things with them, and then (can) return something else. They are generally called with the bracket operator (). I.e. some_function(42) translates to execute some_function and substitute the first parameter with the value 42. An expression in sympy however is as far as python is concerned just an object/variable.
So basically you could have just written P = a*x**3 + b*x**2 + c*x + d. What your P(x) function is doing is basically taking the expression a*x**3 + b*x**2 + c*x + d, substituting x for whatever you have put in the brackets, and then giving it back in as a sympy expression. (It's important to understand, that the x in your P python function has nothing to do with the x you define later! Because of that, one usually tries to avoid such "false friends" in coding)
Also, a math function in sympy is really just an expression formed from sympy symbols. As far as sympy is concerned, the return value of the P function is a (mathematical) function of the symbols a,b,c,d and the symbol you put into the brackets. This is why, whenever you want to integrate or differentiate, you will need to specify by which symbol to do that.
So the line should have looked something like this.
p = P(x) / (x - x_1)
Or you leave replace the P(x) function with P = a*x**3 + b*x**2 + c*x + d and end up with
p = P / (x - x_1)
Thirdly if you would like to have the expression simplified you should take a look here (https://docs.sympy.org/latest/tutorial/simplification.html). There are multiple ways here of simplifying expressions, depending on what sort of expression you want as a result. To make for faster code sympy will only simplify your expression if you specifically ask for it.
You might however be disappointed with the results, as the line
y = (-Q + sqrt(Delta))**(1/3) + (-Q - sqrt(Delta))**(1/3)
will do an implicit conversion to floating point numbers, and you are going to end up with rounding problems. To blame is the (1/3) part which will evaluate to 0.33333333 before ever seeing sympy. One possible fix for this would be
y = (-Q + sqrt(Delta))**(sympy.Rational(1,3)) + (-Q - sqrt(Delta))**(sympy.Rational(1,3))
(You might need to add import sympy at the top)
Generally, it might be worth learning a bit more about python. It's a language that mostly tries to get out of your way with annoying technical details. This unfortunately however also means that things can get very confusing when using libraries like sympy, that heavily rely on stuff like classes and operator overloading. Learning a bit more python might give you a better idea about what's going on under the hood, and might make the distinction between python stuff and sympy specific stuff easier. Basically, you want to make sure to read and understand this (https://docs.sympy.org/latest/gotchas.html).
Let me know if you have any questions, or need some resources :)

z3: How to solve for combinations for a set of constants?

I'm not super savvy on the maths, so please do not destroy me if I've used the wrong terminology here.
What I would like to solve with z3 is something like this:
x + y = z
Assume x, and z are ints.
Where y is an array of constants such as (12,13,14,-13) which may be used, reused, or not used as the solver sees fit.
How would I translate that into z3's functionality? I suspect the answer is generating a constraint for every possible combination of those constants, but I have yet to see an example quite like what I am trying to do.
In other words how would I translate a problem like the "combination of sums" found on many programming interviews such as:
Finding all possible combinations of numbers to reach a given sum
Or
https://leetcode.com/problems/combination-sum/description/
into z3 notation?
To be very precise the piece which is unclear is how to communicate to the solver that it pay pick from an array of choices as many times as it likes.
Sure, this is rather easy for any SMT solver. Here's one way to encode it:
from z3 import *
s = Solver()
x = Int("x")
y = Int("y")
z = Int("z")
s.add(Or(y == 12, y == 13, y == 14, y == -13))
s.add(x + y == z)
while s.check() == sat:
m = s.model ()
if not m:
break
print m
s.add(Not(And([v() == m[v] for v in m])))
Note that there are infinitely many triplets that satisfy this particular set of constraints, so when you run the above it'll go on printing solutions forever!
To solve the find the subset of numbers that sum up to a number, you can proceed similarly. For each element declare a boolean. Then, write a sum expression that adds all the numbers such that the corresponding boolean is True and assert the constraint that this sum equals the required number. Fun little exercise which is again quite easy to express using Z3. Feel free to ask further questions if you give it a shot and have issues.

Euclidean Algorithm (subtraction) in python

In "Great Mathematical problems -- Vision of infinity", page 18 Ian Stewart referred Euclid's proposition 2, Book VII of Element which is a very elementary method of finding Greatest common divisor. I quote "It works by repeatedly subtracting the smaller number from the larger one, then applying a similar process to the resulting remainder and the smaller number, and continuing until there is no remainder." The example is with 630 and 135. 135 is repeadedly "subtracted"from 630 (495, 360, 225) and finally obtain 90 which is less than 135. So the numbers are inverted and 90 is repeatedly subtracted from 135 to have finally, 45. Then 45 is subtracted from 90 and finally obtain 0 yielding 45 the gcd. This is sometimes called Euclidean Algorithm of finding gcd.
To teach a beginner (a child of 10) I need to write the code in python. There should not be any function definition, neither it should use any other mathematical operation than subtraction. I want to use if/while/else/elif/continue/break. There should be provision that if three numbers (or more) are given, the whole program must be repeated deciding the smaller one.
Earlier chain on gcd does not look the algorithm from this perspective.
A typical fast solution to the gcd algorithm would be some iterative version like this one:
def gcd(x, y):
while y != 0:
(x, y) = (y, x % y)
return x
In fact, in python you'd just use directly the gcd function provided by fractions module.
And if you wanted such function to deal with multiple values you'd just use reduce:
reduce(gcd,your_array)
Now, it seems you want to constrain yourself to use only loops+substractions so one possible solution to deal with x,y positive integers would be this:
def gcd_unopt(x, y):
print x,y
while x!=y:
while x>y:
x -= y
print x,y
while y>x:
y -= x
print x,y
return x
print reduce(gcd_unopt,[630,135])
Not sure why you wanted to avoid using functions, gcd is a function by definition, even so, that's simple, just get rid of the function declaration and use the parameters as global variables, for instance:
x = 630
y = 135
print x,y
while x!=y:
while x>y:
x -= y
print x,y
while y>x:
y -= x
print x,y

Categories

Resources