How to predict custom functions values? - python

There is this function, m=[12,24,168,672], the integer values of the function from t=0 to t=168 are known , as well as the fact that there are integers in the array b, it is required to calculate the following values of the function at t from 168 to 335, please tell me how this can be done.

Try this:
from math import cos, pi
def f(t, a, b, m):
# t is a number
# a is a list of 5 numbers
# b and m are lists of 4 numbers
return a[0] + sum(a[i + 1] * cos((t / m[i] + b[i] / 24) * 2 * pi)
for i in range(4))
Now you can compute your function:
>>> a = [10, 11, 11, 12, 12]
>>> b = [1, 2, 3, 4]
>>> m = [12, 24, 168, 672]
>>> f(170, a, b, m)
15.671777368560361

Related

Maximum sum combinations from 4 arrays

I have 4 arrays with 2 columns: one column measuring meters and the other measuring the money you get per meter, I want to get the highest sum combinations from these 4 arrays but I have 2 rules : the first rule is that each meter value in the sum has to be between 1 and 6 meters, and the second rule is that the meter value of the result has to be equal to 12 meters. I have written a code that gets the maximum sum out of a series of 4 arrays but I don't know how to implement the 2 rules in the code. This is why i am asking for your help.
My 4 arrays :
1,2,3,4,5,6 are the meter values
and the numbers below the meter values is the money earned by meters
A = [[1, 2, 3, 4, 5, 6],
[50.4, 100.8, 201.6, 403.2, 806.4, 1612.8]]
B = [[1, 2, 3, 4, 5, 6],
[40.8, 81.6, 163.2, 326.4, 652.8, 1305.6]]
C = [[1, 2, 3, 4, 5, 6],
[110, 220, 440, 880, 1760, 3520]]
D = [[1, 2, 3, 4, 5, 6],
[64, 128, 256, 512, 1024, 2048]]
My code :
import math
from queue import PriorityQueue
def KMaxCombinations(A, B, C, D, N, K):
# Max heap.
pq = PriorityQueue()
# Insert all the possible
# combinations in max heap.
for i in range(0,N):
for j in range(0,N):
for k in range(0,N):
for l in range(0,N):
a = A[i] + B[j] + C[k] + D[l]
pq.put((-a, a))
# Pop first N elements from
# max heap and display them.
count = 0
while (count < K):
print(pq.get()[1])
count = count + 1
# Driver method
A = [50.4, 100.8, 201.6, 403.2, 806.4, 1612.8]
B = [40.8, 81.6, 163.2, 326.4, 652.8, 1305.6]
C = [110, 220, 440, 880, 1760, 3520]
D = [64, 128, 256, 512, 1024, 2048]
N = len(A)
K = 3
# Function call
KMaxCombinations(A, B, C, D, N, K)
As it has been said in the comments other approaches may be more efficient. And of course we need to put the meters data in the list together with the prices:
A = [(1, 50.4), (2, 100.8), (3, 201.6), (4, 403.2), (5, 806.4), (6, 1612.8)]
B = [(1, 40.8), (2, 81.6), (3, 163.2), (4, 326.4), (5, 652.8), (6, 1305.6)]
C = [(1, 110), (2, 220), (3, 440), (4, 880), (5, 1760), (6, 3520)]
D = [(1, 64), (2, 128), (3, 256), (4, 512), (5, 1024), (6, 2048)]
Then, if we want to keep your approach (just allow me to use itertools.product instead of those 4 for loops) a possible solution would be:
def KMaxCombinations(A, B, C, D, N, K):
pq = PriorityQueue()
for p in product(A, B, C, D):
meters, prices = list(zip(*p))
for m in meters:
if not (0<m<7):
allgood = False
break
else:
allgood = True
if allgood and (sum(meters) == 12):
a = sum(prices)
pq.put((-a, a))
count = 0
while (count < K):
print(pq.get()[1])
count = count + 1
KMaxCombinations(A,B,C,D,N,K)
4123.2
4028.0
3960.8
Here's a modification of posted code to solve for solution.
Using exhaustive search as posted code
Changes:
Used heapq as PriorityQueue
Made A, B, C, D 2-dimensional lists to add meters
Added if conditionals to implement rules
Code
import heapq
def KMaxCombinations(A, B, C, D, N, K):
# Trying all combinations of the rows of A, B, C, D
priority_queue = []
for i in range(0,N):
if 1 <= A[0][i] <= 6: # the first rule is that each meter value in the sum has to be between 1 and 6 meters
for j in range(0,N):
if 1 <= B[0][j] <= 6: # the first rule is that each meter value in the sum has to be between 1 and 6 meters
for k in range(0,N):
if 1 <= C[0][k] <= 6: # the first rule is that each meter value in the sum has to be between 1 and 6 meters
for l in range(0,N):
if 1 <= D[0][l] <= 6: # the first rule is that each meter value in the sum has to be between 1 and 6 meters
# second rule is that the meter value of the result has to be equal to 12 meters
if A[0][i] + B[0][j] + C[0][k]+ D[0][l] == 12:
money_obtained = A[1][i] + B[1][j] + C[1][k] + D[1][l]
# Add another solution to priority queue
heapq.heappush(priority_queue, (-money_obtained, i, j, k, l))
return heapq.nsmallest(K, priority_queue)[K-1] # K-th most money
# use smallest since money is negative
# value to make max heap
Test
# Use 2D list for meters and money
# A[0] - list of meters
# A[1] - list of money
# same for B, C, D
A = [[1, 2, 3, 4, 5, 6],
[50.4, 100.8, 201.6, 403.2, 806.4, 1612.8]]
B = [[1, 2, 3, 4, 5, 6],
[40.8, 81.6, 163.2, 326.4, 652.8, 1305.6]]
C = [[1, 2, 3, 4, 5, 6],
[110, 220, 440, 880, 1760, 3520]]
D = [[1, 2, 3, 4, 5, 6],
[64, 128, 256, 512, 1024, 2048]]
K = 3 # 3rd best solution
solution = KMaxCombinations(A, B, C, D, len(A[0]), K)
# Show result
if solution:
max_money,*sol = solution
print(f'{K}rd Max money is {max_money}')
print(f'Using A[{sol[0]}] = {A[0][sol[0]]}')
print(f'Using B[{sol[1]}] = {A[0][sol[1]]}')
print(f'Using C[{sol[2]}] = {A[0][sol[2]]}')
print(f'Using D[{sol[3]}] = {A[0][sol[3]]}')
print(f'Sum A, B, C, d meters is: {A[0][sol[0]] + B[0][sol[1]] + C[0][sol[2]] + D[0][sol[3]]}')
else:
print("No Solution")
Output
3rd Max money is 3960.8
Using A[0] = 1
Using B[3] = 4
Using C[5] = 6
Using D[0] = 1
Sum A, B, C, d meters is: 12
This can be solved with additional info that wasn't in the question. The meter number is just the one-based index of the array. (see comments, and OP: please edit that info into the question. External links to pictures aren't allowed.)
Since you're not familiar with dynamic programming, and this problem suits itself to a brute force approach, we'll do that. You just need the meter number to check the constraints, which you can get from python's enumerate.
https://docs.python.org/3/library/functions.html#enumerate
Your for loops over a container should not be based on an index, but rather something simple like "for a in A", but since we want the index as well, let's do this
for a_meter, a_value in enumerate(A, start=1):
for b_meter, b_value in enumerate(B, start=1):
for c_meter, c_value in enumerate(C, start=1):
for d_meter, d_value in enumerate(D, start=1):
if check_constraints(a_meter, b_meter, c_meter, d_meter):
value = sum((a_value, b_value, c_value, d_value))
pq.put(-value, value)
We can check the constraints first, and only include the values that pass in the priority queue.
def check_constraints(a, b, c, d):
return sum((a, b, c, d)) == 12
When you do this kind of brute forcing, you really want to use itertools. What you've done with these for loops is basically itertools.product.
https://docs.python.org/3/library/itertools.html#itertools.product
Additionally, itertools doesn't care how many different sets of meters you have. It would be easy (with some practice) to write a function like KMaxCombinations(collection_of_meters, target=12, K=3) using itertools.
Additionally, you can chain iterators like enumerate directly into the product. You can also use itertools.islice to skip candidates that can't meet the criteria. That doesn't help in this particular problem, but if the 12 were different, it might be high enough that you can entirely skip the first few readings. Or if it's low enough, you can skip the last several readings.

Two dimensional function not returning array of values?

I'm trying to plot a 2-dimensional function (specifically, a 2-d Laplace solution). I defined my function and it returns the right value when I put in specific numbers, but when I try running through an array of values (x,y below), it still returns only one number. I tried with a random function of x and y (e.g., f(x,y) = x^2 + y^2) and it gives me an array of values.
def V_func(x,y):
a = 5
b = 4
Vo = 4
n = np.arange(1,100,2)
sum_list = []
for indx in range(len(n)):
sum_term = (1/n[indx])*(np.cosh(n[indx]*np.pi*x/a))/(np.cosh(n[indx]*np.pi*b/a))*np.sin(n[indx]*np.pi*y/a)
sum_list = np.append(sum_list,sum_term)
summation = np.sum(sum_list)
V = 4*Vo/np.pi * summation
return V
x = np.linspace(-4,4,50)
y = np.linspace(0,5,50)
V_func(x,y)
Out: 53.633709914177224
Try this:
def V_func(x,y):
a = 5
b = 4
Vo = 4
n = np.arange(1,100,2)
# sum_list = []
sum_list = np.zeros(50)
for indx in range(len(n)):
sum_term = (1/n[indx])*(np.cosh(n[indx]*np.pi*x/a))/(np.cosh(n[indx]*np.pi*b/a))*np.sin(n[indx]*np.pi*y/a)
# sum_list = np.append(sum_list,sum_term)
sum_list += sum_term
# summation = np.sum(sum_list)
# V = 4*Vo/np.pi * summation
V = 4*Vo/np.pi * sum_list
return V
Define a pair of arrays:
In [6]: x = np.arange(3); y = np.arange(10,13)
In [7]: x,y
Out[7]: (array([0, 1, 2]), array([10, 11, 12]))
Try a simple function of the 2
In [8]: x + y
Out[8]: array([10, 12, 14])
Since they have the same size, they can be summed (or otherwise combined) elementwise. The result has the same shape as the 2 inputs.
Now try 'broadcasting'. x[:,None] has shape (3,1)
In [9]: x[:,None] + y
Out[9]:
array([[10, 11, 12],
[11, 12, 13],
[12, 13, 14]])
The result is (3,3), the first 3 from the reshaped x, the second from y.
I can generate the pair of arrays with meshgrid:
In [10]: I,J = np.meshgrid(x,y,sparse=True, indexing='ij')
In [11]: I
Out[11]:
array([[0],
[1],
[2]])
In [12]: J
Out[12]: array([[10, 11, 12]])
In [13]: I + J
Out[13]:
array([[10, 11, 12],
[11, 12, 13],
[12, 13, 14]])
Note the added parameters in meshgrid. So that's how we go about generating 2d values from a pair of 1d arrays.
Now look at what sum does. As you use it in the function:
In [14]: np.sum(I + J)
Out[14]: 108
the result is a scalar. See the docs. If I specify an axis I get an array.
In [15]: np.sum(I + J, axis=0)
Out[15]: array([33, 36, 39])
If you gave V_func the right x and y, sum_list could be a 3d array. That axis-less sum reduces it to a scalar.
In code like this you need to keep track of array shapes. Include test prints if needed; don't just assume anything; test it. Pay attention to how dimensions grow and shrink as they pass through various operations.

In Python, construct cyclic subgroup from generator

Using addition in Z modulo 12, (a.k.a the integers mod 12, a.k.a 0 thru 11):
1 generates [0,1,2,3,4,5,6,7,8,9,10,11]
(starting at 0 and repeatedly adding 1; 11+1 takes us back to 0)
In the same way:
2 generates [0,2,4,6,8,10]
3 generates [0 3 6 9]
9 generates [0,9,6,3] <-- notice order is important
How can I create the subgroup given a particular generator?
I'm assuming you mean the additive subgroup Z * g where Z is the set of integers. If you want the precise order, just compute it:
def subgroup(n, g):
x = 0
while True:
yield x
x = (x + g) % n
if x == 0:
break
And of course if order is unimportant, the subgroup induced by g is
{ G * k for k in xrange((n - 1) // G + 1) }
for G = gcd(g, n).
You can create an generator that does what you're asking like this:
from itertools import imap, count
def subgroup(step, start=0, modulo=12):
yield start
for z in imap(lambda x: x%modulo, count(start+step, step)):
if z == start:
return
else:
yield z
Output:
>>> list(subgroup(9))
[0, 9, 6, 3]
>>> list(subgroup(3))
[0, 3, 6, 9]
>>> list(subgroup(2))
[0, 2, 4, 6, 8, 10]
It will keep generating the next item in the sequence until the start is repeated.

Iterating through multiple lists with same index position in python

I am new to python and I was just trying some list manipulations. I have three lists
A = [10,20,30,40,50,60]
B = [22,44,66,88,12,10]
C = [2,4,6,8,10,20]
I want to iterate over these three lists and for each value of C I want to add half of that value to the corresponding values of A and B.
For example for the 1st iteration -
half = 2/2= 1
So A = 10 + 1 and B = 22+1
So the final lists should look something like this
A = [11,22,33,44,55,70]
B = [23,46,69,92,17,20]
C = [2,4,6,8,10,20]
As long as the lists all have the same lengths, you can iterate with enumerate() function:
for i, n in enumerate(C):
A[i] += n/2
B[i] += n/2
>>> A
[11, 22, 33, 44, 55, 70]
>>> B
[23, 46, 69, 92, 17, 20]
>>> A, B = zip(*((a + c/2, b + c/2) for a, b, c in zip(A, B, C)))
ITs best to use Numpy arrays.
import numpy as np
A, B, C = map(np.array, [A, B, C])
A, B = A - C/2, B - C/2

Python: optimizing the product of a chain of factor-to-the-nth if n is not zero

I am trying to figure out a pythonic, descriptive way to multiply a list of numbers, raised to a corresponding number so long as the number is not zero. Here is a simple version of what I am doing, where I hard-coded a list of factors as [2, 3, 5]:
>>> import operator
>>> ## numbers could be written as lambda factor_list, power_list: [[factor_list[i]...
>>> numbers = lambda x, y, z: [[2, 3, 5][i] ** [x, y, z][i] for i in xrange(3)
if [x, y, z][i] != 0]
>>> product = lambda numbers: reduce(operator.mul, numbers, 1)
>>> numbers(1, 0, 0)
[2]
>>> product(numbers(1, 0, 0))
2
>>> numbers(1, 2, 3)
[2, 9, 125]
>>> product(numbers(1, 2, 3))
2250
I could have written this as a function with a for-loop which simply avoids any additional multiplication if the power value equals 0; e.g. if n !=0: product *= f ** n and loop as needed. I feel list comprehensions and lambda are there as a potentially better alternative.
This should be pythonic enough:
>>> from operator import mul
>>> base = [2, 3, 5]
>>> powers = [1, 0, 0]
>>> l = [n**p for n, p in zip(base, powers) if p != 0]
[2]
>>> reduce(mul, l, 1)
2
With generators:
>>> from itertools import izip
>>> powers = [1, 2, 3]
>>> numbers = (n**p for n, p in izip(base, powers) if p != 0)
>>> reduce(mul, numbers , 1)
2250

Categories