-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTANMLP.py
1581 lines (1452 loc) · 52.8 KB
/
TANMLP.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -*- coding: utf-8 -*-
from sympy import *
from itertools import *
#-----------------------------HEXADECIMAL Y DECIMAL--------------------------------------
def elemento(hexastring,i):
if i<len(hexastring):
n=(hexastring[i])
if n=='1' or n=='2' or n=='3' or n=='4' or n=='5' or n=='6' or n=='7' or n=='8' or n=='9' or n=='0':
return n
elif n=='a':
return 10
elif n=='b':
return 11
elif n=='c':
return 12
elif n=='d':
return 13
elif n=='e':
return 14
elif n=='f':
return 15
else: print 'Elige una posición válida del string'
def hextodec_it(hexastring):
n=0
for i in range(0,len(hexastring)):
n=n+int(elemento(hexastring,i))*(16**(len(hexastring)-i-1))
return n
def hexadec(n):
if n==1 or n==2 or n==3 or n==4 or n==5 or n==6 or n==7 or n==8 or n==9 or n==0:
return str(n)
elif n==10:
return 'a'
elif n==11:
return 'b'
elif n==12:
return 'c'
elif n==13:
return 'd'
elif n==14:
return 'e'
elif n==15:
return 'f'
def dectohex(entero):
i=1
hexa1=''
while entero/16>0:
hexa=hexadec(entero%16)
entero=entero/16
i=i+1
hexa1=hexa+hexa1
hexa1=hexadec(entero)+hexa1
return hexa1
def lista_palabras(mensaje):
j=0
lista=[]
for i in range(0,len(mensaje)):
if mensaje[i]==' ':
lista=lista+[str(mensaje[j:i])]
j=i+1
if i==len(mensaje)-1:
lista=lista+[str(mensaje[j:i+1])]
return lista
def str_to_hexalist(mensaje):
lista=lista_palabras(mensaje)
for i in range(0,len(lista)):
lista[i]=lista[i].encode('hex')
return lista
def hexalist_to_str(lista):
mensaje=''
for i in range(0,len(lista)):
if i==len(lista)-1:
mensaje=mensaje+lista[i].decode('hex')
else:
mensaje=mensaje+lista[i].decode('hex')+' '
return mensaje
def hexalist_to_dec(lista):
for i in range(0,len(lista)):
lista[i]=hextodec_it(lista[i])
return lista
def declist_to_hex(lista):
for i in range(0,len(lista)):
lista[i]=dectohex(int(lista[i]))
return lista
#--------------------------------CRIPTOGRAFÍA--------------------------------------------
#Para codificar afín
def cod_afin(mensaje,a,b,n):
hexalista=str_to_hexalist(mensaje)
declista=hexalist_to_dec(hexalista)
for i in range(0,len(declista)):
declista[i]=((declista[i]*a)+b)%n
return declista
#Para decodificar afín
def deco_afin(declista,a,b,n):
a_inv=gcdex(a%n,n)[0]
for i in range(0,len(declista)):
declista[i]=((declista[i]-b)*a_inv)%n
hexlista=declist_to_hex(declista)
mensaje=hexalist_to_str(hexlista)
return mensaje
#Para codificar RSA
def cod_rsa(mensaje,e,n):
hexalista=str_to_hexalist(mensaje)
declista=hexalist_to_dec(hexalista)
for i in range(0,len(declista)):
declista[i]=pow(declista[i],e,n)
return declista
#Para decodificar RSA
def deco_rsa(declista,e,p,q):
n=p*q
phi=(p-1)*(q-1)
u=gcdex(e,phi)[0]
u=u%phi
for i in range(0,len(declista)):
declista[i]=pow(declista[i],int(u),n)
hexlista=declist_to_hex(declista)
mensaje=hexalist_to_str(hexlista)
return mensaje
#---------------------------------FACTOR BASE---------------------------------------------
def baseprim(b):
#Hacemos una lista con el -1 y los primeros 'b' primos
base=[-1]
for i in range(1,b+1):
base.append(prime(i))
return base
def abmod(x,n):
#Definimos x1 como el resto de x dividido por n
x1=x%n
#Comprobamos si x1 es menor o igual que (n/2)
if x1<=(n/2):
#Si cumple la condición devolvemos x1
return x1
else:
#Si no la cumple devolvemos x1-n
return x1-n
def mayorpot(p,m):
#Comprobamos si p es -1
if p==-1:
if m<0:
return 1
else:
return 0
#Quitamos casos triviales
if p==0:
return "Es una trivialidad preguntarse cual es la mayor potencia de 0 que divide a m"
if p==1:
return 1
#Comprobamos si p divide a m
if m%p!=0:
return 0
#Si p divide a m usamos de variable auxiliar a, con la cual iremos haciendo las potencias de p
#Y comprobar hasta que potencia se divide a m, usamos i como variable auxiliar para ver el exponente de la potencia
else:
i=1
a=p
while m%(a*p)==0:
i=i+1
a=a*p
#Devuelve el exponente de la mayor potencia que divide a m
return i
def bnumer(b,base,n):
#Hacemos la b^2 mod n con nuestra función abmod
#Llamamos b1 a ese número
b1=abmod(b**2,n)
#Hacemos la mayor potencia de los primos que divida a este número
#Y los vamos multiplicando en la variable prod
prod=1
for i in range(0,len(base)):
#Llamamos x a la mayor potencia
x=base[i]**mayorpot(base[i],b1)
prod=prod*x
#Comprobamos si el producto es el número b
if prod==b1:
return true
else:
return false
def vec_alfa(b,base,n):
#Comprueba si b es un b-numero
if bnumer(b,base,n)==false:
return
else:
#Definimos el vector alfa como los exponentes asociados al bnumero en la base
vecalfa=[]
#Definimos b1 como b^2 mod n con nuestra función abmod
b1=b1=abmod(b**2,n)
for i in range(0,len(base)):
vecalfa=vecalfa+[mayorpot(base[i],b1)]
return vecalfa
def parp(lista):
#Devolvemos true si todos los elementos de la lista son pares, en otro caso false.
for i in range(0,len(lista)):
if lista[i]%2!=0:
return false
return true
def ssuma(lista1,lista2):
#Sumamos elemento a elemento dos listas
if len(lista1)!=len(lista2):
print 'No tienen la misma dimensión las dos listas'
return
#Definimos la lista en la que vamos a sumar estas dos
listsuma=[]
for i in range(0,len(lista1)):
listsuma=listsuma+[lista1[i]+lista2[i]]
return listsuma
def aux(k,r):
#Lista con el número total de elementos r
lista=range(0,r)
#Lista de listas con las posibles combinaciones de elementos de lista tomados de k en k
aux=list(combinations(lista, k))
return aux
def ssuman(lista):
#Sumar n listas, que son los elementos de una lista.
suma=lista[0]
for i in range(1,len(lista)):
suma=ssuma(suma,lista[i])
return suma
def suma(lista,k):
r=len(lista)
#lista es una lista de listas
#comprobamos que la longitud de la lista sea mayor que k
if len(lista)<=k:
return
#definimos la salida de la función que es una lista con todas las ssumas de k en k
aux1=aux(k,r)
m=factorial(r)/(factorial(k)*factorial(r-k))
lista1=[[]]
for i in range(0,m):
if i>0:
lista1.append([])
for j in aux1[i]:
if j==aux1[i][0]:
lista1[i]=lista1[i]+lista[j]
elif j==aux1[i][1]:
lista1[i]=[lista1[i]]+[lista[j]]
else:
lista1[i]=lista1[i]+[lista[j]]
lista2=[]
for i in range(0,m):
lista2.append(ssuman(lista1[i]))
return lista2
def bi(n,k,i,base):
#Definimos la lista L1
L1=[]
for l in range(1,k+1):
L1=L1+[floor(sqrt(l*n))]
#Definimos la lista L2
L2=[]
for l in range(0,len(L1)):
for j in range(0,i):
L2=L2+[L1[l]+j]
#Seleccionamos aquellos números de L2 que sean B-números
BN=[]
for l in range(0,len(L2)):
if bnumer(L2[l],base,n)==true:
BN=BN+[L2[l]]
return BN
#También devolvemos True o False para saber si hemos podido resolver la ecuación
def soleq(n,h,k,i):
#Definimos n1 y bp como los valores de n y h
n1=n
bp=h
#Definimos la base con los primeros primos
B=baseprim(bp)
#NOs quedamos con los B-números
BN=bi(n1,k,i,B)
#Construimos la lista de los alfa vectores asociados a estos B-números
alfavec=[]
for i in range(0,len(BN)):
alfavec.append(vec_alfa(BN[i],B,n1))
#Elegimos como j el número de alfa vectores que queremos sumar lo empezamos en 1 y lo podemos ir
#subiendo hasta que consigamos una solución no trivial
#j tiene que ser 1 o mayor
#Cuando j es 1 vamos a mirar si hay alfavectores pares y luego comprobaremos uno a uno si dan soluciones
#Cuando j es mayor que 1 iremos comprobando 1 a 1 si dan solución.
#Usamos i_0 como contador para saber por qué valor de j vamos comprobando
#Usamos i_1 como contador para saber dentro de cada valor de j, por qué combinación de alfavectores pares vamos
i_0=1
i_1=0
for j in range(i_0,len(alfavec)):
sumajpar=[]
in_a=[]
if j==1:
for i in range(0,len(alfavec)):
if parp(alfavec[i])==true:
#Si encontramos un alfavector par, lo guardamos éste y su posición
sumajpar.append(alfavec[i])
in_a.append(i)
#Comprobamos con cada alfavector par
for l in range(0,len(in_a)):
eles_a=in_a
#Calculamos t
t=1
t=(t*BN[eles_a[l]])%n
p=[]
e=[]
for i in range (0,len(sumajpar)):
if sumajpar[l][i]!=0:
p.append(B[i])
e.append(sumajpar[l][i]/2)
#Calculamos s
s=1
for i in range(0,len(p)):
s=(s*pow(p[i],e[i],n))%n
#Comprobamos que sea una solución no trivial
if gcd(s+t,n)!=1:
return[true,(t,s)]
#Entramos en este if si no hay ningun alfavector par y tenemos que probar con sumas (j mayor que 1)
if sumajpar==[]:
in_a=0
while sumajpar==[]:
i_1=0
j=j+1
#Ponemos una condición de parada que es que j llegue a 15,
#o si el j es mayor que la longitud de alfavec, no podemos hacer las sumas
if j>=len(alfavec) or j==15:
return [false,"No hemos resuelto la ecuación"]
#Lista con todas las sumas de j en j de alfavectores
sumaj=suma(alfavec,j)
for i in range(i_1,len(sumaj)):
#Comprobamos una a una si la suma de alfavectores es par
if parp(sumaj[i])==true:
#Si es par procedemos a comprobar si da solución
sumajpar=sumaj[i]
in_a=i
i_0=j
i_1=i
#Vemos cual es la combinación que se ha sumado para obtener el par
eles_a =aux(j,len(BN))
#Calculamos t
t=1
for i in range(0,len(eles_a[in_a])):
t=(t*BN[eles_a[in_a][i]])%n
p=[]
e=[]
for i in range (0,len(sumajpar)):
if sumajpar[i]!=0:
p.append(B[i])
e.append(sumajpar[i]/2)
#Calculamos s
s=1
for i in range(0,len(p)):
s=(s*pow(int(p[i]),int(e[i]),int(n)))%n
#Comprobamos que sea una solución no trivial
if gcd(s+t,n)!=1 and gcd(s-t,n)!=1:
return[true,(t,s)]
return [false]
def fac(n,h):
n1=n
h1=h
i=5
k=5
factorizacion=true
sol=soleq(n1,h1,k,i)
if sol[0]==true:
s=sol[1][0]
t=sol[1][1]
else:
while sol[0]==false:
k=k+5
i=i+5
sol=soleq(n1,h1,k,i)
if sol[0]==true:
s=sol[1][0]
t=sol[1][1]
if i==100:
factorizacion=false
break
if factorizacion==false:
print 'Peligro de bucle infinito, elige otro h'
else:
return (gcd(s+t,n),n/gcd(s+t,n))
#Esta función asignará la base según los Pbs
def elecbase(Pbs):
#Lista de los Pbs
Pbs1=Pbs
#Ceamos una lista donde guardar la factorización de todos los b números
factorb=[]
#Inicializamos nuestra lista B
B=[-1]
#Lista que usaremos de apoyo para construir la B, guardaremos en ella los números que no se repitan
#en las factorizaciones, junto al número de los Pbs del cual es factor.
Baux=[]
#Guardamos las factorizaciones de los números en factorb, junto a la posición del número
#al cual corresponde la factorización en Pbs
for i in range(0,len(Pbs1)):
factorb.append([list(factorint(Pbs1[i])),i])
#Bucles anidados en los cuales compararemos los factores de los números de Pbs para guardar directamente
#en B los que se repitan dos o más veces y los que salga sólo una vez los guardaremos en Baux
#Para comprobar a continuación si tienen exponente par en la factorización del número del cual es factor
#usamos a como variable booleana para comprobar que no metemos dos veces el mismo valor en B
#b también será una variable booleana y esta llevará os indicará cuando un número sólo sale una vez
for i in range(0,len(factorb)):
for j in range(0,len(factorb[i][0])):
b=false
for k in range(i+1,len(factorb)):
for l in range(0,len(factorb[k][0])):
a=false
if factorb[i][0][j]==factorb[k][0][l]:
b=true
for m in range(0,len(B)):
if(factorb[i][0][j]==B[m]):
a=true
if a==false:
B.append(factorb[i][0][j])
for m in range(0,len(B)):
if(factorb[i][0][j]==B[m]):
b=true
if b==false:
Baux.append([factorb[i][0][j],i])
#Comprobamos si tienen exponente par los almacenados en Baux para añadirlos a B
for i in range(0,len(Baux)):
if mayorpot(Baux[i][0],Pbs1[Baux[i][1]])%2==0:
B.append(Baux[i][0])
return B
#Función para ordenar una lista
def orden1(list):
for i in range(1,len(list)):
for j in range(0,len(list)-1):
if(list[j] > list[j+1]):
k = list[j+1]
list[j+1] = list[j]
list[j] = k;
return list
def soleqfc(n,s):
#Definimos n1 y bp como los valores de n y h
n1=n
F = continued_fraction_periodic(0,1,n)
L1= [F[0]]+F[1]
if s<=len(L1):
L2=list(continued_fraction_convergents(L1[:s]))
elif s>len(L1):
return [false,"No se ha podido factorizar el numero con este s, tienes que elegir un s mas pequeño"]
Pbs=[]
for i in range(0,len(L2)):
Pbs.append(fraction(L2[i])[0])
B=elecbase(Pbs)
B=orden1(B)
#Elegimos el k y el i y ponemos una condición para terminar el programa
sol=false
k1=0
i1=0
while sol==false:
#En cada iteración vamos aumentando los valores de k y de i
k1=k1+10
i1=i1+10
#Nos quedamos con los B-números
BN=bi(n1,k1,i1,B)
#Construimos la lista de los alfa vectores asociados a estos B-números
alfavec=[]
for i in range(0,len(BN)):
alfavec.append(vec_alfa(BN[i],B,n1))
#Hacemos un algoritmo análogo al de la función soleq
i_0=1
i_1=0
for j in range(i_0,len(alfavec)):
sumajpar=[]
in_a=[]
if j==1:
#Comprobamos si hay alfavectores pares
for i in range(0,len(alfavec)):
if parp(alfavec[i])==true:
sumajpar.append(alfavec[i])
in_a.append(i)
#Comprobamos si los alfavectores pares dan solución
for l in range(0,len(in_a)):
eles_a=in_a
#Calculamos t
t=1
t=(t*BN[eles_a[l]])%n
p=[]
e=[]
for i in range (0,len(sumajpar)):
if sumajpar[l][i]!=0:
p.append(B[i])
e.append(sumajpar[l][i]/2)
#Calculamos s
s=1
for i in range(0,len(p)):
s=(s*pow(p[i],e[i],n))%n
#Comprobamos que sea una solución no trivial
if gcd(s+t,n)!=1:
return[true,(t,s)]
#Comprobamos si hay sumas pares de alfavectores
if sumajpar==[]:
in_a=0
while sumajpar==[]:
i_1=0
j=j+1
if j>=len(alfavec) or j==15:
break
#Condición para no hacer un bucle infinito
elif k==100:
return [false]
sumaj=suma(alfavec,j)
for i in range(i_1,len(sumaj)):
if parp(sumaj[i])==true:
sumajpar=sumaj[i]
in_a=i
i_0=j
i_1=i
#Vemos que combinación da lugar al vector par
eles_a =aux(j,len(BN))
#calculamos t
t=1
for i in range(0,len(eles_a[in_a])):
t=(t*BN[eles_a[in_a][i]])%n
p=[]
e=[]
for i in range (0,len(sumajpar)):
if sumajpar[i]!=0:
p.append(B[i])
e.append(sumajpar[i]/2)
#Calculamos s
s=1
for i in range(0,len(p)):
s=(s*pow(int(p[i]),int(e[i]),int(n)))%n
#Comprobamos que sea una solución no trivial
if gcd(s+t,n)!=1 and gcd(s-t,n)!=1:
return[true,(t,s)]
return [false]
def facfc(n):
n1=n
#Damos un valor de s y un valor máximo de s por defecto, se podrá modificar según el problema al que nos enfrentemos
s=6
#Comprobamos si conseguimos factorizar el número para el s dado
sol=soleqfc(n1,s)
print sol
if sol[0]==true:
q=sol[1][0]
t=sol[1][1]
else:
while sol[0]==false:
#Vamos ejecutando el método para cada valor de s hasta conseguir solución
sol=soleqfc(n1,s)
if sol[0]==true:
q=sol[1][0]
t=sol[1][1]
#Aumentamos el número s
s=s+3
#Condición sobre un s máximo para no hacer un bucle infinito
if s>45:
return "No hemos podido factorizar el numero"
#Devolvemos la factorización
return (gcd(q+t,n),n/gcd(q+t,n))
#-------------------------FACTORIZACIÓN EN DOMINIOS EUCLÍDEOS (d negativo)-----------------------------
def norma(alpha):
#Función para calcular la norma de un elemento alpha
norma=simplify(alpha*alpha.conjugate())
return norma
def traza(alpha):
#Función para calcular la traza de un elemento alpha
traza=simplify(alpha+alpha.conjugate())
return traza
def es_entero(alpha):
#Comprobamos si el elemento alpha es entero algebraico o no
norm=norma(alpha)
traz=traza(alpha)
#Comprobamos si la norma y la traza son enteras
if ask(Q.integer(traz))and ask(Q.integer(norm)):
return true
else:
return false
def xy(alpha,d):
#Extraemos las coordenadas de alpha en Q(sqrt(d))
x=(alpha+alpha.conjugate())/2
y=(alpha-alpha.conjugate())/(2*sqrt(d))
return(x,y)
def ab(alpha,d):
#Comprobamos si alpha es entero, si lo es calculamos sus coordenadas en una base entera
if es_entero(alpha)==true:
if d==-1 or d==-2:
e=sqrt(d)
a=(alpha+alpha.conjugate())/2
b=(alpha-alpha.conjugate())/(2*sqrt(d))
elif d==-3 or d==-7 or d==-11:
e=Rational(1,2)+sqrt(d)*Rational(1,2)
coord=xy(alpha,d)
x_1=coord[0]*2
y_1=coord[1]*2
a=(x_1-y_1)/2
b=y_1
else:
return "Introduzca un dominio euclideo"
return(a,b)
else:
return"Introduzca un entero algebraico"
def divide(alpha,beta,d):
#Comprobamos si alpha divide a beta, para ello vemos multiplicando por el conjugado si la fracción es un entero
num=expand(simplify(beta*alpha.conjugate()))
norm=norma(alpha)
coord=xy(num,d)
division=Rational(coord[0],norm)+Rational(coord[1],norm)*sqrt(d)
return es_entero(division)
def cociente(alpha,beta,d):
#Si alpha divide a beta calculamos su cociente
if divide(alpha,beta,d)!=true:
return false
division=simplify(beta*alpha.conjugate())/norma(alpha)
return division
def eqpell(n,d):
#Resolución de la ecuación de Pell con d negativo
sol=[]
if d>=0:
return "Introduce un d negativo"
ymax=sqrt(n/-d)
for y in range(0,ymax+1):
x=n+d*(y**2)
x=sqrt(x)
if ask(Q.integer(x)):
if y==0:
sol.append((x,y))
sol.append((-x,y))
elif x==0:
sol.append((x,y))
sol.append((x,-y))
else:
sol.append((x,y))
sol.append((-x,y))
sol.append((x,-y))
sol.append((-x,-y))
return sol
def connorma(n,d):
#Calculamos los elementos con norma n en O
elementos=[]
if d%4!=1:
sol=eqpell(n,d)
for i in range (0,len(sol)):
a=sol[i][0]+sol[i][1]*sqrt(d)
elementos.append(a)
return elementos
else:
sol=eqpell(4*n,d)
for i in range (0,len(sol)):
x=sol[i][0]
y=sol[i][1]
if((x-y)%2==0):
a=Rational(x,2)+Rational(y,2)*sqrt(d)
elementos.append(a)
return elementos
def es_unidad(alpha):
#Comprobamos si alpha es unidad
if es_entero(alpha)==false:
print "No es entero algebraico alpha"
return false
if norma(alpha)==1:
return true
else:
return false
def es_irreducible(alpha,d):
#Comprobamos si alpha es irreducible en O
if es_entero(alpha)==false:
print "No es entero algebraico alpha"
return false
norm_alpha=norma(alpha)
if isprime(norm_alpha)==true:
return true
elif isprime(sqrt(norm_alpha)):
if connorma(sqrt(norm_alpha),d)==[]:
return true
else:
return false
else:
return false
def contador(lista):
#Función que su input es una lista y su output otra lista
#La lista de salido son duplas con cada elemento de la lista de entrada acompañado con las veces que se repite en la lista de entrada
aux=[]
for i in range(0,len(lista)):
bool1=false
for j in range(0,len(aux)):
if lista[i]==aux[j][0]:
bool1=true
if bool1==false:
count=0
for k in range(0,len(lista)):
if lista[i]==lista[k]:
count=count+1
aux.append((lista[i],count))
return aux
def factoriza(alpha,d):
#Función para factorizar alpha en un dominio euclídeo
if d!=-1 and d!=-2 and d!=-3 and d!=-7 and d!=-11:
print "Introduce un dominio euclídeo donde pueda factorizar"
return false
if es_irreducible(alpha,d):
print "Es irreducible"
return false
#Calculamos la norma de n y la lista con los factores de la norma
norm=norma(alpha)
fact=list(factorint(norm))
factores=[]
#Por cada factor de la norma de alpha vemos si algún elemento de esa norma divide a alpha
for i in range(0,len(fact)):
L1=connorma(fact[i],d)
bool1=false
for j in range(0,len(L1)):
while(divide(L1[j],alpha,d))==true:
#Añadimos el elemento a la lista de factores si divide a alpha
factores.append(L1[j])
alpha=cociente(L1[j],alpha,d)
bool1=true
#Cuando nos quede una unidad paramos de iterar
if es_unidad(alpha):
factores.append(alpha)
break
if bool1==false:
#Esta condición es por si no hay irreducibles de norma p, buscarlos de p^2
L1=connorma(fact[i]**2,d)
for j in range(0,len(L1)):
while(divide(L1[j],alpha,d))==true:
#Añadimos el elemento a la lista de factores si divide a alpha
factores.append(L1[j])
alpha=cociente(L1[j],alpha,d)
#Cuando tengamos una unidad paramos de iterar
if es_unidad(alpha):
factores.append(alpha)
break
factores=contador(factores)
return factores
#-------------------------FACTORIZACIÓN EN DOMINIOS EUCLÍDEOS II(d negativo y positivo)--------------------------
def xy2(alpha,d):
#Calculamos las coordenadas racionales de alpha
if d!=0:
alpha2=simplify(alpha)
x=alpha2.coeff(sqrt(d),0)
y=alpha2.coeff(sqrt(d),1)
return (x,y)
else:
print "Mete un d distinto de cero"
return false
def norma2(alpha,d):
#Calculamos la norma de alpha sea cual sea el d
if d!=0:
coord=xy2(alpha,d)
conj=coord[0]-coord[1]*sqrt(d)
norma=expand(simplify(alpha*conj))
return norma
else:
print "Mete un d distinto de cero"
return false
def traza2(alpha,d):
#Calculamos la traza de alpha sea cual sea el d
if d!=0:
coord=xy2(alpha,d)
conj=expand(simplify(coord[0]-coord[1]*sqrt(d)))
traza=expand(simplify(alpha+conj))
return traza
else:
print "Mete un d distinto de cero"
return false
def es_entero2(alpha,d):
#Comprobamos si el elemento alpha es entero algebraico o no
norm=norma2(alpha,d)
traz=traza2(alpha,d)
#Comprobamos si la norma y la traza son enteras
return ask(Q.integer(traz))and ask(Q.integer(norm))
def ab2(alpha,d):
#Si alpha es entero, calculamos sus coordenadas enteras
if es_entero2(alpha,d)==true:
if d<0:
if d%4!=1:
e=sqrt(d)
a=(alpha+alpha.conjugate())/2
b=(alpha-alpha.conjugate())/(2*sqrt(d))
else:
e=Rational(1,2)+sqrt(d)*Rational(1,2)
coord=xy2(alpha,d)
x_1=coord[0]*2
y_1=coord[1]*2
a=(x_1-y_1)/2
b=y_1
return[int(a),int(b)]
elif d>0:
if d%4==1:
e=Rational(1,2)+sqrt(d)*Rational(1,2)
coord=xy2(alpha,d)
x_1=coord[0]*2
y_1=coord[1]*2
a=(x_1-y_1)/2
b=y_1
else:
e=sqrt(d)
coord=xy2(alpha,d)
conj=coord[0]-coord[1]*sqrt(d)
a=(alpha+conj)/2
b=(alpha-conj)/(2*sqrt(d))
return[int(a),int(b)]
else:
print "Introduce un d distinto de 0"
return false
else:
return "Introduzca un entero algebraico"
def divide2(alpha,beta,d):
#Comprobamos si alpha divide a beta, para ello vemos multiplicando por el conjugado si la fracción es un entero
coord_alpha=xy2(alpha,d)
conj=coord_alpha[0]-coord_alpha[1]*sqrt(d)
num=expand(simplify(beta*conj))
norm=norma2(alpha,d)
coord_num=xy2(num,d)
division=Rational(coord_num[0],norm)+Rational(coord_num[1],norm)*sqrt(d)
return es_entero2(division,d)
def cociente2(alpha,beta,d):
#Si alpha divide a beta calculamos su cociente
if divide2(alpha,beta,d)!=true:
return false
coord_alpha=xy2(alpha,d)
conj=coord_alpha[0]-coord_alpha[1]*sqrt(d)
division=expand(simplify((beta*conj)/norma2(alpha,d)))
return division
def es_unidad2(alpha,d):
#Vemos si alpha es una unidad
return abs(norma2(alpha,d))==1
def libre_de_cuadrados(d):
#Vemos si d es libre de cuadrados, para ello hacemos una lista de sus factores
#Y vemos si es divisible por alguno de ellos al cuadrado
d1=abs(d)
lista=list(factorint(d1))
for i in range(0,len(lista)):
if d1%(lista[i]**2)==0:
return false
return true
def pell(d):
#Resolvemos la ecuación de Pell anterior
if libre_de_cuadrados(d)==false:
print "introduce un número libre de cuadrados"
return false
if d<=1 or type(d)!=int:
print "Introduce un d entero positivo válido"
return false
#Calculamos la fracción continua periódica
F = continued_fraction_periodic (0,1,d)
L= [F[0]]+F[1]
#Quitamos el ultimos elemento
L.pop()
#Calculamos la lista de convergentes
convergentes=list(continued_fraction_convergents(L))
#Damos la solución de la ecuación
if len(L)%2==0:
x=fraction(convergentes[len(convergentes)-1])[0]
y=fraction(convergentes[len(convergentes)-1])[1]
return (x,y)
else:
x=fraction(convergentes[len(convergentes)-1])[0]
y=fraction(convergentes[len(convergentes)-1])[1]
u=x+y*sqrt(d)
u_2=expand(u**2)
coord_u2=xy2(u_2,d)
return coord_u2
def generalpell(n,d):
#Resolvemos la ecuación general de Pell
if libre_de_cuadrados(d)==false:
print "introduce un número libre de cuadrados"
return false
if d>1:
#Resolvemos la ecuación de Pell anterior
sol_pell=pell(d)
r=abs(sol_pell[0])
s=abs(sol_pell[1])
sol=[]
if n==1:
#Si n es 1, añadimos la solución de pell
(s1,s2)=sol_pell
if s1==0:
sol.append((s1,s2))
sol.append((s1,-s2))
elif s2==0:
sol.append((s1,s2))
sol.append((-s1,s2))
else:
sol.append((s1,s2))
sol.append((-s1,s2))
sol.append((s1,-s2))
sol.append((-s1,-s2))
if n>0:
#Calculamos la cota
ymax=sqrt((n*(r-1))/(2*d))
for y in range(0,ymax+1):
x=n+d*(y**2)
x=sqrt(x)
if ask(Q.integer(x)):
if x==0:
sol.append((x,y))
sol.append((x,-y))
elif y==0:
sol.append((x,y))
sol.append((-x,y))
else:
sol.append((x,y))
sol.append((-x,y))
sol.append((x,-y))
sol.append((-x,-y))
return sol
elif n<0:
#Calculamos las cotas
ymin=sqrt(-n/d)
ymax=sqrt((-n*(r+1))/(2*d))
for y in range(ymin,ymax+1):
x=n+d*(y**2)
x=sqrt(x)
#Vemos si x es un cuadrado
if ask(Q.integer(x)):
if x==0:
sol.append((x,y))
sol.append((x,-y))
elif y==0:
sol.append((x,y))
sol.append((-x,y))
else:
sol.append((x,y))
sol.append((-x,y))
sol.append((x,-y))
sol.append((-x,-y))
return sol
else:
print "Tenemos una ecuación trivial, mete un n válido"