I am a newbie to python and I came across some issues while I was working on Gaussian elimination using python. I got the error message:
IndexError: index 4 is out of bounds for axis 0 with size 4.
How should I correct it?
A = array( [[3,-1,-1,0,0,0],
[-1,4,-1,-1,0,0],
[0,0,-1,-1,4,-1],
[0,0,0,-1,-1,3]], float)
v = array([5,5,0,0,0,0],float)
N = len(v)
for m in range(N):
Div = A[m,m]
A[m,:]/= Div
v[m]/= Div
for i in range(m + 1, N):
mult= A[i,m]
A[i,:]-= mult*A[m,:]
v[i]-= mult*v[m]
x = empty(N,float)
for m in range(N-1,-1,-1):
x[m] = v[m]
for i in range(m + 1,N):
x[m]-= A[m,i]*x[i]
print(x)
It appears to me that you have a matrix of size 4x6, which means your indices for each dimension of your array go from 0 to 3 and 0 to 5 respectively.
Then you have a for loop going from 0 to range(N), where N is a length of a 6 element array. This is the loop with m as an iterator.
Finally, you have (what I assume is meant to be) an inner loop going from m+1 to N and you use that index in A for the rows:
for i in range(m + 1, N):
mult= A[i,m]
The variable i here will be going to N (which is 6 in this case) each time, but your A matrix can only go 0 to 3 there in the rows index.
In summary:
A is a 4x6 matrix
N is length 6
you are trying to access A[4,m] in the following loop (as well as A[5,m] and A[6,m]:
for i in range(m + 1, N):
mult= A[i,m]
when you can only at most reach A[3,m].
EDIT:
Actually, the error happens a little earlier than I mentioned previously:
for m in range(N):
Div = A[m,m]
Here, A[m,m] will not work for m > 4, but m in range(N) will take m to 5.
Related
A is a mn matrix
B is a nn matrix
I want to return matrix C of size m*n such that:
In python it could be like below
for i in range(m):
for j in range(n):
C[i][j] = 0
for k in range(n):
C[i][j] += max(0, A[i][j] - B[j][k])
this runs on O(m*n^2)
if A[i][j] - B[j][k] is always > 0 it could easily be improved as
C[i][j] = n*A[i][j] - sum(B[j])
but it is possible to improve as well when there are cases of A[i][j] - B[j][k]< 0 ? I think some divide and conquer algorithms might help here but I am not familiar with them.
For each j, You can sort each column B[j][:] and compute cumulative sums.
Then for a given A[i][j] you can find the sum of B[j][k] that are larger than A[i][j] in O(log n) time using binary search. If there's x elements of B[j][:] that are greater than A[i][j] and their sum is S, then C[i][j] = A[i][j] * x - S.
This gives you an overall O((m+n)n log n) time algorithm.
I would look on much simpler construct and go from there..
lets say the max between 0 and the addition wasn't there.
so the answer would be : a(i,j)n - sum(b(j,)
on this you could just go linearly by sum each vector and erase it from a(i,j)n
and because you need sum each vector in b only once per j it can be done in max(mn,nn)
now think about simple solution for the max problem...
if you would find which elements in b(j,) is bigger than a(i,j) you could just ignore their sum and substract their count from the multipication of a(i,j)
All of that can be done by ordering the vector b(j,) by size and make a summing array to each vector from the biggest to lowest (it can be done in nnlog(n) because you order each b(j,) vector once)
then you only need to binary search where is the a(i,j) in the ordered vector and take the sum you already found and subtract it from a(i,j) * the position you found in the binary search.
Eventually you'll get O( max( mnlog(n),nnlog(n) ) )
I got for you also the implementation:
import numpy as np
M = 4
N = 7
array = np.random.randint(100, size=(M,N))
array2 = np.random.randint(100, size=(N,N))
def matrixMacossoOperation(a,b, N, M):
cSlow = np.empty((M,N))
for i in range(M):
for j in range(N):
cSlow[i][j] = 0
for k in range(N):
cSlow[i][j] += max(0, a[i][j] - b[j][k])
for i in range(N):
b[i].sort()
sumArr = np.copy(b)
for j in range(N):
for i in range(N - 1):
sumArr[j][i + 1] += sumArr[j][i]
c = np.empty((M,N))
for i in range(M):
for j in range(N):
sumIndex = np.searchsorted(b[j],a[i][j])
if sumIndex == 0:
c[i][j] = 0;
else:
c[i][j] = ((sumIndex) * a[i][j]) - sumArr[j][sumIndex - 1]
print(c)
assert(np.array_equal(cSlow,c))
matrixMacossoOperation(array,array2,N,M)
I am trying to find the number of ways to construct an array such that consecutive positions contain different values.
Specifically, I need to construct an array with elements such that each element 1 between and k , all inclusive. I also want the first and last elements of the array to be 1 and x.
Complete problem statement:
Here is what I tried:
def countArray(n, k, x):
# Return the number of ways to fill in the array.
if x > k:
return 0
if x == 1:
return 0
def fact(n):
if n == 0:
return 1
fact_range = n+1
T = [1 for i in range(fact_range)]
for i in range(1,fact_range):
T[i] = i * T[i-1]
return T[fact_range-1]
ways = fact(k) / (fact(n-2)*fact(k-(n-2)))
return int(ways)
In short, I did K(C)N-2 to find the ways. How could I solve this?
It passes one of the base case with inputs as countArray(4,3,2) but fails for 16 other cases.
Let X(n) be the number of ways of constructing an array of length n, starting with 1 and ending in x (and not repeating any numbers). Let Y(n) be the number of ways of constructing an array of length n, starting with 1 and NOT ending in x (and not repeating any numbers).
Then there's these recurrence relations (for n>1)
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
In words: If you want an array of length n+1 ending in x, then you need an array of length n not ending in x. And if you want an array of length n+1 not ending in x, then you can either add any of the k-1 symbols to an array of length n ending in x, or you can take an array of length n not ending in x, and add any of the k-2 symbols that aren't x and don't repeat the last value.
For the base case, n=1, if x is 1 then X(1)=1, Y(1)=0 otherwise, X(1)=0, Y(1)=1
This gives you an O(n)-time method of computing the result.
def ways(n, k, x):
M = 10**9 + 7
wx = (x == 1)
wnx = (x != 1)
for _ in range(n-1):
wx, wnx = wnx, wx * (k-1) + wnx*(k-2)
wnx = wnx % M
return wx
print(ways(100, 5, 2))
In principle you can reduce this to O(log n) by expressing the recurrence relations as a matrix and computing the matrix power (mod M), but it's probably not necessary for the question.
[Additional working]
We have the recurrence relations:
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
Using the first, we can replace the Y(_) in the second with X(_+1) to reduce it down to a single variable. Then:
X(n+2) = X(n)*(k-1) + X(n+1)*(k-2)
Using standard techniques, we can solve this linear recurrence relation exactly.
In the case x!=1, we have:
X(n) = ((k-1)^(n-1) - (-1)^n) / k
And in the case x=1, we have:
X(n) = ((k-1)^(n-1) - (1-k)(-1)^n)/k
We can compute these mod M using Fermat's little theorem because M is prime. So 1/k = k^(M-2) mod M.
Thus we have (with a little bit of optimization) this short program that solves the problem and runs in O(log n) time:
def ways2(n, k, x):
S = -1 if n%2 else 1
return ((pow(k-1, n-1, M) + S) * pow(k, M-2, M) - S*(x==1)) % M
could you try this DP version: (it's passed all tests) (it's inspired by #PaulHankin and take DP approach - will run performance later to see what's diff for big matrix)
def countArray(n, k, x):
# Return the number of ways to fill in the array.
big_mod = 10 ** 9 + 7
dp = [[1], [1]]
if x == 1:
dp = [[1], [0]]
else:
dp = [[1], [1]]
for _ in range(n-2):
dp[0].append(dp[0][-1] * (k - 1) % big_mod)
dp[1].append((dp[0][-1] - dp[1][-1]) % big_mod)
return dp[1][-1]
So I have been trying to implement the quadratic sieve and I did step 1 which is(in code):
f = 44
b = ceil(sqrt(n))
factorBase = [i for i in genPrimes(f) if jacobi(n, i) == 1]
t = [modInverse(n, p) for p in factorBase]
sol1 = [(t[i] - b) % factorBase[i] for i in range(len(t))]
sol2 = [(-t[i] - b) % factorBase[i] for i in range(len(t))]
l = [ln(p) for p in factorBase]
size = 60
Here genPrimes() is Sieve of Eratosthenes, jacobi checks if n is quadratic residue mod i, and modInverse is Tonelli-Shanks algorithm.
The next step in the quadratic sieve is this:
Initialize a sieve array to 0's. For each odd prime p in the factor
base, add l[p] to the locations sol1[p] + ip and soln[p] + ip of the sieve array, for
i = 0, 1, 2,... For the prime p = 2, sieve only with sol1.
Or as explained here:
Then I have to add values from ππ to sieving array to positions π ππ1[π]+πβfactor_base[j] and
π ππ1[π]+πβ factor_base[j], where 0β€πβ€ size and 0β€πβ€|factor_base|. And for prime π=2 add ππ only to
positions with sol1.
Now say these were my lists:
sieveArray = [0 for i in range(60)]
factorBase = [2,3,7,17,23,29,37,41]
sol1 = [0,0,2,13,11,26,10,28]
sol2 = [0,1,5,14,8,10,17,26]
l = [0.69,1.1,1.95,2.83,3.14,3.37,3.61,3.71] # logs of factorbase rounded to 2 decimals
I should, following what was said above get this new list:
sieveArray = [1.79,1.1,2.64,1.1,1.79,1.95,1.79,1.1,3.83,3.05,8.77,3.14,3.74,3.93,3.52,1.1,3.74,3.61,1.79,3.0
5,0.69,1.1,1.79,1.95,1.79,1.1,9.72,1.1,5.5,0.0,6.57,7.07,0.69,3.05,4.93,0.0,1.79,3.05,0.69,4.47
,3.74,0.0,1.79,1.1,2.64,1.1,1.79,8.39,4.62,1.1,0.69,3.05,1.79,0.0,10.49,4.47,0.69,4.24,3.74,0.0]
However whenever I try to program I mess up horribly and index out of range errors. Here is my failed code:
for j in factorBase:
if j != 2:
for i in range(0, size):
try:
sieveArray[sol1[j] + (i * factorBase[j])] += l[j]
sieveArray[sol2[j] + (i * factorBase[j])] += l[j]
except:
continue
#Didn't implement case for 2 since I didn't know what I was doing.
Can someone please explain to me what I am doing wrong and how I can get expected results. Also If you want the actual explanation on what the step is go to https://pdfs.semanticscholar.org/5c52/8a975c1405bd35c65993abf5a4edb667c1db.pdf page 6(qs algorithm) step 2 or https://math.stackexchange.com/questions/183183/quadratic-sieve-algorithm?rq=1.
Error when there are no try-except statements:
sieveArray[sol1[j] + (i * factorBase[j])] += j
IndexError: list index out of range
Note: No Index Out of Range error because of the try-except but the code doesn't work properly at all still.
Given a target matrix size of N rows and M columns, is it possible to pick values such that all rows and columns sum to 1, on the condition that the matrix is not symmetric across the diagonal? Here's a target matrix I was able to generate when N==M (The problems arise when N!=M - see below):
[[0.08345877 0.12844672 0.90911941 0.41964704 0.57709569]
[0.53949086 0.07965491 0.62582134 0.48922244 0.38357809]
[0.80619328 0.27581426 0.31312973 0.26855717 0.4540732 ]
[0.11803505 0.88201276 0.1990759 0.2818701 0.63677383]
[0.57058968 0.75183898 0.07062126 0.6584709 0.06624682]]
I'm writing this in numpy. Currently I've written the following (brute force) code, which I know works when n==m. However, if n != m, rowwise and columwise sums don't converge to 0, and the ratio of rowwise sums to columwise sums converges to (n/m):
n,m = (5,4)
mat = np.random.random((n,m))
for i in range(100):
s0 = mat.sum(0)
s1 = mat.sum(1)[:,newaxis]
mat = (mat/s0)
mat = (mat/s1)
if i%10 == 0:
print(s0[0]/s1[0,0])
The final output in this case is 1.25 (I.e. n/m, or 5/4). I'm beginning to think this might not be mathematically possible. Can someone prove me wrong?
I suspect you are correct, the problem cannot be solved if N != M.
Take a 2x3 matrix as an example:
[[a b c]
[d e f]]
Assume that all rows and all columns sum to 1 and show a contradiction. The rows sum to 1 so:
a+b+c = 1
d+e+f = 1
This gives:
(a+b+c)+(d+e+f) = 1 + 1 = 2
Now look at the columns. Each column also sums to 1 so we have:
a+d = 1
b+e = 1
c+f = 1
Combining the three column equations gives:
(a+d)+(b+e)+(c+f) = 1 + 1 + 1 = 3
Since the sum of all six matrix elements cannot be both 2 and 3 simultaneously, 2 != 3, the initial assumption leads to a contradiction and so is disproved. More generally the problem cannot be solved for N != M with N rows and M columns.
The contradiction disappears when N = M for a square matrix.
Inputs:
k-> number of lists
m->modulo
Constraints
1<=k<=7
1<=M<=1000
1<=Magnitude of elements in list<=10*9
1<=Elements in each list<=7
`
This snippet of code is responsible for maximizing (x1^2 + x2^2 + ...) % m where x1, x2, ... are chosen from lists X1, X2, ...
k,m=map(int,input().split())
Sum=0
s=[]
for _ in range(k):
s.append(max(map(int,input().split())))
Sum+=int(s[_])**2
print(Sum%m)
So for instance if inputs are :
3 1000
2 5 4
3 7 8 9
5 5 7 8 9 10
The output would be 206, owing to selecting highest element in each list, square that element, take the sum and perform modulus operation using m
So, it would be (5^2+9^2+10^2)%1000=206
If I provide input like,
3 998
6 67828645 425092764 242723908 669696211 501122842 438815206
4 625649397 295060482 262686951 815352670
3 100876777 196900030 523615865
The expected output is 974, but I am getting 624
I would like to know how you would approach this problem or how to correct existing code.
You have to find max((sum of squares) modulo m). That's not the same as max(sum of squares) modulo m.
It may be that you find a sum of squares that's not in absolute terms as large as possible, but is maximum when you take it modulo m.
For example:
m=100
[10, 9],
[10, 5]
Here, the maximum sum of squares is 100 + 100 = 200, which is 0 modulo 100. The maximum (sum of squares modulo 100) is (81 + 100) = 182, which is 82 modulo 100.
Given that m is forced to be small, there's an fast dynamic programming solution that runs in O(m * N) time, where N is the total number of items in all the lists.
def solve(m, xxs):
r = [1] + [0] * (m - 1)
for xs in xxs:
s = [0] * m
for i in xrange(m):
for x in xs:
xx = (x * x) % m
s[i] += r[(i - xx) % m]
r = s
return max(i for i in xrange(m) if r[i])
m = 998
xxs = [
[67828645, 425092764, 242723908, 669696211, 501122842, 438815206],
[625649397, 295060482, 262686951, 815352670],
[100876777, 196900030, 523615865]]
print solve(m, xxs)
This outputs 974 as required.
One important logical problem here is you have to skip the number of items in each list while find the max element in your for loop. That is, instead of
Example,
6 67828645 425092764 242723908 669696211 501122842 438815206
and your data is
67828645 425092764 242723908 669696211 501122842 438815206
That is,
input().split()
You have to use,
input().split()[1:]
As pointed by Paul Hankin, you basically need to find max(sum of powers % m)
You have to find the combination from three lists whose sum%m is max.
So, this is basically,
You scan the input, split with space, leaving the first element which is the number of values in each line,you map them to integers. And then, you find the squares and append them to a list s. Having that you find the product(itertools module) Example - product([1,2],[3,4,5]) will give, [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)]. Now, you can find the sum of each such result % m and find the max value!
That is,
k,m=map(int,input().split())
from itertools import product
s=[]
for _ in range(k):
s.append(map(lambda x:x**2,map(int,input().split()[1:])))
print(max([sum(i)%m for i in product(*s)]))
Try it online!
This will give you the desired output!
Hope it helps!
Your question is not very clear. However, if I understand it correctly, you have lists of possible values for f(X1), ..., f(Xn) (probably obtained by applying f to all possible values for X1, ..., Xn), and you want to maximize f(X1)^2 + ... + f(Xn)^2 ?
If so, your code seems good, I get the same result:
lists = [[6, 67828645, 425092764, 242723908, 669696211, 501122842, 438815206],
[4, 625649397, 295060482, 262686951, 815352670],
[3, 100876777, 196900030, 523615865]]
sum = 0
for l in lists:
sum += max(l)**2
print(sum%998)
This print 624, just like your code. Where are you getting the 974 from ?
Not going to win any codegolf with this but here was my solution:
from functools import reduce
def get_input():
"""
gets input from stdin.
input format:
3 1000
2 5 4
3 7 8 9
5 5 7 8 9 10
"""
k, m = [int(i) for i in input().split()]
lists = []
for _ in range(k):
lists.append([int(i) for i in input().split()[1:]])
return m, k, lists
def maximise(m, k, lists):
"""
m is the number by which the sum of squares is modulo'd
k is the number of lists in the list of lists
lists is the list of lists containing vals to be sum of squared
maximise aims to maximise S for:
S = (f(x1) + f(x2)...+ f(xk)) % m
where:
f(x) = x**2
"""
max_value = reduce(lambda x,y: x+y**2, [max(l) for l in lists], 0)
# check whether the max sum of squares is greater than m
# if it is the answer has to be the max
if max_value < m:
print(max_value)
return
results = []
for product in cartesian_product(lists):
S = reduce(lambda x, y: x + y**2, product, 0) % m
if S == m-1:
print(S)
return
results.append(S)
print(max(results))
def cartesian_product(ll, accum=None):
"""
all combinations of lists made by combining one element from
each list in a list of lists (cartesian product)
"""
if not accum:
accum = []
for i in range(len(ll[0])):
if len(ll) == 1:
yield accum + [ll[0][i]]
else:
yield from cartesian_product(ll[1:], accum + [ll[0][i]])
if __name__ == "__main__":
maximise(*get_input())