How do I add one more loop to this? - python

Part of my code is:
list1 = zeros((x,y))
for j in range(1,y):
for i in range(1, x-1):
list1[i,j] = list1[i,j-1] + Equation
This works fine. However, when I want to get to the next stage, I need to modify the "Equation" part in the second for loop. Say the equation is (a*b+c)*d, I wish to make one of the parameters(a,b,c,d) varying with every increase in j.
That is, when j is 1, a = something. When j increases to 2, a changes according. It is like a is function of j. For example: a = A*cos(w*j).
My problem is, how do I loop this relation into the code so that a will be updated every time?

Just add an expression in the outer loop, calculating a based on the changing value of j:
for j in range(1, y):
a = A * cos(w * j)
for i in range(1, x-1):
list1[i, j] = list1[i, j - 1] + (a * b + c) * d

Related

How to save vector so it can be accessed further down the program?

I've been struggling trying to find a way I can store a vector so I can use it later. Here's my code:
while cota > RTOL:
for i in range (0, n + 1):
if i == 0:
u[i] = T_b - T_inf
elif 0 < i < n:
u[i] = (u[i + 1] + u[i - 1])/y
else:
u[i] = 0
The vector "u" changes with each iteration as the resulting vector from an iteration is the input for the next, however, in order to define the cut-off for the loop I need to be able to access both the current and previous iteration (the cut-off happens once a certain tolerance is reached and that requires being able to compare the current iteration to the previous one). In order to do this I've tried writing it onto a text file, but I'm wondering if there's a more elegant solution that somehow allows me to avoid that.
I recommend you remove the conditional from the loop,
and invent a new vector v to store results.
while cota > RTOL:
v = {} # Or a numpy array? Unclear from your example.
v[0] = T_b - T_inf
v[n] = 0
for i in range(1, n):
v[i] = (u[i + 1] + u[i - 1]) / y
Then do something useful with v, not sure what your use case is.
Perhaps you want to copy it on top of u for subsequent processing.
By using two separate vectors
you won't have to worry about u[i - 1] giving
a value you munged just a moment ago
on the previous loop iteration.

print the maximum value of x where x = |(A[i] – A[j]) + (i – j)|

️Problem asked in Directi Interview
Take an input array, say A and print the maximum value of x
where x = |(A[i] – A[j]) + (i – j)|
Constraints:
Max array size: 20000
Time limit: 0.1s
Time limit is a major factor in this question.
Here is the setter's solution for this question.
'''
THE BRUTE FORCE APPROACH
def maximum(arr):
res=0
n=len(arr)
for i in range (n):
for j in range(n):
res=max(res,abs(arr[i]-arr[j])+abs(i-j))
return res
'''
import sys
def maximum(arr):
max1=max2=-sys.maxsize-1
min1=min2=sys.maxsize
ans=0
n=len(arr)
for i in range(n):
max1=max(max1,arr[i]+i)
max2=max(max2,arr[i]-i)
min1=min(min1,arr[i]+i)
min2=min(min2,arr[i]-i)
ans=max(ans,max2-min2)
ans=max(ans,max1-min1)
return ans
But I tried solving the problem using sort
def maximum(array):
n=len(array)
array.sort()
return (array[n-1]-array[0]) + (n-1)
if __name__=="__main__":
n=int(input())
array= list(map(int,input("\nEnter the numbers : ").strip().split()))[:n]
print(maximum(array))
Is my approach correct ? Is it optimised?
Thanks in advance.
The answer suggested, of first sorting and taking the elements, is incorrect. Take the counter example of: [2,1,3]
The solution for this problem should yield 3: (3-1) + (2-1) or
(3-2) + (2-0)
However, suggested solution will yield 4: (3-1) + (2-0)
A possible (linear time) solution:
Let's start with some algebra, and drop the absolute value for a minute.
(A[i] – A[j]) + (i – j) = (A[i] + i) - (A[j] + j)
We are looking for maximal value, so
We want to minimize the value of (A[j] + j)
We want to maximize the value of (A[i] + i).
Note that they are completely independent of each other.
You can find two integers, one that maximizes (A[i] + i), and the other that minimizes (A[j] + j). Finding such 2 numbers can be done simply in linear pass.
Repeat for the other way around (when (A[i] – A[j]) + (i – j) is negative):
Find i that minimizes (A[i] + i)
Fine j that maximizes (A[j] + j).
Both are done in linear time, yielding O(n) solution
Sorting disturbs the original array and the mapping of elements at their respective indices gets lost. So logically, sorting will lead to wrong answer.
For example, as correctly described by #amit in his comments:
A = [2, 1, 3]
Correct answer = 3
Suggested solution's answer = 4

What do I get from Queue.get() (Python)

Overall question: How do I know what I am getting from a Queue object when I call Queue.get()? How do I sort it, or identify it? Can you get specific items from the Queue and leave others?
Context:
I wanted to learn a little about multi-proccessing (threading?) to make solving a matrix equation more efficient.
To illustrate, below is my working code for solving the matrix equation Ax = b without taking advantage of multiple cores. The solution is [1,1,1].
def jacobi(A, b, x_k):
N = len(x_k)
x_kp1 = np.copy(x_k)
E_rel = 1
iteration = 0
if (N != A.shape[0] or N != A.shape[1]):
raise ValueError('Matrix/vector dimensions do not match.')
while E_rel > ((10**(-14)) * (N**(1/2))):
for i in range(N):
sum = 0
for j in range(N):
if j != i:
sum = sum + A[i,j] * x_k[j]
x_kp1[i] =(1 / A[i,i]) * (b[i] - sum)
E_rel = 0
for n in range(N):
E_rel = E_rel + abs(x_kp1[n] - x_k[n]) / ((abs(x_kp1[n]) + abs(x_k[n])) / 2)
iteration += 1
# print("relative error for this iteration:", E_rel)
if iteration < 11:
print("iteration ", iteration, ":", x_kp1)
x_k = np.copy(x_kp1)
return x_kp1
if __name__ == '__main__':
A = np.matrix([[12.,7,3],[1,5,1],[2,7,-11]])
b = np.array([22.,7,-2])
x = np.array([1.,2,1])
print("Jacobi Method:")
x_1 = jacobi(A, b, x)
Ok, so I wanted to convert this code following this nice example: https://p16.praetorian.com/blog/multi-core-and-distributed-programming-in-python
So I got some code that runs and converges to the correct solution in the same number of iterations! That's really great, but what is the guarantee that this happens? It seems like Queue.get() just grabs whatever result from whatever process finished first (or last?). I was actually very surprised when my code ran, as I expected
for i in range(N):
x_update[i] = q.get(True)
to jumble up the elements of the vector.
Here is my code updated using the multi-processing library:
import numpy as np
import multiprocessing as mu
np.set_printoptions(precision=15)
def Jacobi_step(index, initial_vector, q):
N = len(initial_vector)
sum = 0
for j in range(N):
if j != i:
sum = sum + A[i, j] * initial_vector[j]
# this result is the updated element at given index of our solution vector.
q.put((1 / A[index, index]) * (b[index] - sum))
if __name__ == '__main__':
A = np.matrix([[12.,7,3],[1,5,1],[2,7,-11]])
b = np.array([22.,7,-2])
x = np.array([1.,2,1])
q = mu.Queue()
N = len(x)
x_update = np.copy(x)
p = []
error = 1
iteration = 0
while error > ((10**(-14)) * (N**(1/2))):
# assign a process to each element in the vector x,
# update one element with a single Jacobi step
for i in range(N):
process = mu.Process(target=Jacobi_step(i, x, q))
p.append(process)
process.start()
# fill in the updated vector with each new element aquired by the last step
for i in range(N):
x_update[i] = q.get(True)
# check for convergence
error = 0
for n in range(N):
error = error + abs(x_update[n] - x[n]) / ((abs(x_update[n]) + abs(x[n])) / 2)
p[i].join()
x = np.copy(x_update)
iteration += 1
print("iteration ", iteration, ":", x)
del p[:]
A Queue is first-in-first-out which means the first element inserted is the first element retrieved, in order of insertion.
Since you have no way to control that, I suggest you insert tuples in the Queue, containing the value and some identifying object that can be used to sort/relate to the original computation.
result = (1 / A[index, index]) * (b[index] - sum)
q.put((index, result))
This example puts the index in the Queue together with the result, so that when you .get() later you get the index too and use it to know which computation this is for:
i, x_i = q.get(True)
x_update[i] = x_i
Or something like that.

Efficiency when adding values from two lists

I'm trying to learn algorithms by writing a python application that tests out Fermat's last theorem. It iterates all combinations of a^n + b^n = c^n Where a/b hit a ceiling at 10000 and n hits a ceiling at 100. I realize I won't get any hits, but it's just a bit of fun. Anyway, the specifics don't really matter.
What it boils down to is a + b where a and b iterate all combinations 1 to 10000. But here's the problem: 4 + 5 is exactly the same as 5 + 4. So my program is doing twice the work it needs to do. How can I iterate these combinations while skipping over mirrored inputs?
base_ceiling = 10000 # max values for a and b
n_ceiling = 100 # max value for power of n
powers = []
for i in range(n_ceiling):
jarr = []
for j in range(base_ceiling):
jarr.append(j ** i)
powers.append(jarr)
for k in range(3, n_ceiling):
for i in range(1, base_ceiling):
for j in range(1, base_ceiling):
pow_vals = powers[k]
a = powers[k][i]
b = powers[k][j]
c = a + b
try:
idx = pow_vals.index(c)
if idx > -1:
print k, ": ", i, j, "=", idx, " results in ", a, b, "=", c
except ValueError:
continue
It's as simple as using for j in range(i, base_ceiling). This works because it will start from i instead of 1, so it doesn't repeat anything less than i. You could use i + 1 instead, because i^n + i^n will never be a power of n.

Not sure how to integrate negative number function in data generating algorithm?

I’m having a bit of trouble controlling the results from a data generating algorithm I am working on. Basically it takes values from a list and then lists all the different combinations to get to a specific sum. So far the code works fine(haven’t tested scaling it with many variables yet), but I need to allow for negative numbers to be include in the list.
The way I think I can solve this problem is to put a collar on the possible results as to prevent infinity results(if apples is 2 and oranges are -1 then for any sum, there will be an infinite solutions but if I say there is a limit of either then it cannot go on forever.)
So Here's super basic code that detects weights:
import math
data = [-2, 10,5,50,20,25,40]
target_sum = 100
max_percent = .8 #no value can exceed 80% of total(this is to prevent infinite solutions
for node in data:
max_value = abs(math.floor((target_sum * max_percent)/node))
print node, "'s max value is ", max_value
Here's the code that generates the results(first function generates a table if its possible and the second function composes the actual results. Details/pseudo code of the algo is here: Can brute force algorithms scale? ):
from collections import defaultdict
data = [-2, 10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool) # all values are False by default
T[0, 0] = True # base case
for i, x in enumerate(data): # i is index, x is data[i]
for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
for c in range(s / x + 1):
if T[s - c * x, i]:
T[s, i+1] = True
coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
# /* Base case: If we've assigned all the variables correctly, list this
# * solution.
# */
if k == 0:
# print what we have so far
print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
return
x_k = data[k-1]
# /* Recursive step: Try all coefficients, but only if they work. */
for c in range(sum // x_k + 1):
if T[sum - c * x_k, k - 1]:
# mark the coefficient of x_k to be c
coeff[k-1] = c
RecursivelyListAllThatWork(k - 1, sum - c * x_k)
# unmark the coefficient of x_k
coeff[k-1] = 0
RecursivelyListAllThatWork(len(data), target_sum)
My problem is, I don't know where/how to integrate my limiting code to the main code inorder to restrict results and allow for negative numbers. When I add a negative number to the list, it displays it but does not include it in the output. I think this is due to it not being added to the table(first function) and I'm not sure how to have it added(and still keep the programs structure so I can scale it with more variables).
Thanks in advance and if anything is unclear please let me know.
edit: a bit unrelated(and if detracts from the question just ignore, but since your looking at the code already, is there a way I can utilize both cpus on my machine with this code? Right now when I run it, it only uses one cpu. I know the technical method of parallel computing in python but not sure how to logically parallelize this algo)
You can restrict results by changing both loops over c from
for c in range(s / x + 1):
to
max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):
This will ensure that any coefficient in the final answer will be an integer in the range 0 to max_value inclusive.
A simple way of adding negative values is to change the loop over s from
for s in range(target_sum + 1):
to
R=200 # Maximum size of any partial sum
for s in range(-R,R+1):
Note that if you do it this way then your solution will have an additional constraint.
The new constraint is that the absolute value of every partial weighted sum must be <=R.
(You can make R large to avoid this constraint reducing the number of solutions, but this will slow down execution.)
The complete code looks like:
from collections import defaultdict
data = [-2,10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool) # all values are False by default
T[0, 0] = True # base case
R=200 # Maximum size of any partial sum
max_percent=0.8 # Maximum weight of any term
for i, x in enumerate(data): # i is index, x is data[i]
for s in range(-R,R+1): #set the range of one higher than sum to include sum itself
max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):
if T[s - c * x, i]:
T[s, i+1] = True
coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
# /* Base case: If we've assigned all the variables correctly, list this
# * solution.
# */
if k == 0:
# print what we have so far
print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
return
x_k = data[k-1]
# /* Recursive step: Try all coefficients, but only if they work. */
max_value = int(abs((target_sum * max_percent)/x_k))
for c in range(max_value + 1):
if T[sum - c * x_k, k - 1]:
# mark the coefficient of x_k to be c
coeff[k-1] = c
RecursivelyListAllThatWork(k - 1, sum - c * x_k)
# unmark the coefficient of x_k
coeff[k-1] = 0
RecursivelyListAllThatWork(len(data), target_sum)

Categories