SHOW:
|
|
- or go back to the newest paste.
| 1 | from itertools import* #reikalinga funkcijai starmap | |
| 2 | from math import* # to get pi | |
| 3 | from numbers import* #to solve equations with complex numbers | |
| 4 | #SKAICIU TEORIJA | |
| 5 | def primes(n, sieve=[False,False,True]): #by-need calculation of primes; not includes n | |
| 6 | #TEST1 | |
| 7 | #sieve: [1,1,1,1,1,1,1,1,1,1]=[1]*10 | |
| 8 | #possible primes [0,1,2,3,4,5,6,7,8,9] | |
| 9 | #given sieve [0,0,1,1,0] | |
| 10 | #a=3 | |
| 11 | #check from 0 to sqrt(len(sieve)) | |
| 12 | #last five entries were checked dividing by primes 0 to a=3 | |
| 13 | #sieve is given as list of bools to save memory | |
| 14 | #TEST2 | |
| 15 | #primes(20) returns [2, 3, 5, 7, 11, 13, 17, 19], sieve is [False, False, True] | |
| 16 | #after that primes(30) returns [2, 3, 5, 7, 11, 13, 17, 19, 23, 29], taken sieve is list of bools with len=20 | |
| 17 | #print sieve - get a primary sieve | |
| 18 | if len(sieve)<n: | |
| 19 | a=len(sieve) | |
| 20 | sieve+=[True]*(n-a) | |
| 21 | i=1 | |
| 22 | while i<=int((n-1)**0.5): | |
| 23 | i+=1 | |
| 24 | if sieve[i]: | |
| 25 | for j in range(max(2*i, a+(i-a)%i),n,i): sieve[j]=False | |
| 26 | return [i for i in range(n) if sieve[i]] | |
| 27 | from time import* | |
| 28 | def factor(num): | |
| 29 | product=[] | |
| 30 | t=time() | |
| 31 | if num==0: return 0 | |
| 32 | if num<0: return None | |
| 33 | for n in primes(int(num**0.5)+1): | |
| 34 | while num%n==0: | |
| 35 | if time()-t>2: break | |
| 36 | product.append(n) | |
| 37 | num/=n | |
| 38 | if num==1: break | |
| 39 | if num<>1: return product+[num] | |
| 40 | return product | |
| 41 | def divisors(num): | |
| 42 | if num<1: return None | |
| 43 | def multiply(array): | |
| 44 | k=1 | |
| 45 | for n in array: k*=n | |
| 46 | return k | |
| 47 | M=tuple(factor(num)) | |
| 48 | return list(map(lambda x: multiply(x), product(*[[n**i for i in range(M.count(n)+1)] for n in set(M)]))) | |
| 49 | #POLINOMU OPERACIJOS, kur a+bx+cx^2+...=[a,b,c...] | |
| 50 | def divide(P1,P2): | |
| 51 | residue=[] | |
| 52 | Pol=[n for n in P1] | |
| 53 | if len(P2)<2: return | |
| 54 | from time import* | |
| 55 | t=time() | |
| 56 | while len(P2)<=len(Pol): | |
| 57 | if time()-t>2: | |
| 58 | break | |
| 59 | print 'Serious error in polynomial division' | |
| 60 | coef=Pol[0]/float(P2[0]) | |
| 61 | residue.append(coef) | |
| 62 | del(Pol[0]) | |
| 63 | for i in range(len(P2)-1): | |
| 64 | - | def roots(P): |
| 64 | + | |
| 65 | - | #mains bugs: finds just integral roots - need quotients (use substitution of polynomial variable to count this) |
| 65 | + | |
| 66 | - | #need general algorhytm for quadratic and cubic polynomials |
| 66 | + | def roots(pol): |
| 67 | - | #possible liar result if roots not integral - abs(P[0]/P[-1]) is not always exact number |
| 67 | + | pol=[float(n) for n in pol] |
| 68 | - | if len(P)<2: return [] |
| 68 | + | deg=max([i for i in range(len(pol)) if pol[i]<>0]) |
| 69 | - | guess=divisors(abs(P[0]/P[-1])) |
| 69 | + | if deg==0: return None |
| 70 | - | guess+=[-n for n in guess] |
| 70 | + | elif deg==1: return [-pol[0]/pol[1]] |
| 71 | - | p=True |
| 71 | + | elif deg==2: |
| 72 | - | for test in guess: |
| 72 | + | a,b,c=pol[2],pol[1],pol[0] |
| 73 | - | M=divide(P,[-test,1]) |
| 73 | + | D=b*b-4*a*c |
| 74 | - | if M<>None: |
| 74 | + | if D<0: return [(-b-(0+1j)*(-D)**0.5)/(2*a), (-b+(0+1j)*(-D)**0.5)/(2*a)] |
| 75 | - | p=False |
| 75 | + | else: return [(-b-D**0.5)/(2*a), (-b+D**0.5)/(2*a)] |
| 76 | - | return [test]+roots(M) |
| 76 | + | #Given ax^3+bx^2+cx+d=0. Reduce to x^3+ax^2+bx+c=0. Substitute x=y-a/3. |
| 77 | - | if p==True: return [] |
| 77 | + | #Reduce to y^3+yp+q=0. Substitute y=z-p/3z. Got z^6+qz^3-p^3/27=0 |
| 78 | elif deg==3: #kinda mystics why half of solutions can be omitted | |
| 79 | a,b,c=pol[2]/pol[3],pol[1]/pol[3],pol[0]/pol[3] | |
| 80 | p,q=b-a*a/3, c+2*a*a*a/27-a*b/3 | |
| 81 | unity=[cos(2*pi*i/3)+sin(2*pi*i/3)*(0+1j) for i in range(3)] | |
| 82 | solve_z=(roots([-p*p*p/27, q, 1])[0]+0j)**(1./3) #solved for z | |
| 83 | zs=[solve_z*unity[i] for i in range(3)] | |
| 84 | ys=[z-p/(3*z) for z in zs] | |
| 85 | return [y-a/3 for y in ys] | |
| 86 | elif deg==4: #Reduce to y^4=py^2+qy+r | |
| 87 | a,b,c,d=pol[3]/pol[4],pol[2]/pol[4],pol[1]/pol[4], pol[0]/pol[4] | |
| 88 | p,q,r=3*a*a/8-b, a*b/2-a*a*a/8-c,3*a**4/256-a*a*b/16+a*c/4-d | |
| 89 | #print p,q,r, [4*p*r-q*q,8*r,4*p,8] | |
| 90 | D=roots([4*p*r-q*q,8*r,4*p,8]) #solving cubics for a constant :) | |
| 91 | if D[0].imag<D[1].imag: t=D[0].real | |
| 92 | else: t=D[1].real #choosing real root | |
| 93 | pre=((2*t+p+0j)**0.5).real | |
| 94 | return [x-a/4 for x in roots([t+pre*q/(2*(2*t+p)),pre,1])+roots([t-pre*q/(2*(2*t+p)),-pre,1])] | |
| 95 | else: | |
| 96 | print "I can't solve for big degrees cuz I don't know how to approximate complex roots efficiently" | |
| 97 | return None | |
| 98 | #MATRICU OPERACIJOS | |
| 99 | def div(a,b): #norim, kad nebutu stufo, tokio kaip 0.0, o butu vietoj to sveikieji | |
| 100 | if float(a)/b==a/b: return a/b | |
| 101 | return float(a)/b | |
| 102 | def gcd(*args): #rasime skaiciu DBD | |
| 103 | def gcd_of_two(a,b): | |
| 104 | a,b=abs(a),abs(b) | |
| 105 | while a>0: | |
| 106 | if b>a: a,b=b,a | |
| 107 | if a==1: return 1 | |
| 108 | a-=(a/b)*b | |
| 109 | return b | |
| 110 | return reduce(lambda x,y: gcd_of_two(x,y), args) | |
| 111 | def T(matrix): return zip(*matrix) #transponuota matrica | |
| 112 | def mul(*args): | |
| 113 | def simple_mul(matrix_a, matrix_b):#matricu daugyba | |
| 114 | if len(matrix_a[0])==len(matrix_b): return map(lambda x: tuple(sum(starmap(lambda j,k: k*j, zip(x,n))) for n in zip(*matrix_b)),matrix_a) | |
| 115 | return reduce(lambda x,y: simple_mul(x,y), args) | |
| 116 | def add(matrix_a, matrix_b, m1=1, m2=1): | |
| 117 | #sudetis m1*matrix_a+m2*matrix_b | |
| 118 | return [tuple(m1*matrix_a[i][j]+m2*matrix_b[i][j] for j in range(len(matrix_a[0]))) for i in range(len(matrix_a))] | |
| 119 | def scalmul(matrix,const): return [tuple(matrix[i][j]*const for j in range(len(matrix[0]))) for i in range(len(matrix))] #matrica dauginta is skaliaro | |
| 120 | def unit(length, diagonal=[]): | |
| 121 | if diagonal==[]: diagonal=[1]*length | |
| 122 | return [tuple(int(i==j)*diagonal[i] for i in range(length)) for j in range(length)] #vienetine matrica | |
| 123 | def inverse(matrix): #atvirkstines matricos algoritmas | |
| 124 | #EXAMPLE: [[a1,a2,x1,x2],[b1,b2,y1,y2]] ->[[a3,a4,a5,a6],[x3,x4,x5,x6]], nes tai ekvivalentu zingsniui | |
| 125 | # /a1 a2\|/1 0 x1 x2\ _______\ /1 0\|/a3 a4 a5 a6\ | |
| 126 | # \b1 b2/|\0 1 y1 y2/ / \0 1/|\x3 x4 x5 x6/ | |
| 127 | #rows can be longer than len of matrix; that case last terms means solutions to several systems of equations | |
| 128 | M=[[m for m in n] for n in matrix] #SIDE EFFECTS ARE ELIMINATED IN THIS ROW | |
| 129 | U=unit(len(M)) | |
| 130 | order=[(i,j) for i in range(len(M)-1) for j in range(i+1,len(M))]+[(i,j) for i in range(len(M)-1,0,-1) for j in range(i-1,-1,-1)] | |
| 131 | #eiluciu keitimo tvarka, kai reikia suvesti i trikampi, po to i diagolini pavidala | |
| 132 | for i in range(len(M)): | |
| 133 | U[i]=U[i]+tuple(M[i][len(matrix):len(M[0])]) | |
| 134 | #eiluciu sudejimo eiliskumas | |
| 135 | try: | |
| 136 | for n in order: | |
| 137 | i,j=n[0],n[1] | |
| 138 | if M[i][i]==0: # jei pasitaike nulinis elementas ant istrizaines, keiciame matricos eilutes. Jei neradome, ka sukeisti - nera atvirkstines matricos | |
| 139 | p=0 | |
| 140 | for k in range(i+1,len(M)): | |
| 141 | if M[k][i]<>0: | |
| 142 | M[i],M[k]=M[k],M[i] | |
| 143 | U[i],U[k]=U[k],U[i] | |
| 144 | p=1 | |
| 145 | break | |
| 146 | if p==0: return [M[i] for i in range(len(M)) if M[i][i]<>0] #bug we'll use later | |
| 147 | if M[j][i]<>0: #suvedimo i trikampi pavidala vienas zingsnis, kai uznulinama kazkuri eilute | |
| 148 | c=M[i][i]*M[j][i]/gcd(M[i][i], M[j][i]) | |
| 149 | c1,c2=c/M[i][i],c/M[j][i] | |
| 150 | M[j]=tuple(map(lambda x: x[1]*c1-x[0]*c2, zip(M[j],M[i]))) | |
| 151 | U[j]=tuple(map(lambda x: x[1]*c1-x[0]*c2, zip(U[j],U[i]))) | |
| 152 | return map(lambda i: tuple(map(lambda x: div(x, M[i][i]),U[i])), range(len(U))) | |
| 153 | except IndexError: print 'Nesiskaiciuoja inverse, per daug eiluciu matricoje' | |
| 154 | #pradine matrica pasikeite i matrica su skaiciais ant istrizaines; jos istrizaine normalizavus, graziname U reiksme | |
| 155 | def rank(M): #gudras metodas, kur klaidos atveju inverse funkcijoje grazinamas tiesiskai nepriklausomu eiluciu matrica | |
| 156 | if len(M)>len(M[0]): return len(inverse(T(M))) #transponuojam, nes inverse taikosi tik siuo atveju | |
| 157 | else: return len(inverse(M)) | |
| 158 | def det(matrix): #determinanto algoritmas - padaryta pagal inverse funkcija | |
| 159 | D=[] | |
| 160 | M=[[m for m in n] for n in matrix] | |
| 161 | - | def orthoappend(*args): |
| 161 | + | |
| 162 | - | #kas zingsni sprendziama sistema, kur like nezinomieji(kuriu kiekis yra defect) prilyginti 1 |
| 162 | + | |
| 163 | - | M=[list(n) for n in list(args)] |
| 163 | + | |
| 164 | - | defect=len(args[0])-len(M) |
| 164 | + | |
| 165 | - | while defect>0: |
| 165 | + | |
| 166 | - | N=[M[i][:-defect]+[-sum(M[i][-defect:])] for i in range(len(M))] |
| 166 | + | |
| 167 | - | M+=[list(solve_system(N)[0])+[1]*defect] |
| 167 | + | |
| 168 | - | defect-=1 |
| 168 | + | |
| 169 | - | return M |
| 169 | + | |
| 170 | break | |
| 171 | if p==0: return 0 | |
| 172 | if M[j][i]<>0: #suvedimo i trikampi pavidala vienas zingsnis, kai uznulinama kazkuri eilute | |
| 173 | c=M[i][i]*M[j][i]/gcd(M[i][i], M[j][i]) | |
| 174 | c1,c2=c/M[i][i],c/M[j][i] | |
| 175 | D.append(-c2) | |
| 176 | M[j]=tuple(map(lambda x: x[1]*c1-x[0]*c2, zip(M[j],M[i]))) | |
| 177 | if D<>[]: D=reduce(lambda x,y:x*y,D) | |
| 178 | else: D=1 | |
| 179 | return reduce(lambda x,y: x*y, map(lambda i: M[i][i], range(len(M))))/D | |
| 180 | def solve_system(matrix): return [list(n) for n in zip(*inverse(matrix))[len(matrix):]] | |
| 181 | def chr_pol(M): #charakteristinis daugianaris, rastas aprepianciuju minoru pagalba | |
| 182 | def minors(M,k): | |
| 183 | L=len(M) | |
| 184 | #first row is elements of matrix with connection of order=[(M[n],M[n]) for n in second_row] | |
| 185 | #second_row says cyclic permutations with len=k of the sequence with len=L | |
| 186 | return [[[M[i][j] for j in n] for i in n] for n in [[x%L for x in range(i,i+k)] for i in range(L)]] | |
| 187 | return [sum([det(n) for n in minors(M,k)])*(-1)**k for k in range(len(M),0,-1)]+[1] | |
| 188 | def eigenvalues(M): return roots(chr_pol(M)) |