I want to implement a python function that evaluates a mathematical function (of four variables) defined by a double infinite sum at a particular point.
I've done this by using
def myfunction(x):
value = 0.0
for m in range(1,100):
for n in range(1,100):
value = value + 4.0*(1.0/((n + m)*np.pi**5)) * np.sin(n*x.detach().numpy()[:, 0:1]) * np.sin(m**2 * x.detach().numpy()[:, 1:2]) * np.sin(n*np.pi*x.detach().numpy()[:, 2:3])* np.cos(m*2*x.detach().numpy()[:, 3:4])
return torch.from_numpy(value)
Is there a better (more efficient) way to do this? When I call this function, it runs very slowly (and I'm only summing indices up to 100).
Related
I am trying to solve a nonlinear optimization problem with GEKKO Python. I know that I can pass my own function to an Intermediate or Objective function, but since my intermediate is a piecewise function, I need if-statements.
For example:
This works from what I've tested.
def calc_weighted_average(values, characteristic):
# values are the model's variables that are changed by GEKKO.
# characteristic are always the same (they are a constant list I've defined).
sum = 0
for i in range(values):
sum += values[i] * characteristic[i]
return sum / m.sum(values)
weighted_average_density = m.Intermediate(calc_weighted_average(values, density_list))
This doesn't work and I am not sure how to get this to work?
def calc_weighted_average(values, characteristic):
# values are the model's variables that are changed by GEKKO.
# characteristic are always the same (they are a constant list I've defined).
sum = 0
for i in range(values):
sum += values[i] * characteristic[i]
# Correction factor when too large
if sum > 5:
correction_factor = (sum - 5) * (0.984 ** 2)
else:
correction_factor = 0
return (sum / m.sum(values)) - correction_factor
weighted_average_density = m.Intermediate(calc_weighted_average(values, density_list))
Try the m.if3() function. Instead of:
if sum > 5:
correction_factor = (sum - 5) * (0.984 ** 2)
else:
correction_factor = 0
try the following code:
correction_factor = m.if3(sum-5,0,(sum-5)*(0.984**2))
The m.if2() function is also available as a logical condition with a Mathematical Program with Complementary Constraints (MPCC). The m.if3() function uses a binary variable instead and generally performs better, but can slow down with many binary variables for large scale problems.
beginner programmer here. I have been assigned to create a function 'Roots' that takes two parameters x and n(n has to be an integer) and then calculates all complex and real roots of the equation z^n=x. However, the only module/package I can use is math. Also, I have been told that the certain aspects of the following function 'Power_complex' play a big role into creating 'Roots':
def Power_complex(re, im, n): #calculates the n-th power of a complex number(lets call this a), where 're' is the real part and 'im' the imaginary part
import math
r=math.sqrt((re)**2+(im)**2) #calculates modulus
h=math.atan2(re,im) #calculates argument(angle)
ren=(r**n)*math.cos(h*n) #calculates the real part of a^n
imn=(r**n)*math.sin(h*n) #calculates the imaginary part of a^n
return ren, imn
print '(',re, '+', im, 'i',')','^',n,'=',ren,'+',imn,'i' #displays the result
Also, I need to somehow implement a for loop into 'Roots'.
I have been pondering over this for hours, but alas I really can't figure it out and am hoping one of you can help me out here.
BTW my python version is 2.7.10
The expression for the solutions is ( explained here ):
when
In the case that z^n is real, equal to the x in your question, then r = |x| and the angle is 0 or pi for positive and negative values, respectively.
So you make the modulus and argument as you have done, then make every solution corresponding to a value of k
z = [r**(1./n) * exp(1j * (theta + 2*pi*k) / n ) for k in range(n)]
This line uses a Python technique called list comprehension. An eqvivalent way of doing it (that you may be more familiar to) could be:
z = []
for k in range(n):
nthroot = r**(1./n) * exp( 1j * (theta + 2*pi*k) / n )
z.append(nthroot)
Printing them out could be done in the same fashion, using a for-loop:
for i in range(len(z)):
print "Root #%d = %g + i*%g" % (i, z[i].real, z[i].imag)
Note that the exp-function used must be from the module cmath (math can't handle complex numbers). If you are not allowed to use cmath, then I suggest you rewrite the expression for the solutions to the form without modulus and argument.
I'm trying to make a calculator for something, but the formulas use a sigma, I have no idea how to do a sigma in python, is there an operator for it?
Ill put a link here with a page that has the formulas on it for illustration:http://fromthedepths.gamepedia.com/User:Evil4Zerggin/Advanced_cannon
A sigma (∑) is a Summation operator. It evaluates a certain expression many times, with slightly different variables, and returns the sum of all those expressions.
For example, in the Ballistic coefficient formula
The Python implementation would look something like this:
# Just guessing some values. You have to search the actual values in the wiki.
ballistic_coefficients = [0.3, 0.5, 0.1, 0.9, 0.1]
total_numerator = 0
total_denominator = 0
for i, coefficient in enumerate(ballistic_coefficients):
total_numerator += 2**(-i) * coefficient
total_denominator += 2**(-i)
print('Total:', total_numerator / total_denominator)
You may want to look at the enumerate function, and beware precision problems.
The easiest way to do this is to create a sigma function the returns the summation, you can barely understand this, you don't need to use a library. you just need to understand the logic .
def sigma(first, last, const):
sum = 0
for i in range(first, last + 1):
sum += const * i
return sum
# first : is the first value of (n) (the index of summation)
# last : is the last value of (n)
# const : is the number that you want to sum its multiplication each (n) times with (n)
An efficient way to do this in Python is to use reduce().
To solve
3
Σ i
i=1
You can use the following:
from functools import reduce
result = reduce(lambda a, x: a + x, [0]+list(range(1,3+1)))
print(result)
reduce() will take arguments of a callable and an iterable, and return one value as specified by the callable. The accumulator is a and is set to the first value (0), and then the current sum following that. The current value in the iterable is set to x and added to the accumulator. The final accumulator is returned.
The formula to the right of the sigma is represented by the lambda. The sequence we are summing is represented by the iterable. You can change these however you need.
For example, if I wanted to solve:
Σ π*i^2
i
For a sequence I [2, 3, 5], I could do the following:
reduce(lambda a, x: a + 3.14*x*x, [0]+[2,3,5])
You can see the following two code lines produce the same result:
>>> reduce(lambda a, x: a + 3.14*x*x, [0]+[2,3,5])
119.32
>>> (3.14*2*2) + (3.14*3*3) + (3.14*5*5)
119.32
I've looked all the answers that different programmers and coders have tried to give to your query but i was unable to understand any of them maybe because i am a high school student anyways according to me using LIST will definately reduce some pain of coding so here it is what i think simplest way to form a sigma function .
#creating a sigma function
a=int(input("enter a number for sigma "))
mylst=[]
for i in range(1,a+1):
mylst.append(i)
b=sum(mylst)
print(mylst)
print(b)
Captial sigma (Σ) applies the expression after it to all members of a range and then sums the results.
In Python, sum will take the sum of a range, and you can write the expression as a comprehension:
For example
Speed Coefficient
A factor in muzzle velocity is the speed coefficient, which is a
weighted average of the speed modifiers si of the (non-
casing) parts, where each component i starting at the head has half the
weight of the previous:
The head will thus always determine at least 25% of the speed
coefficient.
For example, suppose the shell has a Composite Head (speed modifier
1.6), a Solid Warhead Body (speed modifier 1.3), and a Supercavitation
Base (speed modifier 0.9). Then we have
s0=1.6
s1=1.3
s2=0.9
From the example we can see that i starts from 0 not the usual 1 and so we can do
def speed_coefficient(parts):
return (
sum(0.75 ** i * si for i, si in enumerate(parts))
/
sum(0.75 ** i for i, si in enumerate(parts))
)
>>> speed_coefficient([1.6, 1.3, 0.9])
1.3324324324324326
import numpy as np
def sigma(s,e):
x = np.arange(s,e)
return np.sum([x+1])
I am trying to write a program using Python v. 2.7.5 that will compute the area under the curve y=sin(x) between x = 0 and x = pi. Perform this calculation varying the n divisions of the range of x between 1 and 10 inclusive and print the approximate value, the true value, and the percent error (in other words, increase the accuracy by increasing the number of trapezoids). Print all the values to three decimal places.
I am not sure what the code should look like. I was told that I should only have about 12 lines of code for these calculations to be done.
I am using Wing IDE.
This is what I have so far
# base_n = (b-a)/n
# h1 = a + ((n-1)/n)(b-a)
# h2 = a + (n/n)(b-a)
# Trap Area = (1/2)*base*(h1+h2)
# a = 0, b = pi
from math import pi, sin
def TrapArea(n):
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)(((pi-0)/n)(sin((i-1)/n(pi-0))) + sin((i/n)(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
I am not sure if I am on the right track. I am getting an error that says "local variable 'sum' referenced before assignment. Any suggestions on how to improve my code?
Your original problem and problem with Shashank Gupta's answer was /n does integer division. You need to convert n to float first:
from math import pi, sin
def TrapArea(n):
sum = 0
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/float(n))*(sin((i-1)/float(n)*(pi-0))) + sin((i/float(n))*(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
Output:
0
0.785398163397
1.38175124526
1.47457409274
1.45836902046
1.42009115659
1.38070223089
1.34524797198
1.31450259385
1.28808354
Note that you can heavily simplify the sum += ... part.
First change all (pi-0) to pi:
sum += (1.0/2.0)*((pi/float(n))*(sin((i-1)/float(n)*pi)) + sin((i/float(n))*pi))*deltax
Then do pi/n wherever possible, which avoids needing to call float as pi is already a float:
sum += (1.0/2.0)*(pi/n * (sin((i-1) * pi/n)) + sin(i * pi/n))*deltax
Then change the (1.0/2.0) to 0.5 and remove some brackets:
sum += 0.5 * (pi/n * sin((i-1) * pi/n) + sin(i * pi/n)) * deltax
Much nicer, eh?
You have some indentation issues with your code but that could just be because of copy paste. Anyways adding a line sum = 0 at the beginning of your TrapArea function should solve your current error. But as #Blender pointed out in the comments, you have another issue, which is the lack of a multiplication operator (*) after your floating point division expression (1.0/2.0).
Remember that in Python expressions are not always evaluated as you would expect mathematically. Thus (a op b)(c) will not automatically multiply the result of a op b by c like you would expect with a mathematical expression. Instead this is the function call notation in Python.
Also remember that you must initialize all variables before using their values for assignment. Python has no default value for unnamed variables so when you reference the value of sum with sum += expr which is equivalent to sum = sum + expr you are trying to reference a name (sum) that is not binded to any object at all.
The following revision to your function should do the trick. Notice how I place multiplication operators (*) between every expression that you intend to multiply.
def TrapArea(n):
sum = 0
for i in range(1, n):
i = float(i)
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/n)*(sin((i-1)/n*(pi-0))) + sin((i/n)*(pi-0)))*deltax
return sum
EDIT: I also dealt with the float division issue by converting i to float(i) within every iteration of the loop. In Python 2.x, if you divide one integer type object with another integer type object, the expression evaluates to an integer regardless of the actual value.
A "nicer" way to do the trapezoid rule with equally-spaced points...
Let dx = pi/n be the width of the interval. Also, let f(i) be sin(i*dx) to shorten some expressions below. Then interval i (in range(1,n)) contributes:
dA = 0.5*dx*( f(i) + f(i-1) )
...to the sum (which is an area, so I'm using dA for "delta area"). Factoring out the 0.5*dx, makes the whole some look like:
A = 0.5*dx * ( (f(0) + f(1)) + (f(1) + f(2)) + .... + (f(n-1) + f(n)) )
Notice that there are two f(1) terms, two f(2) terms, on up to two f(n-1) terms. Combine those to get:
A = 0.5*dx * ( f(0) + 2*f(1) + 2*f(2) + ... + 2*f(n-1) + f(n) )
The 0.5 and 2 factors cancel except in the first and last terms:
A = 0.5*dx(f(0) + f(n)) + dx*(f(1) + f(2) + ... + f(n-1))
Finally, you can factor dx out entirely to do just one multiplication at the end. Converting back to sin() calls, then:
def TrapArea(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi)) # this is 0 for this problem, but not others
for i in range(1, n-1):
asum += sin(i*dx)
return sum*dx
That changed "sum" to "asum", or maybe "area" would be better. That's mostly because sum() is a built-in function, which I'll use below the line.
Extra credit: The loop part of the sum can be done in one step with a generator expression and the sum builtin function:
def TrapArea2(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi))
asum += sum(sin(i*dx) for i in range(1,n-1))
return asum*dx
Testing both of those:
>>> for n in [1, 10, 100, 1000, 10000]:
print n, TrapArea(n), TrapArea2(n)
1 1.92367069372e-16 1.92367069372e-16
10 1.88644298557 1.88644298557
100 1.99884870579 1.99884870579
1000 1.99998848548 1.99998848548
10000 1.99999988485 1.99999988485
That first line is a "numerical zero", since math.sin(math.pi) evaluates to about 1.2e-16 instead of exactly zero. Draw the single interval from 0 to pi and the endpoints are indeed both 0 (or nearly so.)
i wrote this python code, which from wolfram alpha says that its supposed to return the factorial of any positive value (i probably messed up somewhere), integer or not:
from math import *
def double_factorial(n):
if int(n) == n:
n = int(n)
if [0,1].__contains__(n):
return 1
a = (n&1) + 2
b = 1
while a<=n:
b*=a
a+= 2
return float(b)
else:
return factorials(n/2) * 2**(n/2) *(pi/2)**(.25 *(-1+cos(n * pi)))
def factorials(n):
return pi**(.5 * sin(n*pi)**2) * 2**(-n + .25 * (-1 + cos(2*n*pi))) * double_factorial(2*n)
the problem is , say i input pi to 6 decimal places. 2*n will not become a float with 0 as its decimals any time soon, so the equation turns out to be
pi**(.5 * sin(n*pi)**2) * 2**(-n + .25 * (-1 + cos(2*n*pi))) * double_factorial(loop(loop(loop(...)))))
how would i stop the recursion and still get the answer?
ive had suggestions to add an index to the definitions or something, but the problem is, if the code stops when it reaches an index, there is still no answer to put back into the previous "nests" or whatever you call them
You defined f in terms of g and g in terms of f. But you don't just have a circular definition with no base point to start the recursion. You have something worse. The definition of f is actually the definition of g inverted. f is precisely undoing what g did and vice versa. If you're trying to implement gamma yourself (ie. not using the one that's already there in the libraries) then you need to use a formula that expresses gamma in terms of something else that you know how to evaluate. Just using one formula and its inversion like that is a method that will fail for almost any problem you apply it to.
In your code, you define double_factorial like
double_factorial(n) = factorial(n/2) * f(n) ... (1)
and in the factorial you define it as
factorial(n) = double_factorial(2*n) / f(2*n) ... (2)
which is equivalent to equation (1), so you created a circular reference without an exit point. Even math can't help. You have to define either factorial or double_factorial, e.g.
def factorials(n):
return tgamma(n + 1)