I want to write the first part of the Smith-Waterman algorithm in python with basic functions.
I found this example, but it doesn't give me what I'm looking for.
def zeros(X: int, Y: int):
# ^ ^ incorrect type annotations. should be str
lenX = len(X) + 1
lenY = len(Y) + 1
matrix = []
for i in range(lenX):
matrix.append([0] * lenY)
# A more "pythonic" way of expressing the above would be:
# matrix = [[0] * len(Y) + 1 for _ in range(len(x) + 1)]
def score(X, Y):
# ^ ^ shadowing variables from outer scope. this is not a bug per se but it's considered bad practice
if X[n] == Y[m]: return 4
# ^ ^ variables not defined in scope
if X[n] == '-' or Y[m] == '-': return -4
# ^ ^ variables not defined in scope
else: return -2
def SmithWaterman(X, Y, score): # this function is never called
# ^ unnecessary function passed as parameter. function is defined in scope
for n in range(1, len(X) + 1):
for m in range(1, len(Y) + 1):
align = matrix[n-1, m-1] + (score(X[n-1], Y[m-1]))
# ^ invalid list lookup. should be: matrix[n-1][m-1]
indelX = matrix[n-1, m] + (score(X[n-1], Y[m]))
# ^ out of bounds error when m == len(Y)
indelY = matrix[n, m-1] + (score(X[n], Y[m-1]))
# ^ out of bounds error when n == len(X)
matrix[n, m] = max(align, indelX, indelY, 0)
# this should be nested in the inner for-loop. m, n, indelX, and indelY are not defined in scope here
print(matrix)
zeros("ACGT", "ACGT")
On a book I found this algorithm, but I couldn't implement it correctly.
input: sequences s and t, with |s| =n, |t| = m, score function, penality InDel
match +1, mismatch -2, InDel -1
M = matrix of size n+1 * m+1
M[i,j] = 0
i=j=0
Any help please
Thanks
The problems with the code you presented are well described in the comments in that piece of code.
Assuming that you want a linear gap-penalty of 2 points, and you are looking for the first phase algorithm only (so excluding the trace-back process), the code can be fixed as follows:
def score(x, y):
return 4 if x == y else (
-4 if '-' in (x, y) else -2
)
def zeros(a, b):
penalty = 2 # linear penalty (see Wikipedia)
nextrow = [0] * (len(b) + 1)
matrix = [nextrow]
for valA in a:
row, nextrow = nextrow, [0]
for m, valB in enumerate(b):
nextrow.append(max(
row[m] + score(valA, valB),
row[m+1] - penalty,
nextrow[m] - penalty,
0
))
matrix.append(nextrow)
return matrix
# Example run:
result = zeros("ACGT", "AC-GT")
print(result)
the image algorithm implementation:
M = []
for i in range(n):
M.append([])
for j in range(m):
first = max(M[i - 1][j - 1] + score(s[i], t[j])
second = M[i - 1][j] + penal
third = M[i][j - 1] + penal
M[i].append(first, second, third, 0))
But you will have to fix the edge cases (out of range) and add some default values.
Related
I'm a newbie in algorithms. I have recently started studying binary search and tryed to implement it on my own. The task is simple: we have an array of integers a and an integer x. If a contains x the result should be its index, otherwise the function should return -1.
Here is the code I have written:
def binary_search(a, x):
l = 0
r = len(a)
while r - l > 0:
m = (l + r) // 2
if a[m] < x:
l = m
else:
r = m
if a[l] == x:
return l
return -1
But this code stucks in infinite cycle on a = [1, 2] and x = 2. I suppose, that I have incorrect cycle condition (probably, should be r - l >= 0), but this solution does not help. Where am I wrong?
Let me do some desk checking. I'll assume a = [1, 2] and we are searching for a 2
So we start with
l = 0
r = 2
Since r - l = 2 > 0, we enter the while-loop.
m = (l + r) / 2 = (0 + 2) / 2 = 1
a[m] = a[1] = 2 == x (hence not less than x)
r = m = 1 (and l remains the same)
Now r - l = 1 - 0 = 1 > 0, so we continue
m = (l + r) / 2 = (0 + 1) / 2 = 0
a[m] = a[0] = 1 < x
l = m = 0 (and r remains the same)
After this iteration both r and l have the same value as before, which then produces an endless loop.
Ashok's answer is a great fix. But I think it'll be educational to do some desk checking on the fixed code and look what improves it.
Basically the problematic situation arises, when l + 1 = r.
Then m will always evaluate to l, a[l] < x and l is set to m again, which doesn't change the situation.
In a larger piece of code it'll make sense to make a table that contains a column for each variable to watch and a column to write down the code line that was evaluated. A column for remarks won't harm either.
As Mani mentioned you are not considering when A[m]==x. Include that case (at that point you've found a so just return m), and once you have that case we can let l=m+1 when we are still below x. Like this:
def binary_search(a, x):
l = 0
r = len(a)
while r - l > 0:
m = (l + r) // 2
if a[m] < x:
l = m + 1
elif a[m]==x:
return m
else:
r = m
if l<len(a) and a[l] == x:
return l
return -1
Given an arbitrary range of 1 to F and a starting point S with an ending point G such that the only directions we could go is L Left steps and R Right Steps (also arbitrary), create a general solution that will return the number of steps it would take to go from S to R if it is possible otherwise return not possible.
You are bound to the range [1, F] which means that you cannot move L or R steps if the next move will be more than F or less than 1
Example:
F = 100
S = 2
G = 1
L = 0
R = 1
Output: not possible
F = 10
S = 1
G = 10
L = 1
R = 2
Output: 6
Explanation: [1 -> 3(R) -> 5(R) -> 7(R) -> 9(R) -> 8(L) -> 10(R)]
I've been given this problem in our class and our current topic is binary search and divide and conquer. Here's my approach but this does not solve one hidden case.
F = int(input())
S = int(input())
G = int(input())
L = int(input())
R = int(input())
count = 0
while S != G:
dist = abs(S - G) # Takes the current distance from S to G
if S > G:
if S-L > 0:
S -= L
count += 1
else:
S += R
count += 1
else:
if S+R <= F:
S += R
count += 1
else:
S -= L
count += 1
if dist == abs(S - G): # If distance doesn't change after trying
print("not possible") # a move, conclude that it is not possible.
break
if S == G: print(count)
Mathematically this problem means that we are looking for
integer solutions (for x and y) of the following equation:
x * R - y * L = G - S
we can start by creating a function to check if there is a solution quickly:
def path(S, G, F, L, R):
x=0
while True:
y = (x * R - G + S) / L
if y>=0 and int(y)==y:
return(x,y)
else:
x+=1
This will work if there are solutions, but not if they are not.
It can be proved mathematically that there is no solution when L devides R but not G-S. Here is the proof:
If
R mod L =0 (L devides R)
(G - S)/L != 0 (L doesn't devide G-S)
then by deviding the whole equation (x * R - y * L = G - S) by L we take:
x * R/L - y = (G - S)/L <=>
y= (x * R/L) - (G - S)/L
Now, we want y mod 1 = 0 (means that y is integer) for x mod 1 =0 (x integers). Using common modulo operations we take:
y mod 1 = [(x * R/L) - (G - S)/L] mod 1 =
[(x * R/L) mod 1 - ((G - S)/L) mod 1] mod 1 =
[(x mod 1 * (R/L) mod 1) mod 1 - ((G - S)/L) mod 1] mod 1 =
[(x mod 1 * 0) mod 1 - ((G - S)/L) mod 1] mod 1 =
[((G - S)/L) mod 1] mod 1
This cannot be 0 if L doesn't devide G-S which eventally means that there are no pair of integers x,y that can satisfy the original condition.
Programatically this means for our code, the following additions:
def path(S, G, F, L, R):
if R%L==0 and (G-S)%L != 0 :
return 'No solutions'
x=0
while True:
y = (x * R - G + S) / L
if y>=0 and int(y)==y:
return(x,y)
else:
x+=1
I don;t know if mathematically we can prove that the above if is the only exception, it can probably be proved with some more modulo operations. Programatically we can add some clock in our code so that if there are no solutions, which means that it will go to infitive loop, we can return False after some time. Here is how we can do this:
How would I stop a while loop after n amount of time?
If the distance didn't change that doesn't mean it's impossible, you could have just jumped over the point and made it to the other side with the same distance, imagine L=2, R=1, S=3, G=2, you start distance 1 from goal, jump left (still distance 1) then jump right and win. What you need to check is whether you have gone in a loop and ended up at a location you have already tried before. You can either keep track of these locations (say in a set) or do some math ahead of time and figure out how many Ls and Rs it takes before you have definitely looped (probably not intended to figure this out).
F=int(input())
S=int(input())
G=int(input())
L=int(input())
R=int(input())
L*=-1
Fl=1-L
Fr=F-R
h0=set()
n=0
while True:
if S<G:
S+= R if S<=Fr else L
elif G<S:
S+= L if Fl<=S else R
else:
print(n)
break
if S in h0:
print('not possible')
break
h0.add(S)
n+=1
I am attempting to create a program to solve a specific system of equations using brute force with python. I solved for one equation and substituted it into the second equation. Variables a through f are given by user input, and I am trying to output values for x and y within a range of -10 to 10 if they exist. Any help is greatly appreciated, Thank You!
My problem is that for each check within the range the output is no solution, whereas I would like it to output no solution only if none of the numbers within the range satisfy the equation. Updated the code to fix the int object not callable error.
To be clear, the code is mostly working and gives the correct answer, but the answer is nested in roughly 100 'no solution' statements
''' Read in first equation, ax + by = c '''
a = int(input())
b = int(input())
c = int(input())
''' Read in second equation, dx + ey = f '''
d = int(input())
e = int(input())
f = int(input())
for x in range(-10, 10, 1):
for y in range(-10, 10, 1):
if a * x + b * y == c and d * x + e * y == f:
print(x, y)
else:
print('No solution')
# a * x + b * y = c
# d * x + e * y = f
To fix the issue of the else statement printing for each iteration of the if statement I created a check and set it to false. I set a condition that set the variable to true if any of the numbers within the range satisfied the condition. Then set an if statement to print 'No solution' if the variable was still false. Thanks to everyone for the help with syntax, but I'm glad I had the opportunity to figure this out on my own.
Here's the updated working code:
''' Read in first equation, ax + by = c '''
a = int(input())
b = int(input())
c = int(input())
''' Read in second equation, dx + ey = f '''
d = int(input())
e = int(input())
f = int(input())
check = False
for x in range(-10, 10, 1):
for y in range(-10, 10, 1):
if a * x + b * y == c and d * x + e * y == f:
check = True
print(x,y)
if check == False:
print('No solution')
# a * x + b * y = c
# d * x + e * y = f
if d * x + b((c - a * x)/b) == f:
Parentheses after a variable is an operator that tries to call the variable as a function. So this line above is trying to call b() as a function. You need to explicitly add the multiply operator instead:
if d * x + b*((c - a * x)/b) == f:
So, there is a lot going on here that can be improved upon.
But with some basic assumptions on best practices I've re-written your code so that it is easy for anyone to understand.
The main things I'd recommend getting use to:
Setting up a "main" in your python code
building functions instead of relying on a procedural design
commenting the goal of your functions, along with something about the input and output
There are plenty of discussion online as to why, but to sum them up it makes it A) more clear what your intentions are and B) provides an easier baseline for troubleshooting your code.
There are still more things that could be discussed about improving the clarity of intention and design but I'll cut myself short at fear of rambling on.
def brute_force_two_equations(first_values, second_values,
max_range=10, min_range=-10):
'''
Brute force way of finding solution in
system of equations
Params:
first_values: a list of three values [a const, a const, and the result]
second_values: a list of three values [a const, a const, and the result]
max_range: the maximum range to test with, default 10
min_range: the minimum range to test with, default -10
'''
for x in range(min_range, max_range + 1):
for y in range(min_range, max_range + 1):
first_result = equation(first_values[0], first_values[1], x, y)
second_result = equation(second_values[0], second_values[1], x, y)
if first_result == first_values[2] and second_result == second_values[2]:
return (x, y)
def equation(const1, const2, x, y):
'''
A simple equation: a * x + b * y = c
Params:
const1: the first constant value, `a` in the above example
const2: the second constant value, `b` in the above example
x: the first variable value
y: the second variable value
'''
return const1 * x + const2 * y
def get_three_integers():
'''
Requests and provides three integers from the user
'''
inputs = []
for i in range(0, 3):
inputs.append(int(input("Please enter a value: ")))
return inputs
if __name__ == "__main__":
print("== First Equation ==")
first_equation_values = get_three_integers()
print("== Second Equation ==")
second_equation_values = get_three_integers()
solution = brute_force_two_equations(first_equation_values,
second_equation_values)
if solution:
print(f"(x, y) {solution}")
else:
print("No Solution found")
You're saying "No solution" without complely looping through all the choices.
Code should be
for x in range(-10, 10, 1):
for y in range(-10, 10, 1):
if a * x + b * y == c and d * x + e * y == f:
print(x, y)
else:
print('No solution')
This is the way I did it and it works:
(I borrowed the check = False idea)
''' Read in first equation, ax + by = c '''
a = int(input())
b = int(input())
c = int(input())
''' Read in second equation, dx + ey = f '''
d = int(input())
e = int(input())
f = int(input())
check = False
for x in range(-10, 11):
for y in range(-10, 11):
if (a * x) + (b * y) != c:
y += 1
continue
if (a * x) + (b * y) == c and (d * x) + (e * y) != f:
y += 1
continue
if (a * x) + (b * y) == c and (d * x) + (e * y) == f:
check = True
print("x = {} , y = {}".format(x,y))
else:
x += 1
continue
if check == False:
print("There is no solution")
I have a model for four possibilities of purchasing a pair items (purchasing both, none or just one) and need to optimize the (pseudo-) log-likelihood function. Part of this, of course, is the calculation/definition of the pseudo-log-likelihood function.
The following is my code, where Beta is a 2-d vector for each customer (there are U customers and U different beta vectors), X is a 2-d vector for each item (different for each of the N items) and Gamma is a symmetric matrix with a scalar value gamma(i,j) for each pair of items. And df is a dataframe of the purchases - one row for each customer and N columns for the items.
It would seem to me that all of these loops are inefficient and take up too much time, but I am not sure how to speed up this calculation and would appreciate any help improving it.
Thank you in advance!
def pseudo_likelihood(Args):
Beta = np.reshape(Args[0:2*U], (U, 2))
Gamma = np.reshape(Args[2*U:], (N,N))
L = 0
for u in range(0,U,1):
print datetime.datetime.today(), " for user {}".format(u)
y = df.loc[u][1:]
beta_u = Beta[u,:]
for l in range(N):
print datetime.datetime.today(), " for item {}".format(l)
for i in range(N-1):
if i == l:
continue
for j in range(i+1,N):
if (y[i] == y[j]):
if (y[i] == 1):
L += np.dot(beta_u,(x_vals.iloc[i,1:]+x_vals.iloc[j,1:])) + Gamma[i,j] #Log of the exponent of this expression
else:
L += np.log(
1 - np.exp(np.dot(beta_u, (x_vals.iloc[i, 1:] + x_vals.iloc[j, 1:])) + Gamma[i, j])
- np.exp(np.dot(beta_u, x_vals.iloc[i, 1:])) * (
1 - np.exp(np.dot(beta_u, x_vals.iloc[j, 1:])))
- np.exp(np.dot(beta_u, x_vals.iloc[j, 1:])) * (
1 - np.exp(np.dot(beta_u, x_vals.iloc[i, 1:]))))
else:
if (y[i] == 1):
L += np.dot(beta_u,x_vals.iloc[i,1:]) + np.log(1 - np.exp(np.dot(beta_u,x_vals.iloc[j,1:])))
else:
L += (np.dot(beta_u, x_vals.iloc[j,1:])) + np.log(1 - np.exp(np.dot(beta_u, x_vals.iloc[i,1:])))
L -= (N-2)*np.dot(beta_u,x_vals.iloc[l,1:])
for k in range(N):
if k != l:
L -= np.dot(beta_u, x_vals.iloc[k,1:])
return -L
To add/clarify - I am using this calculation to optimize and find the beta and gamma parameters that generated the data for this pseudo-likelihood function.
I am using scipy optimize.minimize with the 'Powell' method.
Updating for whomever is interested-
I found numpy.einsum to speed up the calculations here by over 90%.
np.einsum performs matrix/vector operations using Einstein notation. Recall that for two matrices A, B their product can be represented as the sum of
a_ij*b_jk
i.e. the ik element of the matrix AB is the sum over j of a_ij*b_jk
Using the einsum function I could calculate in advance all of the values necessary for the iterative calculation, saving precious time and hundreds, if not thousands, of unnecessary calculations.
I rewrote the code as follows:
def pseudo_likelihood(Args):
Beta = np.reshape(Args[0:2*U], (U,2))
Gamma = np.reshape(Args[2*U:], (N,N))
exp_gamma = np.exp(Gamma)
L = 0
for u in xrange(U):
y = df.loc[u][1:]
beta_u = Beta[u,:]
beta_dot_x = np.einsum('ij,j',x_vals[['V1','V2']],beta_u)
exp_beta_dot_x = np.exp(beta_dot_x)
log_one_minus_exp = np.log(1 - exp_beta_dot_x)
for l in xrange(N):
for i in xrange(N-1):
if i == l:
continue
for j in xrange(i+1,N):
if (y[i] == y[j]):
if (y[i] == 1):
L += beta_dot_x[i] + beta_dot_x[j] + Gamma[i,j] #Log of the exponent of this expression
else:
L += math.log(
1 - exp_beta_dot_x[i]*exp_beta_dot_x[j]*exp_gamma[i,j]
- exp_beta_dot_x[i] * (1 - exp_beta_dot_x[j])
- exp_beta_dot_x[j] * (1 - exp_beta_dot_x[i]))
else:
if (y[i] == 1):
L += beta_dot_x[i] + log_one_minus_exp[j]
else:
L += (beta_dot_x[j]) + log_one_minus_exp[i]
L -= (N-2)*beta_dot_x[l]
for k in xrange(N):
if k != l:
L -= sum(beta_dot_x) + beta_dot_x[l]
return -L
For a numerical methods class, I need to write a program to evaluate a definite integral with Simpson's composite rule. I already got this far (see below), but my answer is not correct. I am testing the program with f(x)=x, integrated over 0 to 1, for which the outcome should be 0.5. I get 0.78746... etc.
I know there is a Simpson's rule available in Scipy, but I really need to write it myself.
I suspect there is something wrong with the two loops. I tried "for i in range(1, n, 2)" and "for i in range(2, n-1, 2)" before, and this gave me a result of 0.41668333... etc.
I also tried "x += h" and I tried "x += i*h". The first gave me 0.3954, and the second option 7.9218.
# Write a program to evaluate a definite integral using Simpson's rule with
# n subdivisions
from math import *
from pylab import *
def simpson(f, a, b, n):
h=(b-a)/n
k=0.0
x=a
for i in range(1,n/2):
x += 2*h
k += 4*f(x)
for i in range(2,(n/2)-1):
x += 2*h
k += 2*f(x)
return (h/3)*(f(a)+f(b)+k)
def function(x): return x
print simpson(function, 0.0, 1.0, 100)
You probably forget to initialize x before the second loop, also, starting conditions and number of iterations are off. Here is the correct way:
def simpson(f, a, b, n):
h=(b-a)/n
k=0.0
x=a + h
for i in range(1,n/2 + 1):
k += 4*f(x)
x += 2*h
x = a + 2*h
for i in range(1,n/2):
k += 2*f(x)
x += 2*h
return (h/3)*(f(a)+f(b)+k)
Your mistakes are connected with the notion of a loop invariant. Not to get into details too much, it's generally easier to understand and debug cycles which advance at the end of a cycle, not at the beginning, here I moved the x += 2 * h line to the end, which made it easy to verify where the summation starts. In your implementation it would be necessary to assign a weird x = a - h for the first loop only to add 2 * h to it as the first line in the loop.
All you need to do to make this code work is add a variable for a and b in the function bounds() and add a function in f(x) that uses the variable x. You could also implement the function and bounds directly into the simpsonsRule function if desired... Also, these are functions to be implimented into a program, not a program itself.
def simpsonsRule(n):
"""
simpsonsRule: (int) -> float
Parameters:
n: integer representing the number of segments being used to
approximate the integral
Pre conditions:
Function bounds() declared that returns lower and upper bounds of integral.
Function f(x) declared that returns the evaluated equation at point x.
Parameters passed.
Post conditions:
Returns float equal to the approximate integral of f(x) from a to b
using Simpson's rule.
Description:
Returns the approximation of an integral. Works as of python 3.3.2
REQUIRES NO MODULES to be imported, especially not non standard ones.
-Code by TechnicalFox
"""
a,b = bounds()
sum = float()
sum += f(a) #evaluating first point
sum += f(b) #evaluating last point
width=(b-a)/(2*n) #width of segments
oddSum = float()
evenSum = float()
for i in range(1,n): #evaluating all odd values of n (not first and last)
oddSum += f(2*width*i+a)
sum += oddSum * 2
for i in range(1,n+1): #evaluating all even values of n (not first and last)
evenSum += f(width*(-1+2*i)+a)
sum += evenSum * 4
return sum * width/3
def bounds():
"""
Description:
Function that returns both the upper and lower bounds of an integral.
"""
a = #>>>INTEGER REPRESENTING LOWER BOUND OF INTEGRAL<<<
b = #>>>INTEGER REPRESENTING UPPER BOUND OF INTEGRAL<<<
return a,b
def f(x):
"""
Description:
Function that takes an x value and returns the equation being evaluated,
with said x value.
"""
return #>>>EQUATION USING VARIABLE X<<<
You can use this program for calculating definite integrals by using Simpson's 1/3 rule. You can increase your accuracy by increasing the value of the variable panels.
import numpy as np
def integration(integrand,lower,upper,*args):
panels = 100000
limits = [lower, upper]
h = ( limits[1] - limits[0] ) / (2 * panels)
n = (2 * panels) + 1
x = np.linspace(limits[0],limits[1],n)
y = integrand(x,*args)
#Simpson 1/3
I = 0
start = -2
for looper in range(0,panels):
start += 2
counter = 0
for looper in range(start, start+3):
counter += 1
if (counter ==1 or counter == 3):
I += ((h/3) * y[looper])
else:
I += ((h/3) * 4 * y[looper])
return I
For example:
def f(x,a,b):
return a * np.log(x/b)
I = integration(f,3,4,2,5)
print(I)
will integrate 2ln(x/5) within the interval 3 and 4
There is my code (i think that is the most easy method). I done this in jupyter notebook.
The easiest and most accurate code for Simpson method is 1/3.
Explanation
For standard method (a=0, h=4, b=12) and f=100-(x^2)/2
We got:
n= 3.0, y0 = 100.0, y1 = 92.0, y2 = 68.0, y3 = 28.0,
So simpson method = h/3*(y0+4*y1+2*y2+y3) = 842,7 (this is not true).
Using 1/3 rule we got:
h = h/2= 4/2= 2 and then:
n= 3.0, y0 = 100.0, y1 = 98.0, y2 = 92.0, y3 = 82.0, y4 = 68.0, y5 = 50.0, y6 = 28.0,
Now we calculate the integral for each step (n=3 = 3 steps):
Integral of the first step: h/3*(y0+4*y1+y2) = 389.3333333333333
Integral of the second step: h/3*(y2+4*y3+y4) = 325.3333333333333
Integral of the third step: h/3*(y4+4*y5+y6) = 197.33333333333331
Sum all, and we get 912.0 AND THIS IS TRUE
x=0
b=12
h=4
x=float(x)
h=float(h)
b=float(b)
a=float(x)
def fun(x):
return 100-(x**2)/2
h=h/2
l=0 #just numeration
print('n=',(b-x)/(h*2))
n=int((b-a)/h+1)
y = [] #tablica/lista wszystkich y / list of all "y"
yf = []
for i in range(n):
f=fun(x)
print('y%s' %(l),'=',f)
y.append(f)
l+=1
x+=h
print(y,'\n')
n1=int(((b-a)/h)/2)
l=1
for i in range(n1):
nf=(h/3*(y[+0]+4*y[+1]+y[+2]))
y=y[2:] # with every step, we deleting 2 first "y" and we move 2 spaces to the right, i.e. y2+4*y3+y4
print('Całka dla kroku/Integral for a step',l,'=',nf)
yf.append(nf)
l+=1
print('\nWynik całki/Result of the integral =', sum(yf) )
At the beginning I added simple data entry:
d=None
while(True):
print("Enter your own data or enter the word "test" for ready data.\n")
x=input ('Enter the beginning of the interval (a): ')
if x == 'test':
x=0
h=4 #krok (Δx)
b=12 #granica np. 0>12
#w=(20*x)-(x**2) lub (1+x**3)**(1/2)
break
h=input ('Enter the size of the integration step (h): ')
if h == 'test':
x=0
h=4
b=12
break
b=input ('Enter the end of the range (b): ')
if b == 'test':
x=0
h=4
b=12
break
d=input ('Give the function pattern: ')
if d == 'test':
x=0
h=4
b=12
break
elif d != -9999.9:
break
x=float(x)
h=float(h)
b=float(b)
a=float(x)
if d == None or d == 'test':
def fun(x):
return 100-(x**2)/2 #(20*x)-(x**2)
else:
def fun(x):
w = eval(d)
return w
h=h/2
l=0 #just numeration
print('n=',(b-x)/(h*2))
n=int((b-a)/h+1)
y = [] #tablica/lista wszystkich y / list of all "y"
yf = []
for i in range(n):
f=fun(x)
print('y%s' %(l),'=',f)
y.append(f)
l+=1
x+=h
print(y,'\n')
n1=int(((b-a)/h)/2)
l=1
for i in range(n1):
nf=(h/3*(y[+0]+4*y[+1]+y[+2]))
y=y[2:]
print('Całka dla kroku/Integral for a step',l,'=',nf)
yf.append(nf)
l+=1
print('\nWynik całki/Result of the integral =', sum(yf) )
def simps(f, a, b, N): # N must be an odd integer
""" define simpson method, a and b are the lower and upper limits of
the interval, N is number of points, dx is the slice
"""
integ = 0
dx = float((b - a) / N)
for i in range(1,N-1,2):
integ += f((a+(i-1)*dx)) + 4*f((a+i*dx)) + f((a+(i+1)*dx))
integral = dx/3.0 * integ
# if number of points is even, then error araise
if (N % 2) == 0:
raise ValueError("N must be an odd integer.")
return integral
def f(x):
return x**2
integrate = simps(f,0,1,99)
print(integrate)
Example of implementing Simpson's rule for integral sinX with a = 0 and b = pi/4. And use 10 panels for the integration
def simpson(f, a, b, n):
x = np.linspace(a, b, n+1)
w = 2*np.ones(n+1); w[0] = 1.0; w[-1] = 1;
for i in range(len(w)):
if i % 2 == 1:
w[i] = 4
width = x[1] - x[0]
area = 0.333 * width * np.sum( w*f(x))
return area
f = lambda x: np.sin(x)
a = 0.0; b = np.pi/4
areaSim = simpson(f, a, b, 10)
print(areaSim)