Recursive nesting in equation building - python

I want to code an "application" that will plot the nth reagent's concentration in time function of a chain reaction: A->B->C->D->...
The thing is, c_n(t) contains 2^n - 1 exponential functions - which are nested based on a pattern I've found:
c_1(t) = c_0_1 * exp(-k_1 * t)
c_2(t) = c_0_2 * exp(-k_2 * t) + c_0_1 * k_1 * {[exp(-k_1 * t) - exp(-k_2 * t)]/[k_2 - k_1]}
c_3(t) = c_0_3 * exp(-k_3 * t) + c_0_2 * k_2 * {[exp(-k_2 * t) - exp(-k_3 * t)]/[k_3 - k_2]} + c_0_1 * k_1 * k_2 * [1/(k_2-k_1)] * <{[exp(-k_1 * t) - exp(-k_3 * t)]/[k_3 - k_1]} - {[exp(-k_2 * t) - exp(-k_3 * t)]/[k_3 - k_2]}>
As you can see, each equation is a sum of reappearing elements. The number of nestings is dependent on the degree of relationship: 0-th degree (A to A) - simple exponential function, 1st degree (A to B, B to C, etc.) - 1 nesting, 2nd degree (A to C, B to D, etc.) - 2 nestings, etc.
Each equation can be divided into reappearing parts:
the 'independent' unit: c_0_n * exp(-k_n * t),
the basic unit: f(a,b) = (exp(- k_n[b - 1] * t) - exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1]),
the nested unit based on the basic unit,
the product of the multiplication of constants (parameters) before each nested unit.
Each nested unit of the nth equation derives from the nested units of the (n-1)th equation. The equations themselves can be obtained through iterated integration. The number of possible equations (based on the number of independent kinetic constants k) for the nth reagent is given by Bell number B(n).
Each such equation can be obtained from the equation with n independent kinetic constants for the nth reagent (all are independent of one another). One simply has to find the limes of such equation. E.g. if k_3 = k_4 and k_7 = k_2, then we are looking for lim k_4->k_3 [lim k_7->k_2 (f(t))].
The working code:
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
n = 0
import matplotlib.pyplot as plt
import numpy as np
def komendy(): # displays the list of commands
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
return
def zakres(): # number of reagents query
global n, zakres_n, c_0_n, k_n
n = int(raw_input("Define the number of n reagents: "))
zakres_n = range(1, n + 1)
c_0_n = [int(0)] * n
k_n = [int(0)] * n
return
def stez(): # initial concentrations query
while True:
y = int(raw_input("Define the value of c_0_n for n equal to (press 0 to break): "))
if y == 0:
break
x = raw_input("Define the value of c_0_" + str(y) + ": ")
if "." in x:
c_0_n[y - 1] = float(x)
else:
c_0_n[y - 1] = int(x)
return
def kin(): # kinetic constants query
while True:
q = int(raw_input("Define the value of k_n for n equal to (press 0 to break): "))
if q == 0:
break
p = raw_input("Define the value of k_" + str(q) + ": ")
if "." in p:
k_n[q - 1] = float(p)
else:
k_n[q - 1] = int(p)
return
def tabela(): # displays the table with the initial data
if n == 0:
zakres()
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
else:
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
return
def wykres(): # plots the basic unit
global f_t, t_k, t, t_d
a = int(raw_input("a = "))
b = int(raw_input("b = "))
reag = map(int, raw_input("Provide the reagents to plot (separate with spacebar): ").split(" "))
t_k = float(raw_input("Define time range from 0 to: "))
t_d = float(raw_input("Set the precision of the time axis: "))
t = np.arange(0,t_k,t_d)
p = []
def f_t(t):
return (np.exp(- k_n[b - 1] * t) - np.exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1])
f_t = f_t(t)
for i in reag:
p += plt.plot(t,i*f_t)
And the code that doesn't work [yet] (the only difference is the new wykres() function I'm trying to build):
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
n = 0
import matplotlib.pyplot as plt
import numpy as np
def komendy(): # displays the list of commands
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
return
def zakres(): # number of reagents query
global n, zakres_n, c_0_n, k_n
n = int(raw_input("Define the number of n reagents: "))
zakres_n = range(1, n + 1)
c_0_n = [int(0)] * n
k_n = [int(0)] * n
return
def stez(): # initial concentrations query
while True:
y = int(raw_input("Define the value of c_0_n for n equal to (press 0 to break): "))
if y == 0:
break
x = raw_input("Define the value of c_0_" + str(y) + ": ")
if "." in x:
c_0_n[y - 1] = float(x)
else:
c_0_n[y - 1] = int(x)
return
def kin(): # kinetic constants query
while True:
q = int(raw_input("Define the value of k_n for n equal to (press 0 to break): "))
if q == 0:
break
p = raw_input("Define the value of k_" + str(q) + ": ")
if "." in p:
k_n[q - 1] = float(p)
else:
k_n[q - 1] = int(p)
return
def tabela(): # displays the table with the initial data
if n == 0:
zakres()
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
else:
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
return
def wykres(): # plots the requested functions
global t_k, t, t_d, f, constans
reag = map(int, raw_input("Provide the reagents to plot (separate with spacebar): ").split(" "))
t_k = float(raw_input("Define the time range from 0 to: "))
t_d = float(raw_input("Define the precision of the time axis: "))
t = np.arange(0,t_k,t_d)
p = []
def f(a,b): # basic unit
return (np.exp(- k_n[b - 1] * t) - np.exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1])
def const(l,r): # products appearing before the nested parts
const = 1
constans = 1
for h in range(l,r):
const = const * k_n[h]
constans = c_0_n[l] * const
return
def czlonF(g): # nested part
czlonF = 0
for u in range(g):
czlonF = czlonF + npoch(f(a,b),g)
if g == 1:
czlonF(g) = 0
return
def npoch(f(a,b),n):
f = f(a,b)
for x in range(b+1, n+1):
f = npoch(f(a,b),x)
return
def c(j): # final result, concentration in time function
return
def czlon0(m): # 'independent' part
return (c_0_n[m - 1] * np.exp(- k_n[m - 1] * t))
for i in reag: # the actual plot command
p += plt.plot(t,c(i))
plt.show()
return
def test():
global n, zakres_n, k_n, c_0_n
n = 5
zakres_n = range(1, n + 1)
k_n = [1,2,3,4,5]
c_0_n = [2,3,4,5,6]
return
plt.show()
return
def test():
global n, zakres_n, k_n, c_0_n
n = 5
zakres_n = range(1, n + 1)
k_n = [1,2,3,4,5]
c_0_n = [2,3,4,5,6]
return
How do I fix the wykres() function so that it plots c(n)? How do I build it so that it can be plotted? I want Python to automatically build c_n(t) for whichever n I desire and plot all of them.

Related

How would this be written without using yield?

I've tried and failed multiple times trying to replace yield, but I don't seem to be successful, the goal is to have the same function, without yield.
def calcPi(limit): # Generator function
"""
Prints out the digits of PI
until it reaches the given limit
"""
q = 1
r = 0
t = 1
k = 1
n = 3
l = 3
decimal = limit
counter = 0
while counter != decimal + 1:
if 4 * q + r - t < n * t:
# yield digit
yield n
# insert period after first digit
if counter == 0:
yield '.'
# end
if decimal == counter:
print('')
break
counter += 1
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
Added the full function as people were asking for it in the comments,
Just define a list and collect the digits:
def calcPi(limit): # Generator function
"""
Collects the digits of PI
until it reaches the given limit
"""
pi = []
...
while ...:
...
# yield n
pi.append(n)
...
#break
return pi

How can I save integers displayed in the console?

I created a Python program that calculates the digits of pi and displays them in the console as the calculation is running. Eventually, it starts deleting numbers that were first displayed. How could I save the numbers as they're being displayed? Here is the code:
def calcPi(limit):
q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
decimal = limit
counter = 0
while counter != decimal + 1:
if 4 * q + r - t < n * t:
yield n
if counter == 0:
yield '.'
if decimal == counter:
print('')
break
counter += 1
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
def main():
pi_digits = calcPi(int(input(
"Enter the number of decimals to calculate to: ")))
i = 0
for d in pi_digits:
print(d, end='')
i += 1
if i == 55:
print("")
i = 0
if __name__ == '__main__':
main()
You can write to a txt file instead of printing. For example:
with open("output.txt", "a") as f:
instead of printing,
print(d, end='')
do
f.write(str(d))
and instead of printing,
print('')
do
f.write('\n')
On most UNIX operating systems you can use the tee command:
python calculate_pi.py | tee output.txt
This will let you see the output in your terminal and write it to the file at the same time.

While Loop not functioning properly

I am testing a simple linear diophantine equations code. Here is the code:
a = 3
b = 4
n = 67
i = 0
while True:
if i * a <= n:
if (n - (i * a)) % b == 0:
yy = int((n - (i * a)) / b)
print("{0} x {1} + {2} x {3} = {4}".format(a, i, b, yy, n))
i = i + 1
else:
print("No possible solution!")
break
When the code is run, it is able to find the possible x and y in this equation (which is fine). But, what I can't figure out is why is the print "No Possible solution!" is getting printed together with the answer. The else block is suppose to appear only if a solution is not possible e.g a = 3, b = 4 and n = 2.
Any advice will be appreciated.
print("No possible solution!") is inside the else case so it will execute regardless of whether any solutions were found or not.
Here is one way to fix it where a boolean variable keeps track of whether a solution was found or not and prints the message based on the state of that variable:
a = 3
b = 4
n = 2
i = 0
solution_found = False
while True:
if i * a <= n:
if (n - (i * a)) % b == 0:
yy = int((n - (i * a)) / b)
print("{0} x {1} + {2} x {3} = {4}".format(a, i, b, yy, n))
solution_found = True
i = i + 1
else:
break
if not solution_found:
print("No possible solution!")
Use flag to identify solution is available or not.
a = 3
b = 4
n = 67
i = 0
isSolutionAvailable=False
while True:
if i * a <= n:
if (n - (i * a)) % b == 0:
yy = int((n - (i * a)) / b)
print("{0} x {1} + {2} x {3} = {4}".format(a, i, b, yy, n))
isSolutionAvailable=True
i = i + 1
else:
break
if(not(isSolutionAvailable)):
print("No possible solution!")

Calculating Payment Size Using Bisection Method in Python

I've been working on this problem for MIT's edX course. The goal of the problem is to calculate the payment size for one year given the loan size and APY. My problem is that my answer keeps coming up too high. I'm not exactly sure why this is. Any help would be greatly appreciated.
Here is the code:
b = float(input("balance = "))
r = float(input("annualInterestRate = "))
t = float(input("How many months do you want to take = "))
p = (b / t)
bval = []
new = b
def interest(b, r, p, t):
bal = (b - p)
max = (b * (1 + r / 12)**(12))/12
min = (b / t)
def update(bal, r):
balance = (bal + (r / 12.0) * bal)
return balance
if len(bval) < t:
bval.append(update(bal, r))
return(interest(bval[-1], r, p, t))
if (len(bval) == t):
if bval[-1]< 10:
return print(" Minimum payment: %i" % p)
p = (max + min) / 2.0
if bval[-1] < 0:
min = bval[-1]
elif bval[-1] > 0:
max = bval[-1]
bval.clear()
bval.append(update((new - p), r))
return(interest(bval[-1], r, p, t))
interest(b, r, p, t)
There may be an issue with your order of operations in max. You might want to try adding parentheses around 1+r before dividing it by 12.

broken memoization code

I have a series of numbers I need to find the sum of. The value of the first iterative operation is 1, the second is 20. Every iteration which follows then uses the previous result in the formula n * (n + 1) / 2, so the third iteration, say i03 = 20 * (20 + 1) / 2, and the fourth, i04 = i03 * (i03 + 1) / 2. This continues until the 20th iteration of i20 = i19 * (i19 + 1) / 2. I want to do this using memoization. This is my code:
def outFun():
def sumFun(squares, total = 0, CONST = 20):
if squares > 2:
total = sumFun(squares - 1) * int((sumFun(squares - 1) + 1) / 2)
elif not squares - 2:
total = CONST
return total
return 1 + sumFun(20)
What am I doing wrong?
Here is how I understand your problem: You have a formula x_n = x_{n-1} * (x_{n-1} + 1)/2 with recursion base defined as x_1 = 20 (or x_2 = 20? Not clear from your description). The most efficient way to solve the recursion is bottom-up approach, when you start with x_1, then calculate x_2, etc. Alternative is to use dynamic programming/memorization:
mem={}
def f(x):
if x == 1: # base case
return 20
if not x in mem: # if we did not calculate it before - calculate
mem[x] = f(x-1) * (f(x-1) +1) / 2
return mem[x] # otherwise return it
print f(1)
print f(2)
print f(3)
prints
20
210
22155
f(20) is a little large to print, so I will print the number of digits in it:
print "number of digits: %s" % len(str(f(20)))
number of digits: 530115
The code took about 9 seconds to run on my desktop:
import timeit
mem={}
print "Execution time: %s" % timeit.Timer("len(str(f(20)))",
setup = "from __main__ import f").timeit(1)
you're calling
sumFun(squares - 1)
twice!
Why not introduce a variable to store the result? Something like:
if squares > 2:
nextResult = sumFun(squares - 1)
total = nextResult * ((nextResult + 1) / 2)

Categories

Resources