View difference between Paste ID: 5xy5Furg and HRs8YtLi
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))