Python solving system of equations with square root - python

I've written a function that solves a system of equations, it does however not work when I have a square root in my solutions. The code does work for other equations as long as there are no square roots.
I am getting the following error
TypeError: No loop matching the specified signature and casting
was found for ufunc solve1
I could calculate the sqrt and get a decimal number but I don't want that. I need to do my calculations with complete numbers, I would rather have it return sqrt(5) than 2.236067977
I'm currently trying to solve the following recurrence relation
eqs :=
[
s(n) = s(n-1)+s(n-2),
s(0) = 1,
s(1) = 1
];
I've written down my outputs and steps theoratically down here. It does work for equations without square roots. How can I get linalg to work with sqrt or should I use a different approach?
def solve_homogeneous_equation(init_conditions, associated):
# Write down characteristic equation for r
Returns eq_string = r^2-1*r^(2-1)-+1*r^(2-2)
# Find the roots for r
Returns r_solutions = [1/2 + sqrt(5)/2, -sqrt(5)/2 + 1/2]
# Write down general solution (for solver)
Returns two lists, one with variables and one with outcomes
general_solution_variables = [[1, 1], [1/2 + sqrt(5)/2, -sqrt(5)/2 + 1/2]]
general_solution_outcomes = [1, 1]
# Solve the system of equations
THIS IS WHERE THE ERROR OCCURS
solution = np.linalg.solve(general_solution_variables, general_solution_outcomes)
# Write the solution
This is where I rewrite the general solution with found solutions
The raw function is defined here, in case you want to look deeper in the code
def solve_homogeneous_equation(init_conditions, associated):
print("Starting solver")
# Write down characteristic equation for r
eq_length = len(init_conditions)
associated[0] = str('r^' + str(eq_length))
for i in range(eq_length, 0, -1):
if i in associated.keys() :
associated[i] = associated[i] + str('*r^(') + str(eq_length) + str('-') + str(i) + str(')')
print("Associated equation: " + str(associated))
eq_string = ''
for i in range(0, eq_length+1, 1):
if i in associated.keys():
if i < eq_length:
eq_string = eq_string + associated[i] + '-'
else:
eq_string = eq_string + associated[i]
print("Equation: " + eq_string)
# Find the roots for r
r_symbol = sy.Symbol('r')
r_solutions = sy.solve(eq_string, r_symbol)
r_length = len(r_solutions)
print("Solutions: " + str(r_solutions))
print("Eq length: " + str(eq_length) + " ; Amount of solutions: " + str(r_length))
# If equation length is equal to solutions
if eq_length == r_length:
# Write down general solution (for solver)
general_solution_variables = []
general_solution_outcomes = []
for i in range(0, eq_length):
general_solution_variables_single = []
for j in range(0, eq_length + 1):
if j != eq_length:
k = r_solutions[j]**i
general_solution_variables_single.append(k)
if j == eq_length:
k = init_conditions[i]
general_solution_outcomes.append(int(k))
general_solution_variables.append(general_solution_variables_single)
print("General solution variables: " + str(general_solution_variables))
print("General solution outcomes: " + str(general_solution_outcomes))
# Solve the system of equations
solution = np.linalg.solve(general_solution_variables, general_solution_outcomes)
print("Solutions: " + str(solution))
# Write the solution
solution_full = ""
for i in range(0, eq_length):
if i > 0:
solution_full = solution_full + " + "
solution_full = solution_full + str(int(solution[i])) + "*" + str(int(r_solutions[i])) + "^n"
print("Solved equation: " + solution_full)
return(solution_full)
# If equation length is not equal to solutions
elif eq_length > r_length:
print("NonEqual")
return 0

I haven't tried very hard to read your code. I note that you can solve that system symbolically using sympy.
As usual with sympy terms in function definitions and equations must all be moved to one side of equals sign.
The initial conditions are passed in a dict.
>>> from sympy import *
>>> from sympy.solvers.recurr import rsolve
>>> var('n')
n
>>> s = Function('s')
>>> f = s(n) - s(n-1) -s(n-2)
>>> rsolve(f, s(n), {s(0):1, s(1):1})
(1/2 + sqrt(5)/2)**n*(sqrt(5)/10 + 1/2) + (-sqrt(5)/2 + 1/2)**n*(-sqrt(5)/10 + 1/2)

Related

Check the difference between string i and p

How would I go about checking to see what the difference between string p and i? So the 2nd line can equal the first line.
t=int(input())
print(t)
for i in range(t):
print(i)
i=input()
p=input()
print(i,p)
print('Case #'+(str(i+1))+': ')
if len(i)==0:
#print(len(p))
else:
#print((len(p)-len(i)))
Help Barbara find out how many extra letters she needs to remove in order to obtain I or if I cannot be obtained from P by removing letters then output IMPOSSIBLE.
input:
2
aaaa
aaaaa
bbbbb
bbbbc
output:
Case #1: 1
Case #2: IMPOSSIBLE
You can use Levenshtein distance to calculate the difference and decide what is possible and impossible yourself.
You can find more resources on YouTube to understand the concept better. E.g. https://www.youtube.com/watch?v=We3YDTzNXEk
I have provided a version of code for your convenient as well.
import numpy as np
def calculate_edit_distance(source, target):
'''Calculate the edit distance from source to target
[In] source="ab" target="bc"
[Out] return 2
'''
num_row = len(target) + 1
num_col = len(source) + 1
distance_table = np.array([[0] * num_col for _ in range(num_row)])
# getting from X[0...i] to empty target string requires i deletions
distance_table[:, 0] = [i for i in range(num_row)]
# getting from Y[0...i] to empty source string requires i deletions
distance_table[0] = [i for i in range(num_col)]
# loop through all the characters and calculate their respective distances
for i in range(num_row - 1):
for j in range(num_col - 1):
insert = distance_table[i + 1, j]
delete = distance_table[i, j + 1]
substitute = distance_table[i, j]
# if target char and source char are the same,
# just copy the diagonal value
if target[i] == source[j]:
distance_table[i + 1, j + 1] = substitute
else:
operations = [delete, insert, substitute]
best_operation = np.argmin(operations)
if best_operation == 2: # +2 if the operation is to substitute
distance_table[i + 1, j + 1] = substitute + 2
else: # same formula for both delete and insert operation
distance_table[i + 1, j + 1] = operations[best_operation] + 1
return distance_table[num_row - 1, num_col - 1]

Forming a polynomial from the input

I need to write a program that, when provided inputs by the user, will create a polynomial based on the position of the input order.
For example, if the user input: 1 2 3
The polynomial should be printed x^2 + (2.0)x^1 + 3 and this answer should be in float form. How do I do that?
This is what I have done so far
def get_expression(x1):
x1=""
power = len(x1) - 1
for i in range(len(x1)):
if x1[i] < 0:
x1 += str(x1[i])
else:
x1 += "+" + str(x1[i])
if x1[i] == 0:
continue
if power == 1:
x1 += "x"
elif power == 0:
x1 = x1
else:
x1 += "x" + str(power)
power = power - 1
if sum(x1)==0:
return float(0)
return x1
The code should satisfy the code below and give results correctly in the form: -4.5x - 5 & 2x^2 - 3
p1=[-4.5,-5.0]
print(get_expression(p1))
p2=[2.0,0.0,-3.0]
print(get_expression(p2))
Please help me and advise how I could correct my code and get an answer in float form.
You could build the string naively and then make it look nicer with string replacements:
def poly(*C):
result = "+".join(f" {c}x^{-p} " for p,c in enumerate(C,1-len(C)) if c)
result = result.replace("+ -","- ") # subtract for negative coefficient
result = result.replace("^1 "," ") # implicit x^1
result = result.replace("x^0","") # implicit x^0
result = result.replace(" 1x"," x").replace("-1x","-x") # implicit 1x
return result.strip()
for example: poly(-1,0,3,-1,5)
result = ' -1x^4 + 3x^2 + -1x^1 + 5x^0 ' # naive build (skips zero coeff.)
result = ' -1x^4 + 3x^2 - 1x^1 + 5x^0 ' # subtract for negative coefficient
result = ' -1x^4 + 3x^2 - 1x + 5x^0 ' # implicit x^1
result = ' -1x^4 + 3x^2 - 1x + 5 ' # implicit x^0
result = ' -x^4 + 3x^2 - x + 5 ' # implicit 1x
return '-x^4 + 3x^2 - x + 5' # strip extra space for return
output:
print(poly(1,2,3)) # x^2 + 2x + 3
print(poly(-4.5,-5)) # -4.5x - 5
print(poly(2,0,-3)) # 2x^2 - 3
print(poly(-1,0,-1.5,5,0,-32)) # -x^5 - 1.5x^3 + 5x^2 - 32
print(poly("a","b","-c")) # ax^2 + bx - c
Sort of follow your logic and re-write your code, FYI.
def get_expresultsion(x1):
result = "" # use another variable instead of x1
power = len(x1) - 1
for i in range(len(x1)):
if x1[i] < 0:
result += str(x1[i])
elif x1[i] == 0:
# put this into the same IF logic since this part is checking x1[i] as well
power = power - 1
continue
else:
result += "+" + str(x1[i])
# check power then
if power == 1:
result += "x"
elif power == 0:
pass
else:
# add "^"
result += "x^" + str(power)
power = power - 1
if sum(x1) == 0:
return float(0)
return result
At the time of viewing your question, I couldn't understand the logic you were following so I wrote it from scratch as simple as I can.
def get_expression(coefficient_list):
power = 0
expression = "" #Our final result (instead of x1)
if len(coefficient_list) == 1: #For the case having just the constant
return(coefficient_list[0])
elif len(coefficient_list) > 1:
for coefficient in reversed(coefficient_list): #We reverse the list
if power == 0: #Dealing with constant
expression += str(coefficient)
else: #Here it puts the coeff and power together and adds to the left side of expression
expression = f"({coefficient})x^{power} + " + expression
power += 1
return expression

Check result using 4 operations based with Python

I'm struggling to make a Python program that can solve riddles such as:
get 23 using [1,2,3,4] and the 4 basic operations however you'd like.
I expect the program to output something such as
# 23 reached by 4*(2*3)-1
So far I've come up with the following approach as reduce input list by 1 item by checking every possible 2-combo that can be picked and every possible result you can get to.
With [1,2,3,4] you can pick:
[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]
With x and y you can get to:
(x+y),(x-y),(y-x),(x*y),(x/y),(y/x)
Then I'd store the operation computed so far in a variable, and run the 'reducing' function again onto every result it has returned, until the arrays are just 2 items long: then I can just run the x,y -> possible outcomes function.
My problem is this "recursive" approach isn't working at all, because my function ends as soon as I return an array.
If I input [1,2,3,4] I'd get
[(1+2),3,4] -> [3,3,4]
[(3+3),4] -> [6,4]
# [10,2,-2,24,1.5,0.6666666666666666]
My code so far:
from collections import Counter
def genOutputs(x,y,op=None):
results = []
if op == None:
op = str(y)
else:
op = "("+str(op)+")"
ops = ['+','-','*','/','rev/','rev-']
z = 0
#will do every operation to x and y now.
#op stores the last computated bit (of other functions)
while z < len(ops):
if z == 4:
try:
results.append(eval(str(y) + "/" + str(x)))
#yield eval(str(y) + "/" + str(x)), op + "/" + str(x)
except:
continue
elif z == 5:
results.append(eval(str(y) + "-" + str(x)))
#yield eval(str(y) + "-" + str(x)), op + "-" + str(x)
else:
try:
results.append(eval(str(x) + ops[z] + str(y)))
#yield eval(str(x) + ops[z] + str(y)), str(x) + ops[z] + op
except:
continue
z = z+1
return results
def pickTwo(array):
#returns an array with every 2-combo
#from input array
vomit = []
a,b = 0,1
while a < (len(array)-1):
choice = [array[a],array[b]]
vomit.append((choice,list((Counter(array) - Counter(choice)).elements())))
if b < (len(array)-1):
b = b+1
else:
b = a+2
a = a+1
return vomit
def reduceArray(array):
if len(array) == 2:
print("final",array)
return genOutputs(array[0],array[1])
else:
choices = pickTwo(array)
print(choices)
for choice in choices:
opsofchoices = genOutputs(choice[0][0],choice[0][1])
for each in opsofchoices:
newarray = list([each] + choice[1])
print(newarray)
return reduceArray(newarray)
reduceArray([1,2,3,4])
The largest issues when dealing with problems like this is handling operator precedence and parenthesis placement to produce every possible number from a given set. The easiest way to do this is to handle operations on a stack corresponding to the reverse polish notation of the infix notation. Once you do this, you can draw numbers and/or operations recursively until all n numbers and n-1 operations have been exhausted, and store the result. The below code generates all possible permutations of numbers (without replacement), operators (with replacement), and parentheses placement to generate every possible value. Note that this is highly inefficient since operators such as addition / multiplication commute so a + b equals b + a, so only one is necessary. Similarly by the associative property a + (b + c) equals (a + b) + c, but the below algorithm is meant to be a simple example, and as such does not make such optimizations.
def expr_perm(values, operations="+-*/", stack=[]):
solution = []
if len(stack) > 1:
for op in operations:
new_stack = list(stack)
new_stack.append("(" + new_stack.pop() + op + new_stack.pop() + ")")
solution += expr_perm(values, operations, new_stack)
if values:
for i, val in enumerate(values):
new_values = values[:i] + values[i+1:]
solution += expr_perm(new_values, operations, stack + [str(val)])
elif len(stack) == 1:
return stack
return solution
Usage:
result = expr_perm([4,5,6])
print("\n".join(result))

How to make this breadth first search faster?

I have a search algorithm that looks for combinations of add and multiply functions to reach a certain range of number from a certain range of numbers. It is searching for the shortest program, a program being a something like AAMMA where the initial number is added, added, multiplied, multiplied, add where the ending number is in the range r to s. It has to work for every number in the starting range p to q.
The input is a and m, what you are adding and multiplying by(num+a), (num*m) for each function. What I am doing is trying every combination of functions until I find one that works, stopping that branch if it gets too big. If I find "program" that works I try the program on all of the other numbers in the starting range. It does this until either it finds no branches that don't reach the range without going over.
I know the search isn't super typical, but I don't think there is a possibility for duplicates so I didn't include a found list.
It works for smaller ranges and inputs like
Problem3("1 2 2 3 10 20")
but for larger ranges, it just takes forever my test case is
Problem3("8 13 28 91 375383947 679472915")
which I haven't even seen complete. What is my best approach from here, multithreading(hope not), making my inner functions faster somehow or just scraping this approach.
def Problem3(s):
a,m,p,q,r,s = list(map(int, s.split(" ")))
print(str(a) + "-C-" + str(m) + " processor")
print("Input guarenteed between " + str(p) + " and " + str(q))
print("Output is real number between " + str(r) + " and " + str(s))
open_set = queue.Queue()
# curr path depth
open_set.put([p, "", 0])
while not open_set.empty():
subroot = open_set.get()
multiCurr = subroot[0] * m
addCurr = subroot[0] + a
depth = subroot[2] + 1
if r <= addCurr <= s:
truePath = True
#If we find a working path, we need to check if it works for the other things
path = subroot[1] + "A"
for x in range(p, q+1):
for op in path:
if op == "A":
x += a
if op == "M":
x *= m
if r <= x <= s:
pass
else:
truePath = False
break
if truePath:
print("Found " + path + " at depth " + str(depth) + " with starting number " + str(p) + ", output " + str())
if r <= multiCurr <= s:
truePath = True
path = subroot[1] + "M"
for x in range(p, q+1):
for op in path:
if op == "A":
x += a
if op == "M":
x *= m
if r <= x <= s:
pass
else:
truePath = False
break
if truePath:
print("Found " + path + " at depth " + str(depth) + " with starting number " + str(p) + ", output " + str())
if addCurr > s and multiCurr > s:
pass
elif multiCurr > s:
open_set.put([addCurr, subroot[1] + "A", depth])
elif addCurr > s:
open_set.put([multiCurr, subroot[1] + "M", depth])
else:
open_set.put([multiCurr, subroot[1] + "M", depth])
open_set.put([addCurr, subroot[1] + "A", depth])
You don't need to test every value in the range(p, q + 1) sequence. You only need to test for p and q. If it works for the lowest and the highest number, it'll work for all the values in between, because the problem has been reduced to just multiplication and addition. You really only need to test the progress of program(q), keeping it below s, until you have created the shortest program that puts program(p) at or above r.
However, this isn't really a great problem for breath-first search; your second example would require testing 17.6 trillion possible states; the shortest solution is 44 characters long, so a breath-first search would explore 2 ** 44 states, so 17,592,186,044,416 to be exact! Even using a compiled programming language like C would take a long, long time to find the solution using such a search. Instead, you can just generate the string using a bit of math.
You can calculate the maximum number of multiplications needed here with int(math.log(s // q, m)), that's the number of times you can multiply with m when starting at q and still stay below s. You can't ever use more multiplications! With math.ceil(math.log(r / p, m)) you can find the minimum number of multiplications that would put p at or above r. To minimise the program length, pick the lower value of those two numbers.
Then, start fitting in A additions, before each M multiplication. Do so by taking i as the number of M characters that are to follow, then dividing both r and s by m ** i. These inform the number a additions to p and q that together with the subsequent multiplications bring it closest to r and s; the difference with the current p and q let you calculate the minimum number of A characters you can insert here to keep within the [r, s] range. For p, round up, for q, round down.
Repeat this procedure for every subsequent M operation, updating the p and q values with the results each time:
import math
def problem3(s):
a, m, p, q, r, s = map(int, s.split())
p_mult = math.ceil(math.log(math.ceil(r / p), m))
q_mult = int(math.log(s // q, m))
mult = min(p_mult, q_mult)
program = []
for i in range(mult, -1, -1):
p_additions = math.ceil((math.ceil(r / (m ** i)) - p) / a)
q_additions = ((s // (m ** i)) - q) // a
additions = min(p_additions, q_additions)
program += [additions * 'A']
if i:
p, q = (p + (additions * a)) * m, (q + (additions * a)) * m
program += ['M']
return ''.join(program)
This is a closed-form solution, no search needed. The result is guaranteed to be the shortest:
>>> problem3("1 2 2 3 10 20")
'AMM'
>>> problem3("8 13 28 91 375383947 679472915")
'AAAAAAMAAMAAAAAAAAAAAMAAAAAMAAAMAAAAMAAAAAAA'

Python output formatting issues

Not sure about the syntax of the output I am receving. Any help would be appreciated.
Here is my code:
import numpy
def g(): #generate random complex values
return numpy.random.random(1) + numpy.random.random(1) *1j
p = numpy.poly1d(numpy.squeeze([g(),g(),g()])) # test function p
pprime = numpy.polyder(p) #derivative of p
print 'Our p(x) is {} '. format(p)
print('\n') # new line
print'Our pprime(x) is {} '. format(pprime) #apply newtons method to p
print('\n') # new line
#apply newtons method to p
def root_newton ( f, df, tolerance = 1.0e-6):
dx = 2 * tolerance
x=0
while dx > tolerance:
x1 = x - f(x)/df(x)
dx = abs (x - x1)
x = x1
return x
print('Our first root is at {}'.format(root_newton(p,pprime)))
print('\n') # new line
Here's the output:
Our p(x) is 2
(0.6957 + 0.683j) x + (0.3198 + 0.5655j) x + (0.9578 + 0.1899j)
Our pprime(x) is
(1.391 + 1.366j) x + (0.3198 + 0.5655j)
Our first root is at (0.00925817978737+0.830966156841j)
The correct roots are [-0.64968928-1.01513333j 0.00925818+0.83096616j]
What does the 2 above the second component in my first line outputted mean? I can't find anything similar to my question online. I am guessing it may mean the x component is squared but I'm not sure? This is python 3 by the way.
The 2 is the exponent on the first x, misaligned because you put text before it on the same line.
If we take your output:
Our p(x) is 2
(0.6957 + 0.683j) x + (0.3198 + 0.5655j) x + (0.9578 + 0.1899j)
and remove the text you prepended:
2
(0.6957 + 0.683j) x + (0.3198 + 0.5655j) x + (0.9578 + 0.1899j)
the intended meaning of the 2 becomes clearer.

Categories

Resources