Ejemplo n.º 1
0
        public void Test04_SquareRoot()
        {
            TestContext.WriteLine($"ENTER: {nameof(Test04_SquareRoot)}");

            Assert.IsTrue(step03_passed, "IsTrue(step03_passed)");
            Assert.IsNotNull(gnfs, "IsNotNull(gnfs)");

            int maxSetSize = gnfs.CurrentRelationsProgress.FreeRelations.Max(lst => lst.Count);

            List <Relation> choosenRelationSet = gnfs.CurrentRelationsProgress.FreeRelations.Where(lst => lst.Count == maxSetSize).First();

            SquareFinder squareRootFinder = new SquareFinder(gnfs, choosenRelationSet);

            squareRootFinder.CalculateRationalSide();
            Tuple <BigInteger, BigInteger> foundFactors = squareRootFinder.CalculateAlgebraicSide(cancelToken);

            /*	Non-trivial factors also recoverable by doing the following:
             *
             * BigInteger min = BigInteger.Min(squareRootFinder.RationalSquareRootResidue, squareRootFinder.AlgebraicSquareRootResidue);
             * BigInteger max = BigInteger.Max(squareRootFinder.RationalSquareRootResidue, squareRootFinder.AlgebraicSquareRootResidue);
             * BigInteger R = max - min;
             * BigInteger S = max + min;
             * BigInteger P = GCD.FindGCD(gnfs.N, S);
             * BigInteger Q = GCD.FindGCD(gnfs.N, R);
             *
             */

            BigInteger P = foundFactors.Item1;
            BigInteger Q = foundFactors.Item2;

            Assert.AreNotEqual(1, P, "AreNotEqual(1, P)");
            Assert.AreNotEqual(1, Q, "AreNotEqual(1, Q)");

            Assert.AreEqual(new BigInteger(1811), P, "AreEqual(1811, P)");
            Assert.AreEqual(new BigInteger(1777), Q, "AreEqual(1777, Q)");

            step04_passed = true;

            TestContext.WriteLine($"{nameof(Test04_SquareRoot)} passed?: {step04_passed}");
            TestContext.WriteLine($"LEAVE: {nameof(Test04_SquareRoot)}");
        }
Ejemplo n.º 2
0
        public static GNFS FindSquares(CancellationToken cancelToken, GNFS gnfs)
        {
            if (cancelToken.IsCancellationRequested)
            {
                return(gnfs);
            }

            Logging.LogMessage();
            Logging.LogMessage($"# of solution sets: {gnfs.CurrentRelationsProgress.FreeRelations.Count}");
            Logging.LogMessage();

            BigInteger polyBase = gnfs.PolynomialBase;

            List <List <Relation> > freeRelations = gnfs.CurrentRelationsProgress.FreeRelations;

            // Below randomly selects a solution set to try and find a square root of the polynomial in.

            // Each time this step is stopped and restarted, it will try a different solution set.
            // Previous used sets are tracked with the List<int> triedFreeRelationIndices

            if (triedFreeRelationIndices.Count == freeRelations.Count)             // If we have exhausted our solution sets, alert the user. Number wont factor for some reason.
            {
                Logging.LogMessage("ERROR: ALL RELATION SETS HAVE BEEN TRIED...?");
                Logging.LogMessage($"If the number of solution sets ({freeRelations.Count}) is low, you may need to sieve some more and then re-run the matrix solving step.");
                Logging.LogMessage("If there are many solution sets, and you have tried them all without finding non-trivial factors, then something is wrong...");
                Logging.LogMessage();
                return(gnfs);
            }

            int freeRelationIndex = 0;

            do
            {
                freeRelationIndex = StaticRandom.Next(0, freeRelations.Count);
            }while (triedFreeRelationIndices.Contains(freeRelationIndex));

            triedFreeRelationIndices.Add(freeRelationIndex);                             // Add current selection to our list

            List <Relation> selectedRelationSet = freeRelations[freeRelationIndex];      // Get the solution set

            SquareFinder squareRootFinder = new SquareFinder(gnfs, selectedRelationSet); // If you want to solve for a new solution set, create a new instance

            Logging.LogMessage($"Selected solution set # {freeRelationIndex + 1}");
            Logging.LogMessage();
            Logging.LogMessage($"Selected set (a,b) pairs (count: {selectedRelationSet.Count}): {string.Join(" ", selectedRelationSet.Select(rel => $"({rel.A},{rel.B})"))}");
            Logging.LogMessage();
            Logging.LogMessage();
            Logging.LogMessage();
            Logging.LogMessage($"ƒ'(m)     = {squareRootFinder.PolynomialDerivative}");
            Logging.LogMessage($"ƒ'(m)^2   = {squareRootFinder.PolynomialDerivativeSquared}");
            Logging.LogMessage();
            Logging.LogMessage("Calculating Rational Square Root.");
            Logging.LogMessage("Please wait...");

            squareRootFinder.CalculateRationalSide();

            Logging.LogMessage("Completed.");
            Logging.LogMessage();
            Logging.LogMessage($"γ²        = {squareRootFinder.RationalProduct} IsSquare? {squareRootFinder.RationalProduct.IsSquare()}");
            Logging.LogMessage($"(γ  · ƒ'(m))^2 = {squareRootFinder.RationalSquare} IsSquare? {squareRootFinder.RationalSquare.IsSquare()}");
            Logging.LogMessage();
            Logging.LogMessage();
            Logging.LogMessage("Calculating Algebraic Square Root.");
            Logging.LogMessage("Please wait...");

            Tuple <BigInteger, BigInteger> foundFactors = squareRootFinder.CalculateAlgebraicSide(cancelToken);
            BigInteger P = foundFactors.Item1;
            BigInteger Q = foundFactors.Item2;

            if (cancelToken.IsCancellationRequested && P == 1 && Q == 1)
            {
                Logging.LogMessage("Square root search aborted!");
                return(gnfs);
            }

            Logging.LogMessage("Completed.");
            Logging.LogMessage();
            Logging.LogMessage();

            if (P != 1 || Q != 1)
            {
                Logging.LogMessage("NON-TRIVIAL FACTORS FOUND!");
                Logging.LogMessage();
            }

            IPolynomial S           = squareRootFinder.S;
            IPolynomial SRingSquare = squareRootFinder.SRingSquare;

            BigInteger prodS = SRingSquare.Evaluate(polyBase);

            IPolynomial reducedS = Polynomial.Modulus(S, gnfs.N);

            BigInteger totalProdS    = squareRootFinder.TotalS.Evaluate(polyBase) * squareRootFinder.PolynomialDerivative;
            BigInteger totalProdModN = totalProdS % gnfs.N;
            BigInteger prodSmodN     = prodS % gnfs.N;

            List <BigInteger> algebraicNumberFieldSquareRoots = squareRootFinder.AlgebraicResults;

            BigInteger rationalSquareRoot  = squareRootFinder.RationalSquareRootResidue;
            BigInteger algebraicSquareRoot = squareRootFinder.AlgebraicSquareRootResidue;


            Logging.LogMessage($"∏ Sᵢ =");
            Logging.LogMessage($"{squareRootFinder.TotalS}");
            Logging.LogMessage();
            Logging.LogMessage($"∏ Sᵢ (mod ƒ) =");
            Logging.LogMessage($"{reducedS}");
            Logging.LogMessage();
            Logging.LogMessage("Polynomial ring:");
            Logging.LogMessage($"({string.Join(") * (", squareRootFinder.PolynomialRing.Select(ply => ply.ToString()))})");
            Logging.LogMessage();
            Logging.LogMessage("Primes:");
            Logging.LogMessage($"{string.Join(" * ", squareRootFinder.AlgebraicPrimes)}");             // .RelationsSet.Select(rel => rel.B).Distinct().OrderBy(relB => relB))
            Logging.LogMessage();
            Logging.LogMessage();
            Logging.LogMessage($"X² / ƒ(m) = {squareRootFinder.AlgebraicProductModF}  IsSquare? {squareRootFinder.AlgebraicProductModF.IsSquare()}");
            Logging.LogMessage();
            Logging.LogMessage($"");
            Logging.LogMessage($"AlgebraicPrimes: {squareRootFinder.AlgebraicPrimes.FormatString(false)}");
            Logging.LogMessage($"AlgebraicResults: {squareRootFinder.AlgebraicResults.FormatString(false)}");
            Logging.LogMessage($"");
            Logging.LogMessage($"*****************************");
            Logging.LogMessage($"");
            Logging.LogMessage($"AlgebraicSquareRootResidue: {squareRootFinder.AlgebraicSquareRootResidue}");
            Logging.LogMessage($"");
            Logging.LogMessage($"AlgebraicNumberFieldSquareRoots: {algebraicNumberFieldSquareRoots.FormatString(false)}");
            Logging.LogMessage($"");
            Logging.LogMessage($" RationalSquareRoot : {rationalSquareRoot}");
            Logging.LogMessage($" AlgebraicSquareRoot: {algebraicSquareRoot} ");
            Logging.LogMessage($"");
            Logging.LogMessage($"*****************************");
            Logging.LogMessage($"S (x)       = {prodSmodN}  IsSquare? {prodSmodN.IsSquare()}");
            Logging.LogMessage();
            Logging.LogMessage("Roots of S(x):");
            Logging.LogMessage($"{{{string.Join(", ", squareRootFinder.RootsOfS.Select(tup => (tup.Item2 > 1) ? $"{tup.Item1}/{tup.Item2}" : $"{tup.Item1}"))}}}");