I am trying to convert these rate equations to python code, I have made I lot of research but can't seem to get any clear path to follow to achieve this, please any help will be appreciated
This is a newly updated code....i wrote using the quide from Tom10.....please what do you think?
import numpy as np
# import numpy as sum # not necessary, just for convenience, and replaces the builtin
# set N_core value
N_CORE = 0
# set the initial conditions appropriately (you need to set these correctly)
N = np.ones(8)
r = np.ones((8, 8))
dN = np.zeros(8) # the value here is not important for your equations
# set constant for equation 1
R_P1abs37 = 20
F_P1 = 20
R_P1abs47 = 40
W_3317 = 1.0
# set constant for equation 2
W_6142 = 90
W_5362 = 80
# Set you constants appropriately for equation 3
R_P2abs35 = 30
F_P2 = 40
R_L2se34 = 50
F_L2 = 90
# equation 4 constants
W_2214 = 20
#equation 5 constants
R_P1abs13 = 30
R_L2se32 = 20
F_L1 = 10
# equation 1 formular
dN[7] =sum(r[7,:]*N[7]) + (R_P1abs37*F_P1) + (R_P1abs47*F_P1) + (W_3317*N[3]**2)
# equation 2 formular
dN[6] = (r[7,6]*N[7]) - sum(r[6,:]*N[6]) - (W_6142*N[6]*N[1]) + (W_5362*N[5]*N[3])
#equation 3 formular
dN[5] = sum(r[:,5]*N) - sum(r[5,:]*N[5]) + R_P2abs35*F_P2 - R_L2se34*F_L2 - W_5362*N[5]*N[3]
# equation 4 formular
dN[4] = sum(r[:,4]*N) - sum(r[4,:]*N[4]) - (R_P1abs47*F_P1) + (R_L2se34*F_L2) + (W_2214*N[2]**2)+ (W_6142*N[6]*N[1])
#equation 5 formular
dN[3] = sum(r[:,3]*N) - sum(r[3,:]*N[3]) + (R_P1abs13*F_P1) - (R_P1abs37*F_P1) - (R_P2abs35*F_P2)
-(R_L2se32*F_L1) - ((2*W_3317)*N[3]**2) - (W_5362*N[5]*N[3])
#equation 6 formular
dN[2] = sum(r[:,2]*N) - (r[2,1]*N[2]) + (R_L2se32*F_L1) - ((2*W_2214)*N[2]**2) + (W_6142*N[6]*N[1])+(W_5362*N[5]*N[3])
#equation 7 formular
dN[1] = sum(r[:,1] * N) - (R_P1abs13*F_P1) + (W_2214*N[2]**2) + (W_3317+N[3]**2) - (W_6142+N[6]*N[1])
#equation for N CORE
N_CORE = sum(dN)
print(N_CORE)
Here is list of relevant issues based on your question and comments:
Usually if the summation is over i, then everything without an i subscript is constant for that sum. (Mathematically these constant terms can just be brought out of the sum; so the first equation is a bit odd where the N_7 could be moved out of the sum but I think they're keeping it in to show the symmetry with the other equations which all have an r*N term).
The capitol sigma symbol (Ξ£) means you need to do a sum, which you can do in a loop, but both Python list and numpy have a sum function. Numpy has the additional advantage that multiplication is interpreted as multiplication of the individual elements, making the expression easier. So for a[0]*[b0] + a[1]*b[1] + a[2]*b[2] and numpy arrays is simply sum(a*b) and for Python lists it's sum([a[i]*b[i] for in range(len(a))]
Therefore using numpy, the setup and your third equation would look like:
import numpy as np
import numpy.sum as sum # not necessary, just for convenience, and replaces the builtin
# set the initial conditions appropriately (you need to set these correctly)
N = np.ones(7, dtype=np.float)
# r seems to be a coupling matrix, and should be set according to your system
r = np.ones((7, 7), dtype = np.float)
# the values for dN are not important for your equations because dN only appears on the left side of the equations, so we just make a place to store the results
dN = np.zeros(7, dtype=np.float)
# Set you constants appropriate.y
R_P2abs35 = 1.0
F_P2 = 1.0
R_L2se34 = 1.0
F_L2 = 1.0
W_5362 = 1.0
dN[5] = sum(r[:,5]*N) - sum(r[5,:]*N[5]) + R_P2abs35*F_P2 - R_L2se34*F_L2 - W_5362*N[5]*N[3]
Note that although the expressions in the sums look similar, the first is essentially a dot product between two vectors and the second is a scalar times a vector so N[5] could be taken out of the sum (but I left it there to match the equation).
Final note: I see you're new to S.O. so I thought it would be helpful if I answered this question for you. In the future, please show some attempt at the code -- it really helps a lot.
Related
I am looking for ideas on how to translate one range values to another in Python. I am working on hardware project and am reading data from a sensor that can return a range of values, I am then using that data to drive an actuator that requires a different range of values.
For example lets say that the sensor returns values in the range 1 to 512, and the actuator is driven by values in the range 5 to 10. I would like a function that I can pass a value and the two ranges and get back the value mapped to the second range. If such a function was named translate it could be used like this:
sensor_value = 256
actuator_value = translate(sensor_value, 1, 512, 5, 10)
In this example I would expect the output actuator_value to be 7.5 since the sensor_value is in the middle of the possible input range.
One solution would be:
def translate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
You could possibly use algebra to make it more efficient, at the expense of readability.
Using scipy.interpolate.interp1d
You can also use scipy.interpolate package to do such conversions (if you don't mind dependency on SciPy):
>>> from scipy.interpolate import interp1d
>>> m = interp1d([1,512],[5,10])
>>> m(256)
array(7.4951076320939336)
or to convert it back to normal float from 0-rank scipy array:
>>> float(m(256))
7.4951076320939336
You can do also multiple conversions in one command easily:
>>> m([100,200,300])
array([ 5.96868885, 6.94716243, 7.92563601])
As a bonus, you can do non-uniform mappings from one range to another, for intance if you want to map [1,128] to [1,10], [128,256] to [10,90] and [256,512] to [90,100] you can do it like this:
>>> m = interp1d([1,128,256,512],[1,10,90,100])
>>> float(m(400))
95.625
interp1d creates piecewise linear interpolation objects (which are callable just like functions).
Using numpy.interp
As noted by ~unutbu, numpy.interp is also an option (with less dependencies):
>>> from numpy import interp
>>> interp(256,[1,512],[5,10])
7.4951076320939336
This would actually be a good case for creating a closure, that is write a function that returns a function. Since you probably have many of these values, there is little value in calculating and recalculating these value spans and factors for every value, nor for that matter, in passing those min/max limits around all the time.
Instead, try this:
def make_interpolater(left_min, left_max, right_min, right_max):
# Figure out how 'wide' each range is
leftSpan = left_max - left_min
rightSpan = right_max - right_min
# Compute the scale factor between left and right values
scaleFactor = float(rightSpan) / float(leftSpan)
# create interpolation function using pre-calculated scaleFactor
def interp_fn(value):
return right_min + (value-left_min)*scaleFactor
return interp_fn
Now you can write your processor as:
# create function for doing interpolation of the desired
# ranges
scaler = make_interpolater(1, 512, 5, 10)
# receive list of raw values from sensor, assign to data_list
# now convert to scaled values using map
scaled_data = map(scaler, data_list)
# or a list comprehension, if you prefer
scaled_data = [scaler(x) for x in data_list]
I was looking for the same thing in python to map angles 0-300deg to raw dynamixel values 0-1023, or 1023-0 depending on the actuator orientations.
I ended up going very simple.
Variables:
x:input value;
a,b:input range
c,d:output range
y:return value
Function:
def mapFromTo(x,a,b,c,d):
y=(x-a)/(b-a)*(d-c)+c
return y
Usage:
dyn111.goal_position=mapFromTo(pos111,0,300,0,1024)
def translate(sensor_val, in_from, in_to, out_from, out_to):
out_range = out_to - out_from
in_range = in_to - in_from
in_val = sensor_val - in_from
val=(float(in_val)/in_range)*out_range
out_val = out_from+val
return out_val
Simple map range function:
def mapRange(value, inMin, inMax, outMin, outMax):
return outMin + (((value - inMin) / (inMax - inMin)) * (outMax - outMin))
def maprange(a, b, s):
(a1, a2), (b1, b2) = a, b
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
a = [from_lower, from_upper]
b = [to_lower, to_upper]
found at https://rosettacode.org/wiki/Map_range#Python_
does not clamp the transformed values to the ranges a or b (it extrapolates)
also works when from_lower > from_upper or to_lower > to_upper
All of the existing answers are under the CC BY-SA license. Here's one that I wrote; to the extent possible under law, I waive all copyright or related and neighboring rights to this code. (Creative Commons CC0 Public Domain Dedication).
def remap(number, from_min, from_max, to_min, to_max):
number_s = number - from_min
from_max_s = from_max - from_min
to_max_s = to_max - to_min
return ((number_s / from_max_s) * to_max_s) + to_min
You could use a lambda function
translate = lambda a, b, c, d, e: (a - b) * (e - d) / (c - b) + d
sensor_value = 256
translate(sensor_value, 1, 512, 5, 10)
>> 7.495107632093934
I'm a beginner to Python and I'm trying to calculate the angles (-26.6 &18.4) for this figure below and so on for the rest of the squares by using Python code.
I have found the code below and I'm trying to understand very well. How could it work here? Any clarification, please?
Python Code:
def computeDegree(a,b,c):
babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])
norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)
norm_babc = norm_ba * norm_bc
radian = math.acos(babc/norm_babc)
degree = math.degrees(radian)
return round(degree, 1)
def funcAngle(p, s, sn):
a = (s[0]-p[0], s[1]-p[1])
b = (sn[0]-p[0], sn[1]-p[1])
c = a[0] * b[1] - a[1] * b[0]
if p != sn:
d = computeDegree(s, p, sn)
else:
d = 0
if c > 0:
result = d
elif c < 0:
result = -d
elif c == 0:
result = 0
return result
p = (1,4)
s = (2,2)
listSn= ((1,2),(2,3),(3,2),(2,1))
for sn in listSn:
func(p,s,sn)
The results
I expected to get the angles in the picture such as -26.6, 18.4 ...
Essentially, this uses the definition of dot products to solve for the angle. You can read more it at this link (also where I found these images).
To solve for the angle you first need to convert your 3 input points into two vectors.
# Vector from b to a
# BA = (a[0] - b[0], a[1] - b[1])
BA = a - b
# Vector from b to c
# BC = (a[0] - c[0], a[1] - c[1])
BC = c - b
Using the two vectors you can then find the angle between them by first finding the value of the dot product with the second formula.
# babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])
dot_product = BA[0] * BC[0] + BA[1] * BC[1]
Then by going back to the first definition, you can divide off the lengths of the two input vectors and the resulting value should be the cosine of the angle between the vectors. It may be hard to read with the array notation but its just using the Pythagoras theorem.
# Length/magnitude of vector BA
# norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
length_ba = math.sqrt(BA[0]**2 + BA[1]**2)
# Length/magnitude of vector BC
# norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)
length_bc = math.sqrt(BC[0]**2 + BC[1]**2)
# Then using acos (essentially inverse of cosine), you can get the angle
# radian = math.acos(babc/norm_babc)
angle = Math.acos(dot_product / (length_ba * length_bc))
Most of the other stuff is just there to catch cases where the program might accidentally try to divide by zero. Hopefully this helps to explain why it looks the way it does.
Edit: I answered this question because I was bored and didn't see harm in explaining the math behind that code, however in the future try to avoid asking questions like 'how does this code work' in the future.
Let's start with funcAngle since it calls computeDegree later.
The first thing it does is define a as a two item tuple. A lot of this code seems to use two item tuples, with the two parts referenced by v[0] and v[1] or similar. These are almost certainly two dimensional vectors of some sort.
I'm going to write these as π― for the vector and vβ and vᡧ since they're probably the two components.
[don't look too closely at that second subscript, it's totally a y and not a gamma...]
a is the vector difference between s and p: i.e.
a = (s[0]-p[0], s[1]-p[1])
is aβ=sβ-pβ and aᡧ=sᡧ-pᡧ; or just π=π¬-π© in vector.
b = (sn[0]-p[0], sn[1]-p[1])
again; π=π¬π§-π©
c = a[0] * b[1] - a[1] * b[0]
c=aβbᡧ-aᡧbβ; c is the cross product of π and π (and is just a number)
if p != sn:
d = computeDegree(s, p, sn)
else:
d = 0
I'd take the above in reverse: if π© and π¬π§ are the same, then we already know the angle between them is zero (and it's possible the algorithm fails badly) so don't compute it. Otherwise, compute the angle (we'll look at that later).
if c > 0:
result = d
elif c < 0:
result = -d
elif c == 0:
result = 0
If c is pointing in the normal direction (via the left hand rule? right hand rule? can't remember) that's fine: if it isn't, we need to negate the angle, apparently.
return result
Pass the number we've just worked out to some other code.
You can probably invoke this code by adding something like:
print (funcangle((1,0),(0,1),(2,2))
at the end and running it. (Haven't actually tested these numbers)
So this function works out a and b to get c; all just to negate the angle if it's pointing the wrong way. None of these variables are actually passed to computeDegree.
so, computeDegree():
def computeDegree(a,b,c):
First thing to note is that the variables from before have been renamed. funcAngle passed s, p and sn, but now they're called a, b and c. And the note the order they're passed in isn't the same as they're passed to funcAngle, which is nasty and confusing.
babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])
babc = (aβ-bβ)(cβ-bβ)+(aᡧ-bᡧ)(cᡧ-bᡧ)
If π' and π' are π-π and π-π respectively, this is just
a'βc'β+a'ᡧc'ᡧ, or the dot product of π' and π'.
norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)
norm_ba = β[(aβ-bβ)Β² + (aᡧ-bᡧ)Β²] (and norm_bc likewise).
This looks like the length of the hypotenuse of π' (and π' respectively)
norm_babc = norm_ba * norm_bc
which we then multiply together
radian = math.acos(babc/norm_babc)
We use the arccosine (inverse cosine, cos^-1) function, with the length of those multiplied hypotenuses as the hypotenuse and that dot product as the adjacent length...
degree = math.degrees(radian)
return round(degree, 1)
but that's in radians, so we convert to degrees and round it for nice formatting.
Ok, so now it's in maths, rather than Python, but that's still not very easy to understand.
(sidenote: this is why descriptive variable names and documentation is everyone's friend!)
Energy calculations in molecular simulation are inherently full of "for" loops. Traditionally coordinates for each atom/molecule were stored in arrays. arrays are fairly straightforward to vectorize, but structures are nice to code with. Treating molecules as individual objects, each with their own coordinates, and other properties, is very convenient and much clearer as far as book-keeping goes.
I am using Python version 3.6
My problem is that I cannot figure out how to vectorize calculations when I am using an array of objects... it seems that a for loop cannot be avoided. Is it necessary for me to use arrays in order to take advantage of numpy and vectorize my code?
Here is a python example which utilizes arrays (line 121 of the code), and shows a fast (numpy) and slow ( 'normal') python energy calculation.
https://github.com/Allen-Tildesley/examples/blob/master/python_examples/mc_lj_module.py
The calculation is much faster using the numpy accelerated method because it is vectorized.
How would I vectorize an energy calculation if I was not using arrays, but an array of objects, each with their own coordinates? This seems to necessitate using the slower for loop.
Here is a simple example code with a working slow version of the for loop, and an attempted vectorization that doesn't work:
import numpy as np
import time
class Mol:
num = 0
def __init__(self, r):
Mol.num += 1
self.r = np.empty((3),dtype=np.float_)
self.r[0] = r[0]
self.r[1] = r[1]
self.r[2] = r[2]
""" Alot more useful things go in here in practice"""
################################################
# #
# Main Program #
# #
################################################
L = 5.0 # Length of simulation box (arbitrary)
r_cut_box_sq = L/2 # arbitrary cutoff - required
mol_list=[]
nmol = 1000 # number of molecules
part = 1 # arbitrary molecule to interact with rest of molecules
""" make 1000 molecules (1 atom per molecule), give random coordinates """
for i in range(nmol):
r = np.random.rand(3) * L
mol_list.append( Mol( r ) )
energy = 0.0
start = time.time()
################################################
# #
# Slow but functioning loop #
# #
################################################
for i in range(nmol):
if i == part:
continue
rij = mol_list[part].r - mol_list[i].r
rij = rij - np.rint(rij/L)*L # apply periodic boundary conditions
rij_sq = np.sum(rij**2) # Squared separations
in_range = rij_sq < r_cut_box_sq
sr2 = np.where ( in_range, 1.0 / rij_sq, 0.0 )
sr6 = sr2 ** 3
sr12 = sr6 ** 2
energy += sr12 - sr6
end = time.time()
print('slow: ', end-start)
print('energy: ', energy)
start = time.time()
################################################
# #
# Failed vectorization attempt #
# #
################################################
""" The next line is my problem, how do I vectorize this so I can avoid the for loop all together?
Leads to error AttributeError: 'list' object has no attribute 'r' """
""" I also must add in that part cannot interact with itself in mol_list"""
rij = mol_list[part].r - mol_list[:].r
rij = rij - np.rint(rij/L)*L # apply periodic boundary conditions
rij_sq = np.sum(rij**2)
in_range = rij_sq < r_cut_box_sq
sr2 = np.where ( in_range, 1.0 / rij_sq, 0.0 )
sr6 = sr2 ** 3
sr12 = sr6 ** 2
energy = sr12 - sr6
energy = sum(energy)
end = time.time()
print('faster??: ', end-start)
print('energy: ', energy)
Lastly
Would any possible solutions be affected if inside the energy calculation, it was necessary to loop over each atom in each molecule where their is now more than 1 atom per molecule, and not all molecules have the same number of atoms, thus having a double for loop for molecule-molecule interactions rather than the simple pair-pair interactions currently employed.
Making use of the itertools library might be the way forward here. Suppose you wrap the energy calculation of a pair of molecules in a function:
def calc_pairwise_energy((mol_a,mol_b)):
# function takes a 2 item tuple of molecules
# energy calculating code here
return pairwise_energy
Then you can use itertools.combinations to get all the pairs of molecules and python's built in list comprehensions (the code inside [ ] on the last line below):
from itertools import combinations
pairs = combinations(mol_list,2)
energy = sum( [calc_pairwise_energy(pair) for pair in pairs] )
I've come back to this answer as I realised I hadn't properly answered your question. With what I've already posted the pairwise energy calculation function looked like this (I've made a few optimisations to your code):
def calc_pairwise_energy(molecules):
rij = molecules[0].r - molecules[1].r
rij = rij - np.rint(rij/L)*L
rij_sq = np.sum(rij**2) # Squared separations
if rij_sq < r_cut_box_sq:
return (rij_sq ** -6) - (rij_sq ** - 3)
else:
return 0.0
Whereas a vectorised implementation that does all the pairwise calculations in a single call might look like this:
def calc_all_energies(molecules):
energy = 0
for i in range(len(molecules)-1):
mol_a = molecules[i]
other_mols = molecules[i+1:]
coords = np.array([mol.r for mol in other_mols])
rijs = coords - mol_a.r
# np.apply_along_axis replaced as per #hpaulj's comment (see below)
#rijs = np.apply_along_axis(lambda x: x - np.rint(x/L)*L,0,rijs)
rijs = rijs - np.rint(rijs/L)*L
rijs_sq = np.sum(rijs**2,axis=1)
rijs_in_range= rijs_sq[rijs_sq < r_cut_box_sq]
energy += sum(rijs_in_range ** -6 - rijs_in_range ** -3)
return energy
This is much faster but there is still plenty to optimise here.
If you want to calculate energies with coordinates as inputs, I'm assuming you're looking for pair-wise distances. For this, you should look into the SciPy library. Specifically, I would look at scipy.spatial.distance.pdist. The documentation can be found here.
I'm trying to get the Taylor series for this function
Which should be similar to this, considering that d is centered or around rs
However when I try to take the example of #Saullo for my problem,
As you can see the result is eliminating "d" from the series of Taylor, which should not be my goal.
Another additional info about the function in fact is:
I'm doing something wrong ??, is there a way to get my result without deleting "d" ??
Any help is appreciated
The code
Thank you for your response and interest in helping me, here is my code until nowdays #asmeurer
import sympy as sy
#import numpy as np
from sympy import init_printing
init_printing(use_latex=True)
# Define the variable and the function to approximate
z, d, r_s, N_e, r_t, r_s, r_b = sy.symbols('z d r_s N_e r_t r_s r_b')
# Define W_model
def W_model(r_t=r_t, r_b=r_b, r_s=r_s, z=z):
s_model = sy.sqrt(pow(r_t, 2) - pow(r_s*sy.sin(z), 2)) - sy.sqrt(pow(r_b, 2) - pow(r_s*sy.sin(z), 2))
d_model = r_t - r_b
STEC_approx = N_e * s_model
VTEC_approx = N_e * d_model
return STEC_approx/VTEC_approx
f = W_model()
# printing Standard model
f
# Some considerations for modify Standard model
rb = r_s - d/2
rt = r_s + d/2
f = W_model(r_b=rb, r_t=rt, r_s=r_s, z=z)
# printing My model
f
## Finding taylor series aproximmation for W_model
num_of_terms = 2
# creates a generator
taylor_series = f.series(x=d, n=None)
# takes the number of terms desired for your generator
taylor_series = sum([next(taylor_series) for i in range(num_of_terms)])
taylor_series
The issue is that your expression is complicated enough that series doesn't know that the odd order terms are zero (you get complicated expressions for them, but if you call simplify() on them, they go to 0). Consider
In [62]: s = f.series(d, n=None)
In [63]: a1 = next(s)
In [64]: a2 = next(s)
In [65]: simplify(a0)
Out[65]:
rβ
ββββββββββββββββ
_____________
β± 2 2
β²β± rβ β
cos (z)
In [66]: simplify(a1)
Out[66]: 0
If you print a0 and a1 they are both complicated expressions. In fact, you need to get several terms (up to a3) before series gets a term that doesn't cancel to 0:
In [73]: simplify(a3)
Out[73]:
_____________
2 β± 2 2 2
d β
β²β± rβ β
cos (z) β
sin (z)
βββββββββββββββββββββββββββ
3 6
8β
rβ β
cos (z)
If you do f.series(d, n=3), it gives the expansion up to d**2 (n=3 means + O(d**3)). You can simplify the expression quite a bit using
collect(expr.removeO(), d, simplify)
Internally, when you give series an explicit n, it uses the term-by-term generator to get as many terms as it needs to give the proper O(d**n) expansion. If you use the generator yourself (n=None), you need to do this manually.
In general, the iterator is not guaranteed to give you the next order term. If you want guarantees that you have all the terms, you need to provide an explicit n. The O term returned by series is always correct (meaning all the lower order terms are complete).
The book Calculus and Pizza by Clifford Pickover has a few code examples here and there, all written in some dialect of BASIC.
I wrote a Python version of the code example covering integration. His BASIC example goes like:
10 REM Integration
20 DEF FNY(X) = X*X*X
30 A = 0
40 B = 1
50 N = 10
55 R = 0
60 H = (B-A)/N
70 FOR X = A TO B - H/2 STEP H
80 R = R + FNY(X)
90 NEXT X
100 R = R * H
110 PRINT *INTEGRATION ESTIMATE*: R
I changed a few things here and there, allowing the user to specify the interval over which to take the integral, specify the function to be integrated as a lambda, and so forth. I knew right off the bat that the for loop wouldn't work as I have written it below. I'm just wondering if there's some direct or idiomatic translation of the BASIC for to a Python for.
def simpleintegration():
f = eval(input("specify the function as a lambda\n:%"))
a = int(input("take the integral from x = a = ...\n:%"))
b = int(input("to x = b = ...\n:%"))
n = 10
r = 0
h = (b-a)/n
for x in range(a,b-h/2,h):
r = r + f(x)
r = r * h
print(r)
Your translation isn't far off. The only difference between the for loop in other languages and Python's "loop-over-a-range" pattern is that the "stop" value is usually inclusive in other languages, but is exclusive in Python.
Thus, in most other languages, a loop including a and b looks like
for i = a to b step c
' Do stuff
next i
In Python, it would be
for i in range(a, b + 1, c):
# Do stuff
The formula is computing the Riemann sums using the values at the left end of the subdivision intervals. Thus the last used value for X should be B-H.
Due to floating point errors, stepping from A by H can give a last value that is off by some small amount, thus B-H is not a good bound (in the BASIC code) and B-H/2 is used to stop before X reaches B.
The Python code should work in the presented form for the same reasons, since the bound B-H/2 is unreachable, thus the range should stop with B-H or a value close by.
Using a slight modification you can actually compute the trapezoidal approximation, where you initialize with R=f(A)/2, step X from A+H to including B-H adding f(X) to R and then finish by adding f(B)/2 (which could already be done in the initialization). As before, the approximation of the integral is then R*H.
You can do as below, just changing iteration of 'i' in for loop.
def simpleintegration():
f = eval(input("specify the function as a lambda\n:%"))
a = int(input("take the integral from x = a = ...\n:%"))
b = int(input("to x = b = ...\n:%"))
n = 10
r = 0
h = (b-a)/n
for x = a to b-h/2 step h:
r = r + f(x)
r = r * h
print(r)