How to change my code to solve modular equations with division? - python

I wrote the Extended Euclidean Algorithm, but i'm having trouble with using it to solve the following equation:
which the Modular Equation Solver reduces to
and
Here is my code:
def fastlinearcongruenceSO(powx, divmodx, N, withstats=False):
x, y, z = egcditerx2SO(powx, N, withstats)
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}")
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditerx2SO(powx, N, withstats)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}")
return answer
def egcditerx2SO(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
quotient = 0
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
To solve for inverses, i used this form:
IN: fastlinearcongruenceSO(327, 1, 1009)
OUT: 108
I'm not sure how or what changes i need to make to modify it to solve with the form of division, does anyone have any ideas of what changes i need to make or if i can solve it using my existing code? I really want to modify my code to handle it solving this equation: 743360/1008x = 272 (mod 1009) and x == 116 or for someone to let me know how that equation was solved, and i can then with those steps modify my code to solve for division based modulus equations. Thanks for anyone who knows how to solve these division based equations.

Related

Implementation of binomial option pricing closed form expression

I am trying to implement this formula in python:
This is the code I think came up with:
N = 2
S0 = 10
K = 9
T = 2
r = 0.2
import math
def combos(n, i):
return math.factorial(n) / (math.factorial(n-i)*math.factorial(i))
def binom(S0, K , T, r, N, type_ = 'call'):
dt = T/N
# u = np.exp(sigma * np.sqrt(dt))
# d = np.exp(-sigma * np.sqrt(dt))
# p = ( np.exp(r*dt) - d ) / ( u - d )
u = 1.5
d = 0.5
p = 0.2
value = 0
for i in range(N+1):
node_prob = combos(N, i)*p**i*(1-p)**(N-i)
ST = S0*(u)**i*(d)**(N-i)
print(ST)
if type_ == 'call':
value += max(ST-K,0) * node_prob
elif type_ == 'put':
value += max(K-ST, 0) * node_prob
else:
raise ValueError("type_ must be 'call' or 'put'" )
return value*(1/(1+r)**T)
binom(S0, K, T, r, N)
But when I try to calculate the option price above I don't get 4.59375 but instead get 0.3750. As you can see i don't have to calculate the u,d and p as they are given. So it my code incorrect or is the example wrong?

labyrinth solver on python language

just a small labyrinth solver. try it to on python but dont even understand why it doesnt print anything. Im just started with python and trying to actually translate my teachers code from cpp just for interest.
need to reach to the destination after visiting each cell
m = [
[2,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,2,0,0],
[0,0,0,0,0,0]
]
STOP = 34
r = 0
c = 0
def init( r_: int = 0, c_: int = 0) -> None:
r = 0
c = 0
def step(r,c,level):
if level==STOP-1:
if r == 3 and c == 5:
for i in range(0,level):
print("("+init(int(r),int(c))+"," + init(int(r),int(c)) + ") - ")
print("(3,5)\n")
return True
else:
return False
m[r][c]=1
if c > 0 and m[r][c - 1] == 0:
if step(r, c - 1, level + 1):
return True
if c < 5 and m[r][c + 1] == 0:
if (step(r, c + 1, level + 1)):
return True
if r > 0 and m[r - 1][c] == 0:
if (step(r - 1, c, level + 1)):
return True
if r < 5 and m[r + 1][c] == 0:
if (step(r + 1, c, level + 1)):
return True
m[r][c] = 0
return False
def main(argc, argv):
step(0, 1, 0)
Python doesn't automatically call main like c does, nor does it require a main function. Your code can just live in the top level (e.g. print('hello world') is a valid, complete program)
Change this line:
def main(argc, argv):
to this:
if __name__ == '__main__':
got it
import matplotlib.pyplot as plt
S, F, W, X = 1, 2, 0, None
FIELD = [[X,S,W,W,W,W],
[W,W,W,W,W,W],
[W,W,W,W,W,W],
[W,W,W,W,W,F],
[W,W,W,X,W,W],
[W,W,W,W,W,W]]
ROWS = len(FIELD)
COLS = len(FIELD[0])
START_POS = [(i, line.index(S)) for i, line in enumerate(FIELD) if S in line][0]
FINISH_POS = [(i, line.index(F)) for i, line in enumerate(FIELD) if F in line][0]
STEPS = sum(line.count(W) for line in FIELD) + 1
print("Start:", START_POS, "\nFinish:", FINISH_POS, "\nTotal steps:", STEPS)
def do_step(level, path, points):
global FIELD
r, c = points[-1]
if r<0 or c<0 or r>=ROWS or c>=COLS or FIELD[r][c] == X:
return
if level == STEPS and (r, c) == FINISH_POS:
print("Found path:", path)
yy, xx = zip(*points)
plt.plot(xx, yy, "-ok")
plt.gca().invert_yaxis()
plt.show()
exit()
current = FIELD[r][c]
FIELD[r][c] = X
for dr, dc, dir in ((-1,0,'^'), (0,1,'>'), (1,0,'v'), (0,-1,'<')):
do_step(level+1, path+dir, points+[(r+dr,c+dc)])
FIELD[r][c] = current
do_step(0, "", [START_POS])
print("No path's found.")

Python pow() function returns wrong answer

I am creating a basic RSA encryption program without using an RSA library that takes a secret message, converts each character in the string to its ASCII value, encrypts with a public key and concatenates the values, and then decrypts it using a private key and returns it to a string.
All with the principle of cipher = pow(plain,e,n) and plain = pow(cipher,d,n). My issue is that when the numbers get very large as I need d and n to be 16 digits minimum, the pow() function seems to result in an error in calculation that yields an ASCII value that is out of range to convert to a character. I've been struggling to figure out where I'm going wrong for days now. Any help is appreciated. Code below:
from random import randrange, getrandbits
def is_prime(n, k=128):
# Test if n is not even.
# But care, 2 is prime !
if n == 2 or n == 3:
return True
if n <= 1 or n % 2 == 0:
return False
# find r and s
s = 0
r = n - 1
while r & 1 == 0:
s += 1
r //= 2
# do k tests
for q in range(k):
a = randrange(2, n - 1)
x = pow(a, r, n)
if x != 1 and x != n - 1:
j = 1
while j < s and x != n - 1:
x = pow(x, 2, n)
if x == 1:
return False
j += 1
if x != n - 1:
return False
return True
def generate_prime_candidate(length):
# generate random bits
p = getrandbits(length)
#p = randrange(10**7,9*(10**7))
# apply a mask to set MSB and LSB to 1
p |= (1 << length - 1) | 1
return p
def generate_prime_number(length=64):
p = 4
# keep generating while the primality test fail
while not is_prime(p, 128):
p = generate_prime_candidate(length)
return p
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def generate_keypair(p, q):
n = p * q
#Phi is the totient of n
phi = (p-1) * (q-1)
#Choose an integer e such that e and phi(n) are coprime
e = randrange(1,65537)
g = gcd(e, phi)
while g != 1:
e = randrange(1,65537)
g = gcd(e, phi)
d = multiplicative_inverse(e, phi)
return ((e, n), (d, n))
def multiplicative_inverse(e, phi):
d = 0
k = 1
while True:
d = (1+(k*phi))/e
if((round(d,5)%1) == 0):
return int(d)
else:
k+=1
def encrypt(m,public):
key, n = public
encrypted = ''
print("Your original message is: ", m)
result = [(ord(m[i])) for i in range(0,len(m))]
encryption = [pow(result[i],key,n) for i in range(0,len(result))]
for i in range(0,len(encryption)):
encrypted = encrypted + str(encryption[i])
#encrypted = pow(int(encrypted),key,n)
print("Your encrypted message is: ", encrypted)
#return result,encrypted
return encrypted, encryption
def decrypt(e,c,private):
key, n = private
print("Your encrypted message is: ", c)
print(e)
decryption = [pow(e[i],key,n) for i in range(0,len(e))]
print(decryption)
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
decrypted = ''.join(result)
print("Your decrypted message is: ",decrypted)
return result,decrypted
def fastpow(x,y,p):
res = 1
x = x%p
while(y>0):
if((y&1) == 1):
res = (res*x)%p
y = y>>1
x = (x*x)%p
return res
message = input("Enter your secret message: ")
p1 = generate_prime_number()
p2 = generate_prime_number()
public, private = generate_keypair(p1,p2)
print("Your public key is ", public)
print("Your private key is ", private)
encrypted,cipher = encrypt(message,public)
decrypt(cipher,encrypted,private)
Traceback:
File "<ipython-input-281-bce7c44b930c>", line 1, in <module>
runfile('C:/Users/Mervin/Downloads/group2.py', wdir='C:/Users/Mervin/Downloads')
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:\Users\Mervin\Anaconda3\lib\site-packages\spyder\util\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/Mervin/Downloads/group2.py", line 125, in <module>
decrypt(cipher,encrypted,private)
File "C:/Users/Mervin/Downloads/group2.py", line 100, in decrypt
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
File "C:/Users/Mervin/Downloads/group2.py", line 100, in <listcomp>
result = [chr(decryption[i])for i in range(0,len(decryption)) ]
OverflowError: Python int too large to convert to C long
Your method multiplicative_inverse is not correct. I'm not certain what you are doing in that method with the round method and floating point division, but even if you got that part correct it would be too slow anyway, requiring O(φ) steps. The usual method for computing modular multiplicative inverses is an adaptation of the extended Euclidean algorithm, which runs in O(log(φ)2) steps. Here is a straightforward mapping from the psuedocode in the Wikipedia article to python 3 code:
def multiplicative_inverse(a, n):
t, newt = 0, 1
r, newr = n, a
while newr:
quotient = r // newr
t, newt = newt, t - quotient * newt
r, newr = newr, r - quotient * newr
if r > 1:
raise ZeroDivisionError("{} is not invertible".format(a))
if t < 0:
t = t + n
return t

How to solve a congruence system in python?

for the problem Ax ≡ B (MOD C) I did this, and it was okay:
def congru(a,b,c):
for i in range(0,c):
if ((a*i - b)%c)== 0 :
print(i)
Now I have to solve a system of equations, where A = ( 5x + 7y) and A= (6x + 2y),
and B= 4 and B = 12 , respectively, and C is 26.
In other words:
( 5x + 7y)≡ 4 (mod 26)
(6x + 2y)≡ 12 (mod 26)
How do I do that?
Thanks.
For the aX ≡ b (mod m) linear congruence, here is a more powerful Python solution, based on Euler's theorem, which will work well even for very large numbers:
def linear_congruence(a, b, m):
if b == 0:
return 0
if a < 0:
a = -a
b = -b
b %= m
while a > m:
a -= m
return (m * linear_congruence(m, -b, a) + b) // a
>>> linear_congruence(80484954784936, 69992716484293, 119315717514047)
>>> 45347150615590
For the X, Y system: multiply 1st equation by 2 and the 2nd one by -7, add them together and solve for X. Then substitute X and solve for Y.
This is a very fast linear congruence solver that can solve a 4096 byte number in a second. Recursion versions meet their max depth at this length:
#included if you use withstats=True, not needed otherwise
def ltrailing(N):
return len(str(bin(N))) - len(str(bin(N)).rstrip('0'))
#included if you use withstats=True, not needed otherwise
def _testx(n, b, withstats=False):
s = ltrailing(n - 1)
t = n >> s
if b == 1 or b == n - 1:
return True
else:
for j in range(0, s):
b = pow_mod(b, 2, n, withstats)
if b == n - 1:
return True
if b == 1:
return False
if withstats == True:
print(f"{n}, {b}, {s}, {t}, {j}")
if withstats == True:
print(f"{n}, {b}, {s}, {t}")
return False
def fastlinearcongruence(powx, divmodx, N, withstats=False):
x, y, z = egcditer(powx, N, withstats)
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
if x > 1:
powx//=x
divmodx//=x
N//=x
if withstats == True:
print(f"powx = {powx}, divmodx = {divmodx}, N = {N}")
x, y, z = egcditer(powx, N, withstats)
if withstats == True:
print(f"x = {x}, y = {y}, z = {z}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
answer = (y*divmodx)%N
if withstats == True:
print(f"answer = {answer}, mrbt = {a}, mrst = {b}, mranswer = {_testx(N, answer)}")
return answer
def egcditer(a, b, withstats=False):
s = 0
r = b
old_s = 1
old_r = a
quotient = 0
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
while r!= 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
if withstats == True:
print(f"quotient = {quotient}, old_r = {old_r}, r = {r}, old_s = {old_s}, s = {s}")
if b != 0:
bezout_t = quotient = (old_r - old_s * a) // b
if withstats == True:
print(f"bezout_t = {bezout_t}")
else:
bezout_t = 0
if withstats == True:
print("Bézout coefficients:", (old_s, bezout_t))
print("greatest common divisor:", old_r)
return old_r, old_s, bezout_t
To use:
In [2703]: fastlinearcongruence(63,1,1009)
Out[2703]: 993
In [2705]: fastlinearcongruence(993,1,1009)
Out[2705]: 63
Also this is 100x faster than pow when performing this pow:
pow(1009, 2**bit_length()-1, 2**bit_length())
where the answer is 273.
This is equivalent to the much faster:
In [2713]: fastlinearcongruence(1009,1,1024)
Out[2713]: 273
Solved, here's the code for it:
def congru(a0,a1,a2,b0,b1,b2,c):
for i in range(0,c):
for j in range(0,c):
if ((a0*i + a1*j) - a2)%c ==0 and ((b0*i +b1*j)-b2)%c==0:
print('x: %d y: %d' %( i, j))
If you need a congruence system you can use this code.
from functools import reduce
class CI:
"""
cX=a (mod m)
"""
def __init__(self, c, a, m):
self.c = c%m
self.a = a%m
self.m = m
def solve(self, x):
return (x*self.c)%self.m == self.a
def find(cil):
espacio = reduce(lambda acc, ci: acc*ci.m, cil, 1)+1
for x in range(0, espacio):
if reduce(lambda acc, ci: acc and ci.solve(x), cil, True):
return x
print(find([CI(3, 2, 4), CI(4, 1, 5), CI(6, 3, 9)]))
this example will solve for x
3x=2 (mod 2)
4x=1 (mod 1)
6x=3 (mod 9)
To solve linear congruence system, You should use Chinese theorem of reminders.
I wrote full code using python and AppJar (AppJar is for grafics).
And You can download it from my github profile: github profile, full code there
There You can find all the functions I used.
It is very simple and I am sure You will understand the code, although it is written in serbian language.

Sympy seems to break down with higher numbers

I've been playing around with sympy and decided to make an arbitrary equations solver since my finance class was getting a little dreary. I wrote a basic framework and started playing with some examples, but some work and some don't for some reason.
from sympy import *
import sympy.mpmath as const
OUT_OF_BOUNDS = "Integer out of bounds."
INVALID_INTEGER = "Invalid Integer."
INVALID_FLOAT = "Invalid Float."
CANT_SOLVE_VARIABLES = "Unable to Solve for More than One Variable."
CANT_SOLVE_DONE = "Already Solved. Nothing to do."
# time value of money equation: FV = PV(1 + i)**n
# FV = future value
# PV = present value
# i = growth rate per perioid
# n = number of periods
FV, PV, i, n = symbols('FV PV i n')
time_value_money_discrete = Eq(FV, PV*(1+i)**n)
time_value_money_continuous = Eq(FV, PV*const.e**(i*n))
def get_sym_num(prompt, fail_prompt):
while(True):
try:
s = input(prompt)
if s == "":
return None
f = sympify(s)
return f
except:
print(fail_prompt)
continue
equations_supported = [['Time Value of Money (discrete)', [FV, PV, i, n], time_value_money_discrete],
['Time Value of Money (continuous)',[FV, PV, i, n], time_value_money_continuous]]
EQUATION_NAME = 0
EQUATION_PARAMS = 1
EQUATION_EXPR = 2
if __name__ == "__main__":
while(True):
print()
for i, v in enumerate(equations_supported):
print("{}: {}".format(i, v[EQUATION_NAME]))
try:
process = input("What equation do you want to solve? ")
if process == "" or process == "exit":
break
process = int(process)
except:
print(INVALID_INTEGER)
continue
if process < 0 or process >= len(equations_supported):
print(OUT_OF_BOUNDS)
continue
params = [None]*len(equations_supported[process][EQUATION_PARAMS])
for i, p in enumerate(equations_supported[process][EQUATION_PARAMS]):
params[i] = get_sym_num("What is {}? ".format(p), INVALID_FLOAT)
if params.count(None) > 1:
print(CANT_SOLVE_VARIABLES)
continue
if params.count(None) == 0:
print(CANT_SOLVE_DONE)
continue
curr_expr = equations_supported[process][EQUATION_EXPR]
for i, p in enumerate(params):
if p != None:
curr_expr = curr_expr.subs(equations_supported[process][EQUATION_PARAMS][i], params[i])
print(solve(curr_expr, equations_supported[process][EQUATION_PARAMS][params.index(None)]))
This is the code I have so far. I guess I can strip it down to a basic example if need be, but I was also wondering if there was a better way to implement this sort of system. After I have this down, I want to be able to add arbitrary equations and solve them after inputting all but one parameter.
For example, if I put in (for equation 0), FV = 1000, PV = 500, i = .02, n is empty I get 35.0027887811465 which is the correct answer. If I redo it and change FV to 4000, it returns an empty list as the answer.
Another example, when I input an FV, PV, and an n, the program seems to hang. When I input small numbers, I got RootOf() answers instead of a simple decimal.
Can anyone help me?
Side note: I'm using SymPy 0.7.6 and Python 3.5.1 which I'm pretty sure are the latest
This is a floating point accuracy issue. solve by default plugs solutions into the original equation and evaluates them (using floating point arithmetic) in order to sort out false solutions. You can disable this by setting check=False. For example, for Hugh Bothwell's code
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}), check=False)
print("{}: {}".format(fv, sols))
which gives
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: [66.6656266802551]
1873: [66.6925950919998]
1874: [66.7195491090752]
I don't have an answer, but I do have a much simpler demonstration case ;-)
import sympy as sp
FV, n = sp.symbols("FV n")
eq = sp.Eq(FV, sp.S("500 * 1.02 ** n"))
# see where it breaks
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}))
print("{}: {}".format(fv, sols))
which produces
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: []
1873: []
1874: []
At a guess this is where the accuracy breaks down enough that it can't find a verifiable solution for n?
Also, while poking at this I did a fairly extensive rewrite which you may find useful. It does pretty much the same as your code but in a much more loosely-coupled fashion.
import sympy as sp
class Equation:
def __init__(self, label, equality_str, eq="=="):
self.label = label
# parse the equality
lhs, rhs = equality_str.split(eq)
self.equality = sp.Eq(sp.sympify(lhs), sp.sympify(rhs))
# index free variables by name
self.vars = {var.name: var for var in self.equality.free_symbols}
def prompt_for_values(self):
# show variables to be entered
var_names = sorted(self.vars, key=str.lower)
print("\nFree variables are: " + ", ".join(var_names))
print("Enter a value for all but one (press Enter to skip):")
# prompt for values by name
var_values = {}
for name in var_names:
value = input("Value of {}: ".format(name)).strip()
if value:
var_values[name] = sp.sympify(value)
# convert names to Sympy variable references
return {self.vars[name]:value for name,value in var_values.items()}
def solve(self):
values = self.prompt_for_values()
solutions = sp.solve(self.equality.subs(values))
# remove complex answers
solutions = [sol.evalf() for sol in solutions if sol.is_real]
return solutions
def __str__(self):
return str(self.equality)
# Define some equations!
equations = [
Equation("Time value of money (discrete)", "FV == PV * (1 + i) ** n"),
Equation("Time value of money (continuous)", "FV == PV * exp(i * n)" )
]
# Create menu
menu_lo = 1
menu_hi = len(equations) + 1
menu_prompt = "\n".join(
[""]
+ ["{}: {}".format(i, eq.label) for i, eq in enumerate(equations, 1)]
+ ["{}: Exit".format(menu_hi)]
+ ["? "]
)
def get_int(prompt, lo=None, hi=None):
while True:
try:
value = int(input(prompt))
if (lo is None or lo <= value) and (hi is None or value <= hi):
return value
except ValueError:
pass
def main():
while True:
choice = get_int(menu_prompt, menu_lo, menu_hi)
if choice == menu_hi:
print("Goodbye!")
break
else:
solutions = equations[choice - 1].solve()
num = len(solutions)
if num == 0:
print("No solutions found")
elif num == 1:
print("1 solution found: " + str(solutions[0]))
else:
print("{} solutions found:".format(num))
for sol in solutions:
print(sol)
if __name__ == "__main__":
main()

Categories