Solving linear equations using Z3 - python

I have the following linear equations.
m = 2 ** 31 - 1
(207560540 ∗ a + b) modulo m = 956631177
(956631177 ∗ a + b) modulo m = 2037688522
What is the most efficient way to solve these equations?
I used Z3 however it did not find any solution. My code for Z3 to solve the above equations is:
#! /usr/bin/python
from z3 import *
a = Int('a')
b = Int('b')
s = Solver()
s.add((a * 207560540 + b) % 2147483647 == 956631177)
s.add((a * 956631177 + b) % 2147483647 == 2037688522)
print s.check()
print s.model()
I know that the solution is: a = 16807, b = 78125, however, how can I make Z3 solve it?
The other method I tried is by setting a and b to BitVec() instead of Integers as shown below:
a = BitVec('a', 32)
b = BitVec('b', 32)
This gives me an incorrect solution as shown below:
[b = 3637638538, a = 4177905984]
Is there way to solve it with Z3?
Thanks.

An aside on bit-vectors: When you use bit-vectors, then all operations are done modulo 2^N where N is the bit-vector size. So, z3 isn't giving you an incorrect solution: If you do the math modulo 2^32, you'll find that the model it finds is indeed correct.
It appears your problem does indeed need unbounded integers, and it is not really linear due to modulus 2^31-1. (Linear means multiplication by a constant; modulus by a constant takes you to a different realm.) And modulus is just not easy to reason with; I don't think z3 is the right tool for this sort of problem, nor any other SMT solver. Tools like mathematica, wolfram-alpha etc. probably are better choices in this case; for instance, see: wolfram-alpha solution

Related

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 :)

sympy solve function gives wrong result

according to this graph: desmos
print(solve('x**2 + x - 1/x'))
# [-1/3 + (-1/2 - sqrt(3)*I/2)*(sqrt(69)/18 + 25/54)**(1/3) + 1/(9*(-1/2 - sqrt(3)*I/2)*(sqrt(69)/18 + 25/54)**(1/3)), -1/3 + 1/(9*(-1/2 + sqrt(3)*I/2)*(sqrt(69)/18 + 25/54)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(sqrt(69)/18 + 25/54)**(1/3), -1/3 + 1/(9*(sqrt(69)/18 + 25/54)**(1/3)) + (sqrt(69)/18 + 25/54)**(1/3)]
I was expecting [0.755, 0.57], but, I got something I cannot use in my future program. I desire to get a list of floats as result, so refer to this post, I did following, but I got some even more weird:
def solver(solved, rit=3):
res = []
for val in solved:
if isinstance(val, core.numbers.Add):
flt = val.as_two_terms()[0]
flt = round(flt, rit)
else:
flt = round(val, rit)
if not isinstance(flt, core.numbers.Add):
res.append(flt)
return res
print(solver(solve('x**2 + x - 1/x')))
# [-0.333, -0.333, -0.333]
Now I am really disappointed with sympy, I wonder if there is an accurate way to get a list of floats as result, or I will code my own gradient descent algorithm to find the roots and intersection.
sym.solve solves an equation for the independent variable. If you provide an expression, it'll assume the equation sym.Eq(expr, 0). But this only gives you the x values. You have to substitute said solutions to find the y value.
Your equation has 3 solutions. A conjugate pair of complex solutions and a real one. The latter is where your two graphs meet.
import sympy as sym
x = sym.Symbol('x')
# better to represent it like the equation it is
eq = sym.Eq(x**2, 1/x - x)
sol = sym.solve(eq)
for s in sol:
if s.is_real:
s = s.evalf()
print(s, eq.lhs.subs({x: s})) # eq.rhs works too
There are a variety of things you can do to get the solution. If you know the approximate root location and you want a numerical answer, nsolve is simplest since it has no requirements on the type of expression:
>>> from sympy import nsolve, symbols
>>> x = symbols('x')
>>> eq = x**2 + x - 1/x
>>> nsolve(eq, 1)
0.754877666246693
You can try a guess near 0.57 but it will go to the same solution. So is there really a second real roots? You can't use real_roots on this expression because it isn't in polynomial form. But if you split it into numerator and denominator you can check for the roots of the numerator:
>>> n, d = eq.as_numer_denom()
>>> from sympy import real_roots
>>> real_roots(n)
[CRootOf(x**3 + x**2 - 1, 0)]
So there is only one real root for that expression, the one that nroots gave you.
Note: the answer that solve gives is an exact solution to the cubic equation and it can't figure out definitively which ones are a solution to the equation so it returns all three. If you evaluate them you will find that only one of them is real. But since you don't need the symbolic solution, just stick to nroots.

get the program to recognize if its an integers or a real numbers (python)

thankyou for your help.
i am very new to programming, but have decided to learn Python. i am doing a program that can check if a number is a prime. this is mathematically done by checking if (x-1)^p -(x^p-1) is devisible by p (Capable of being divided, with no remainder) then p is a prime.
However i have run into trouble. this is my code so far:
from sympy import *
x=symbols('x')
p=11
f=(pow(x - 1, p)) - (pow(x, p) - 1) # (x-1)^p -(x^p-1)
f1=expand(f)
>>> -11*x**10 + 55*x**9 - 165*x**8 + 330*x**7 - 462*x**6 + 462*x**5 - 330*x**4 + 165*x**3 - 55*x**2 + 11*x
f2= f1/p
>>> -x**10 + 5*x**9 - 15*x**8 + 30*x**7 - 42*x**6 + 42*x**5 - 30*x**4 + 15*x**3 - 5*x**2 + x
to tell if the number p is a prime i need to check if the coefficients of the polynomium is divisible by p. so i have to check if the coefficients of f2 is whole numbers or real numbers.
this is what i would like to make a program that can check: https://www.youtube.com/watch?v=HvMSRWTE2mI
i have tried making it into int but it still shows fractions like 1/2 and 3/7. i wish that it will only show whole numbers.
how do i make it so?
What the method effective does is expand the polynomial and drop the first (x^p) and last coefficients (x^0). Then you have to iterate through the rest and check for divisibility. Since a polynomial expansion of power p produces p+1 terms (from 0 to p), we want to collect p-2 terms (from 1 to p-1). This is all summed up in the following code.
from sympy.abc import x
def is_prime_sympy(p):
poly = pow((x - 1), p).expand()
return not any(poly.coeff(x, i) % p for i in xrange(1, p))
This works, but the higher the number you input, e.g. 1013, the longer you'll notice it takes. Sympy is slow because internally it stores all expressions as some classes and all multiplications and additions take a long time. We can simply generate the coefficients using Pascal's triangle. For the polynomial (x - 1)^p, the coefficients are supposed to change sign, but we don't care about that. We just want the raw numbers. Credits to Copperfield for pointing out you only need half of the coefficients because of symmetry.
import math
def combination(n, r):
return math.factorial(n) // (math.factorial(r) * math.factorial(n - r))
def pascals_triangle(row):
# only generate half of the coefficients because of symmetry
return (combination(row, term) for term in xrange(1, (row+1)//2))
def is_prime_math(p):
return not any(c % p for c in pascals_triangle(p))
We can time both methods now to see which one is faster.
import time
def benchmark(p):
t0 = time.time()
is_prime_math(p)
t1 = time.time()
is_prime_sympy(p)
t2 = time.time()
print 'Math: %.3f, Sympy: %.3f' % (t1-t0, t2-t1)
And some tests.
>>> benchmark(512)
Math: 0.001, Sympy: 0.241
>>> benchmark(2003)
Math: 3.852, Sympy: 41.695
We know that 512 is not a prime. The very second term we have to check for divisibility fails the test, so most of the time is actually spent generating the coefficients. Python lazily computes them while sympy must expand the whole polynomial out before we can start collecting them. This shows as that a generator approach is preferable.
2003 is prime and here we notice sympy performs 10 times as slowly. In fact, all of the time is spent generating the coefficients, as iterating over 2000 elements for a modulo operation takes no time. So if there are any further optimisations, that's where one should focus.
numpy.poly1d()
Numpy has a class that can manipulate polynomial coefficients and it's exactly what we want. It even works relatively fast for powers up to 50k. However, in its original implementation it's useless to us. That is because the coefficients are stored as signed int32, which means very quickly they will overflow and our modulo operations will be thrown off. In fact, it'll fail for even 37.
But it's fast, though, right? Maybe if we can hack it so it accepts infite precision integers... Maybe it's possible, maybe it isn't. But even if it is, we have to consider that maybe the reason why it is so fast is exactly because it uses a fixed precision type under the hood.
For the sake of curiosity, this is what the implementation would look like if it were any useful.
import numpy as np
def is_prime_numpy(p):
poly = pow(np.poly1d([1, -1]), p)
return not any(c % p for c in poly.coeffs[1:-1])
And for the curious ones, the source code is located in ...\numpy\lib\polynomial.py.
I am not sure if I understood what you mean, but for checking if a number is an integer or float you can use isinstance:
>>> isinstance(1/2.0, float)
>>> True
>>> isinstance(1/2, float)
>>> False

Integration with sympy

I'm trying to perform the following integration using sympy;
x = Symbol('x')
expr = (x+3)**5
integrate(expr)
The answer that I'm expecting is:
But what's being returned is:
The following code works in MATLAB:
syms x
y = (x+3)^5;
int(y)
I'm unsure what I'm doing wrong in order to perform this using sympy.
This is actually a common problem seen in Calculus where for these kinds of polynomial expressions, you do get two answers. The coefficients for each of the powers of x exist but the constant factor is missing between them.
As such, there are two methods you can use to find the indefinite integral of this expression.
The first method is to perform a substitution where u = x+3, then integrate with respect to u. Then, the indefinite integral would be (1/6)*(x + 3)^6 + C as you expect.
The second method is to fully expand out the polynomial and integrate each term individually.
MATLAB elects to find the integral the first way:
>> syms x;
>> out = int((x+3)^5)
out =
(x + 3)^6/6
Something to note for later is that if we expand out this polynomial expression, we get:
>> expand(out)
ans =
x^6/6 + 3*x^5 + (45*x^4)/2 + 90*x^3 + (405*x^2)/2 + 243*x + 243/2
sympy elects to find the integral the second way:
In [20]: from sympy import *
In [21]: x = sym.Symbol('x')
In [22]: expr = (x+3)**5
In [23]: integrate(expr)
Out[23]: x**6/6 + 3*x**5 + 45*x**4/2 + 90*x**3 + 405*x**2/2 + 243*x
You'll notice that the answer is the same between both environments, but the constant factor is missing. Because the constant factor is missing, there is no neat way to factor this into the neat polynomial that you are expecting from your output seen in MATLAB.
As a final note, if you would like to reproduce what sympy generates, expand out the polynomial, then integrate. We get what sympy generates:
>> syms x;
>> out = expand((x+3)^5)
out =
x^5 + 15*x^4 + 90*x^3 + 270*x^2 + 405*x + 243
>> int(out)
ans =
x^6/6 + 3*x^5 + (45*x^4)/2 + 90*x^3 + (405*x^2)/2 + 243*x
The constant factor though shouldn't worry you. In the end, what you are mostly concerned with is a definite integral, and so the subtraction of these constant factors will happen, which won't affect the final result.
Side Note
Thanks to DSM, if you specify the manual=True flag for integrate, this will attempt to mimic performing integration by hand, which will give you the answer you're expecting:
In [26]: from sympy import *
In [27]: x = sym.Symbol('x')
In [28]: expr = (x+3)**5
In [29]: integrate(expr, manual=True)
Out[29]: (x + 3)**6/6

Python sympy - simplify nonzero factors from an equation

I am using the sympy library for python3, and I am handling equations, such as the following one:
a, b = symbols('a b', positive = True)
my_equation = Eq((2 * a + b) * (a - b) / 2, 0)
my_equations gets printed exactly as I have defined it ((2 * a + b) * (a - b) / 2 == 0, that is), and I am unable to reduce it even using simplify or similar functions.
What I am trying to achieve is simplifying the nonzero factors from the equation (2 * a + b and 1 / 2); ideally, I'd want to be able to simplify a - b as well, if I am sure that a != b.
Is there any way I can reach this goal?
The point is that simplify() is not capable (yet) of complex reasoning about assumptions. I tested it on Wolfram Mathematica's simplify, and it works. It looks like it's a missing feature in SymPy.
Anyway, I propose a function to do what you're looking for.
Define this function:
def simplify_eq_with_assumptions(eq):
assert eq.rhs == 0 # assert that right-hand side is zero
assert type(eq.lhs) == Mul # assert that left-hand side is a multipl.
newargs = [] # define a list of new multiplication factors.
for arg in eq.lhs.args:
if arg.is_positive:
continue # arg is positive, let's skip it.
newargs.append(arg)
# rebuild the equality with the new arguments:
return Eq(eq.lhs.func(*newargs), 0)
Now you can call:
In [5]: simplify_eq_with_assumptions(my_equation)
Out[5]: a - b = 0
You can easily adapt this function to your needs. Hopefully, in some future version of SymPy it will be sufficient to call simplify.

Categories

Resources