martes, 21 de julio de 2015

ALGORITMO QUADRATIC SIEVE


Es un algoritmo de factorización de enteros y, en la práctica, el segundo método más rápido conocido (después de Number field Sieve). Es todavía el más rápido para enteros que tienen 100 o menos dígitos decimales, y es considerado mucho más sencillo que la NFS. Es un algoritmo de factorización de propósito general, lo que significa que su tiempo de ejecución únicamente depende el tamaño del entero a ser factorizado, y no sobre una estructura especial o propiedades.

Algoritmo:







Ejemplo Aplicativo:
Nota: El valor de X, es un numero aleatorio, en este caso elegimos el 12






Observación: si al momento de hallar el mcd(x-y,n) este nos da un valor de 1 o n , debemos volver a buscar otra combinación de filas a sumar.

Implementación:
La siguiente implementación fue realizada en conjunto con uno de los autores de este Blog (Rafael Larco Buchelli).

Clase QuadraticSieve
import java.util.ArrayList;

public class QuadraticSieve {
    
    public static int base=40;
    
    EsPrimo esPrimo = new EsPrimo();
    Jacobi jacobi = new Jacobi();
    
    public ArrayList< Long > QS(int n){
        //***************CALCULO DE LA BASE DE FACTORES************//
        int jac=0,raiz=0;
        ArrayList< Long > solucion = new ArrayList<  >();
        ArrayList< Integer > factoresBase = new ArrayList<  >();
        ArrayList< Integer > valoresX = new ArrayList<  >();
        ArrayList< Integer > valoresY = new ArrayList<  >();
        ArrayList< Boolean > ySuaves = new ArrayList<  >();
        ArrayList< Integer > valoresSuaves = new ArrayList<  >();
        factoresBase.add(-1);
        
        for (int i = 2; i <  base; i++) {
            if(esPrimo.esPrimo(i)){
                jac=jacobi.Jacobi(n, i);
                if(jac==1){
                    factoresBase.add(i);
                }
            }
        }
        System.out.println("Mostrando Base De Factores");
        for (int i = 0; i <  factoresBase.size(); i++) {
            System.out.println(factoresBase.get(i));
        }
        
        //*********************RAIZ CUADRADA DE N*************//
        raiz=(int) Math.sqrt(n);
        System.out.println("\nRaiz Cuadrada De "+n+" : "+raiz);
        
        //*******************BUSQUEDA DE VALORES*************//
        for (int i = -base; i < = base; i++) {
            valoresX.add(raiz+i);
        }
        
        for (int i = -base ; i < = base; i++) {
            valoresY.add((int)Math.pow((raiz+i), 2)-n);  
        }

        //**********HALLANDO LOS Y'S SUAVES*************//
        int i,j,valor,p;
        int []a= new int[50];
        for (int k = 0; k <  valoresY.size(); k++) {
            valor=Math.abs(valoresY.get(k));
            i=2;
            j=0;
            while(valor >1){
               if(valor%i==0){
                  valor=valor/i;
                  a[j]=i;
                  j++;
                  i=2;
               }
               else
                  i++;
            }
            p=0;
            for (int l = 0; l <  j; l++) {
                boolean band=true;
                for (int m = 0; m <  factoresBase.size() && band==true; m++) {
                    if(a[l]==factoresBase.get(m)){
                        band=false;
                        p++;
                    }
                }
                
            }
            
            if(p==j){
                System.out.println(valoresY.get(k)+" | Suave"+" X: "+Math.sqrt(valoresY.get(k)+n));
                ySuaves.add(true);
                valoresSuaves.add(valoresY.get(k));
                
            }
            else{
//                System.out.println(valoresY.get(k)+" | No Suave");
                ySuaves.add(false);
            }  
        }
        
        //**************CALCULANDO LA MATRIZ*************//
        int [][]matrizInicial = new int [valoresSuaves.size()][factoresBase.size()];
        int conRep,filaMI=0,columnaMI=0;
        ArrayList< Integer > factorizacionN = new ArrayList<  >();
        Factorizar factorizar=new Factorizar();
        
        for (int k = 0; k <  valoresSuaves.size(); k++) {
            conRep=0;
            columnaMI=0;
            factorizacionN=factorizar.factorizarN(Math.abs(valoresSuaves.get(k)));
            if(valoresSuaves.get(k)< 0){
                factorizacionN.add(-1);
            }
            for (int l = 0; l <  factoresBase.size(); l++) {
                conRep=0;
                for (int m = 0; m <  factorizacionN.size(); m++) {
                    if(factoresBase.get(l)==factorizacionN.get(m)){
                        conRep++;
                    }
                }
                matrizInicial[filaMI][columnaMI]=conRep%2;
                columnaMI++;
            }
            filaMI++;
        }
        

        //*******************ELIMINACION GAUSSIANA*************//
        System.out.println("Gaussiana");
        /**********************************************************/
        /***Eliminacion de gauss: escoger las filas de la matriz***/
        /*identidad cuya fila en la matriz inicial son todos ceros*/
        /**********************************************************/
        
        int filas, columnas;
        filas=valoresSuaves.size();
        columnas=factoresBase.size();
        
        Identidad identidad = new Identidad();
        
        int [][]MI=new int[filas][filas];
        
        identidad.crearMatrizIdentidad(MI, filas);
        
        Gaussiana gaussiana = new Gaussiana();
        
        gaussiana.Gaussiana(matrizInicial, MI, filas, columnas);
        

        //**************OBTENIENDO LAS FILAS A USAR (CEROS)***********//
        boolean banderaCeros=true;
        ArrayList< Integer > FilasUsar = new ArrayList<  >();
        for(int q=0;q< filas;q++){
            banderaCeros=true;
            for(int w=0;w< columnas && banderaCeros==true;w++){
                if(matrizInicial[q][w]==1){
                    banderaCeros=false;
                }
        }
            if(banderaCeros==true){
                System.out.println("Usar Filas: "+q);
            }
            if(banderaCeros==true){
                FilasUsar.add(q);
            }
        }
        
        /***************CALCULANDO RESULTADO***********/
        int filaUsar;
        long resultadoX,resultadoY,valorXSuave,respuestaVerdad_Uno,respuestaVerdad_Dos;
        boolean bandSolucion=true;
        for (int k = 0; k <  FilasUsar.size() && bandSolucion==true; k++) {
            resultadoX=1;
            resultadoY=1;
            respuestaVerdad_Uno=0;
            respuestaVerdad_Dos=0;
            filaUsar=FilasUsar.get(k);
            for (int l = 0; l <  MI.length; l++) {
                if(MI[filaUsar][l]==1){
                    valorXSuave=(long) Math.sqrt(valoresSuaves.get(l)+n);
                    resultadoX=resultadoX*valorXSuave;
                    resultadoY=resultadoY*valoresSuaves.get(l);
                }
            }
            System.out.println("Resultado Y Sin Modulo: "+resultadoY);
            resultadoX=resultadoX%n;
            System.out.println("Resultado X: "+resultadoX);
            resultadoY=(long) ((Math.sqrt(resultadoY)))%n;
            System.out.println("Resultado Y: "+resultadoY);
            
            MCD gcd = new MCD();
            
            respuestaVerdad_Uno=gcd.mcd((resultadoX-resultadoY), n);
            respuestaVerdad_Dos=gcd.mcd((resultadoX+resultadoY), n);
            
            if(respuestaVerdad_Uno*respuestaVerdad_Dos==n && respuestaVerdad_Uno!=1 && respuestaVerdad_Dos!=1){
                System.out.println("\nValor No Trivial: "+respuestaVerdad_Uno);
                System.out.println("\nEl Otro Valor: "+respuestaVerdad_Dos);
                solucion.add(0,respuestaVerdad_Uno);
                solucion.add(1,respuestaVerdad_Dos);
                bandSolucion=false;
            }     
        }
        return solucion;
    }
}


Clase CalcularExponente
public class EsPrimo {
    
    public boolean esPrimo(int numero){
        int contador = 2;
        boolean primo=true;
        while ((primo) && (contador!=numero)){
            if (numero % contador == 0)
                primo = false;
            contador++;
        }
        return primo;
    }
}
Clase Factorizar
import java.util.ArrayList;


public class Factorizar {
    public ArrayList< Integer >  factorizarN(int n){
        int i,j;
        ArrayList< Integer >  factores = new ArrayList<  > ();
        i=2;
        j=0;
        while(n > 1){
            if(n%i==0){
                n=n/i;
                factores.add(i);
                j++;
                i=2;
            }
            else
                i++;
        }
        return factores;
    }
}


Clase Gaussiana
public class Gaussiana {
    public void Gaussiana(int M[][], int Identidad[][], int filas, int columnas){
        int i=0;
    int k=0;
    boolean band=true;
        
    while(i< filas-1){   
            for(int j=0;j< columnas && band==true;j++){       
                if(M[i][j]==1){           
                    k=j;         
                    band=false;
                }
            }
     
            if(band==false){
                for(int u=i+1;u< filas;u++){
                    if(M[u][k]==1){
                        for(int w=0;w< columnas;w++){
                            M[u][w]^=M[i][w];
                            if(w< u){
                            Identidad[u][w]^=Identidad[i][w];
                            }
                        }  
                    }       
                }
            }
            band=true;
            i++;
        }
    }
}


Clase Identidad
public class Identidad {
    public void crearMatrizIdentidad(int I[][],int filas){
        for(int i=0;i< filas;i++){
            for(int j=0;j< filas;j++){      
            if(i==j){
                    I[i][j]=1;
                }
                else{
                    I[i][j]=0;
                }
        }
        }
    }
}

Clase Jacobi
public class Jacobi {
    
    CalcularExponente calcularExponente = new CalcularExponente();
    SonCongruentes sonCongruentes = new SonCongruentes();
    
    public int Jacobi(int a, int n){
        int e=0,a1=1,n1=0,s=-2;
    
        if(a==0 || a==1)
            return a;

        e=calcularExponente.hallarExponente(a);

        a1=(int)(a/Math.pow(2,e));

        if(e%2==0) // si 'e' es par
            s=1;
        else{
            if((sonCongruentes.son_congruentes(n,1,8))||(sonCongruentes.son_congruentes(n,7,8)))
                s=1;
            else
            if((sonCongruentes.son_congruentes(n,3,8))||(sonCongruentes.son_congruentes(n,5,8)))
                s=-1;
        }

        if((sonCongruentes.son_congruentes(n,3,4))&&(sonCongruentes.son_congruentes(a1,3,4)))
            s=-1*s;

        n1=n%a1;

        if(a1==1)
            return s;
        else
            return (s*Jacobi(n1,a1));
    }

}

Clase MCD
public class MCD {
    public long mcd(long a, long b){
        return (b == 0)? a : mcd(b, a % b);
    }
}


Clase Potencia Prima
import java.util.ArrayList;

public class PotenciaPrima {
    public boolean potenciaPrima(int n){
        int i;
        ArrayList< Integer > A = new ArrayList< >();
        i=2;
        while(n >1){
           if(n%i==0){
              n=n/i;
              A.add(i);
              i=2;
           }
           else
              i++;
        }

        boolean band=true;

        for(i=0;i < A.size()&&band==true;i++){
            for(int o=0;o < A.size();o++){
                if(A.get(i)!=A.get(o)){
                    band=false;
                }
            }
        }

        return band;
        }
}

Clase Congruencia
public class SonCongruentes {
    
    public boolean son_congruentes(long a, long b, long n){
        if((a-b)%n==0)
            return true;
        else
            return false;
    }
    
}

banner
Previous Post
Next Post

Hola, me llamo Andrés.Soy egresado de la carrera de Ingeniería Informática en la Universidad Nacional de Trujillo (Perú).Me considero autodidacta de corazón ,amante del mundo de la programación, software libre y hacking ético

0 comentarios: