Пример #1
0
        public static BigInteger SelectAppropriateMod(IntPolynomial f, IntPolynomial SquareFreef)
        {
            BigInteger mod = 2;

            while (true)
            {
                while (f[f.degree] % mod == 0)
                {
                    mod = getNextPrime(mod);
                }
                RingPolynomial.SetModContext(mod);
                RingPolynomial Ringf = new RingPolynomial(SquareFreef);
                RingPolynomial.GCD(Ringf, Ringf.Derivative(), out RingPolynomial gcdRes);
                if (gcdRes.degree < 1 && ((Ringf / gcdRes).Quotient).FindNumOfMultipliers() > 0)
                {
                    break;
                }

                mod = getNextPrime(mod);
            }
            return(mod);
        }
Пример #2
0
        static void RingPolyTest()
        {
            RingPolynomial.SetModContext(7);
            tester test = () =>
            {
                Random         rnd  = new Random();
                int            flen = rnd.Next(5, 20);
                int            glen = rnd.Next(5, 21);
                int            clen = rnd.Next(5, 22);
                RingPolynomial f    = new RingPolynomial();
                RingPolynomial g    = new RingPolynomial();
                RingPolynomial c    = new RingPolynomial();
                for (int i = 0; i < flen; i++)
                {
                    f.Add(rnd.Next(0, (int)RingBint.mod));
                }
                for (int i = 0; i < glen; i++)
                {
                    g.Add(rnd.Next(0, (int)RingBint.mod));
                }
                for (int i = 0; i < clen; i++)
                {
                    c.Add(rnd.Next(0, (int)RingBint.mod));
                }
                f = f.Normalize();
                g = g.Normalize();
                c = c.Normalize();
                RingPolynomial.GCD(f, g, out RingPolynomial gcd);
                var sol = RingPolynomial.SolveEquation(f, g, c);
                if (!sol.isDefined)
                {
                    Console.WriteLine("Решение не найдено!");
                }

                f.Print('f');
                g.Print('g');
                c.Print('c');
                Console.WriteLine(sol);

                if (f.IsNull() && !g.IsNull())
                {
                    if (c.IsNull())
                    {
                        return(sol.zeroSolution.Y.IsNull() && (sol.solutionStep.X - new RingPolynomial {
                            1
                        }).IsNull() && sol.solutionStep.Y.IsNull());
                    }
                    else
                    {
                        if ((c / g).Reminder.IsNull())
                        {
                            return(sol.zeroSolution.Y == (c / g).Quotient.Normalize() && sol.solutionStep.Y.IsNull() && (sol.solutionStep.X - new RingPolynomial {
                                1
                            }).IsNull());
                        }
                        else
                        {
                            return(sol.isDefined == false);
                        }
                    }
                }
                if (!f.IsNull() && g.IsNull())
                {
                    if (c.IsNull())
                    {
                        return(sol.zeroSolution.X.IsNull() && (sol.solutionStep.Y - new RingPolynomial {
                            1
                        }).IsNull() && sol.solutionStep.X.IsNull());
                    }
                    else
                    {
                        if ((c / f).Reminder.IsNull())
                        {
                            return(sol.zeroSolution.X == (c / f).Quotient.Normalize() && sol.solutionStep.X.IsNull() && (sol.solutionStep.Y - new RingPolynomial {
                                1
                            }).IsNull());
                        }
                        else
                        {
                            return(sol.isDefined == false);
                        }
                    }
                }
                if (f.IsNull() && g.IsNull())
                {
                    if (!c.IsNull())
                    {
                        return(sol.isDefined == false);
                    }
                    else
                    {
                        return((sol.solutionStep.X - new RingPolynomial {
                            1
                        }).IsNull() && (sol.solutionStep.Y - new RingPolynomial {
                            1
                        }).IsNull());
                    }
                }
                if (c.IsNull())
                {
                    return((((sol.solutionStep.X) * f + (sol.solutionStep.Y) * g) - c).IsNull() && (sol.zeroSolution.X / sol.solutionStep.X).Reminder.IsNull() && (sol.zeroSolution.Y / sol.solutionStep.Y).Reminder.IsNull());
                }

                if ((c / gcd).Reminder.IsNull())
                {
                    return((((sol.zeroSolution.X + sol.solutionStep.X) * f + (sol.zeroSolution.Y + sol.solutionStep.Y) * g) - c).IsNull());
                }
                else
                {
                    return(sol.isDefined == false);
                }
            };
            int  i = 0;
            bool res;

            while (res = test())
            {
                Console.WriteLine("i =" + i + (res ? " OK" : "ERR"));
                i++;
            }
        }
        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.White;

            Console.WriteLine("Выберите пример (1 - НОД, 2 - Берлекамп, 3 - Гензель)");

            int chosen_example = Console.Read() - '0';

            if (chosen_example == 1)
            {
                int mod = 13;
                RingPolynomial.SetModContext(mod);

                Console.WriteLine("Выбран НОД.");
                Console.WriteLine("1) НОД полиномов над R[x]: (Расширенный алгоритм Евклида)");
                Polynomial f_r = new Polynomial {
                    1, 1, 1
                } *new Polynomial {
                    (decimal)0.5, 1, 1
                } *new Polynomial {
                    2, 1
                };
                f_r.Print('f');
                Polynomial g_r = new Polynomial {
                    1, 1
                } *new Polynomial {
                    7, 7, 7
                } *new Polynomial {
                    3, 1
                };
                g_r.Print('g');
                Console.WriteLine("Их НОД и коэффициенты:");
                Polynomial gcd_r;

                Polynomial.GCDResult coeffs = Polynomial.GCD(f_r, g_r, out gcd_r);

                Console.WriteLine(gcd_r + " = (" + coeffs.Coef1 + ")*(" + f_r + ") + (" + coeffs.Coef2 + ")*(" + g_r + ")");

                Console.WriteLine("---------------------------------------------------------");

                Console.WriteLine("2) НОД полиномов над Zp[x]: (Расширенный алгоритм Евклида), модуль p = " + mod);
                RingPolynomial f_p = new RingPolynomial {
                    2, 1, 1
                } *new RingPolynomial {
                    5, 1
                } *new RingPolynomial {
                    2, 1
                };
                f_p.Print('f');
                RingPolynomial g_p = new RingPolynomial {
                    1, 1
                } *new RingPolynomial {
                    14, 7, 7
                } *new RingPolynomial {
                    3, 1
                };
                g_p.Print('g');
                Console.WriteLine("Их НОД и коэффициенты:");
                RingPolynomial gcd_p;

                RingPolynomial.GCDResult coeffs_p = RingPolynomial.GCD(f_p, g_p, out gcd_p);

                Console.WriteLine(gcd_p + " = (" + coeffs_p.Coef1 + ")*(" + f_p + ") + (" + coeffs_p.Coef2 + ")*(" + g_p + ")");

                Console.WriteLine("---------------------------------------------------------");

                Console.WriteLine("3) НОД полиномов над Z[x]: (алгоритм Евклида с псевдоделением)");
                IntPolynomial f_z = new IntPolynomial {
                    1, 1
                } *new IntPolynomial {
                    5, 1
                } *new IntPolynomial {
                    2, 1
                };
                f_z.Print('f');
                IntPolynomial g_z = new IntPolynomial {
                    1, 1
                } *new IntPolynomial {
                    2, 7, 7
                } *new IntPolynomial {
                    3, 1
                } *new IntPolynomial {
                    2, 1
                };
                g_z.Print('g');
                Console.WriteLine("Их НОД:");
                IntPolynomial gcd_z;
                IntPolynomial.GCD(f_z, g_z, out gcd_z);

                Console.WriteLine(gcd_z);
            }
            else if (chosen_example == 2)
            {
                int mod = 7;
                RingPolynomial.SetModContext(mod);
                Console.WriteLine("Выбран алгоритм Берклемпа факторизации многочлена. Модуль кольца равен: " + mod);
                RingPolynomial f = new RingPolynomial {
                    2, 1
                } *new RingPolynomial {
                    5, 1
                } *new RingPolynomial {
                    25, 10
                } *new RingPolynomial {
                    3, 1
                } *new RingPolynomial {
                    1, 1, 1
                };

                var LiftedFactorisation = f.BerlekampFactor();

                RingPolynomial res = new RingPolynomial {
                    1
                };
                Program.Log("Получена факторизация:");
                for (int i = 0; i < LiftedFactorisation.CountUniq; i++)
                {
                    for (int j = 0; j < LiftedFactorisation.divisors[i].count; j++)
                    {
                        RingPolynomial currPoly;
                        if (i == 0 && j == 0)
                        {
                            currPoly = LiftedFactorisation[i] * LiftedFactorisation.polyCoef;
                        }
                        else
                        {
                            currPoly = LiftedFactorisation[i];
                        }

                        currPoly.Print('g');
                        res *= currPoly;
                    }
                }

                Program.Log("Проверка на соответствие исходному многочлену произведения:");
                Program.recDepth++;
                Program.Log("Исходный многочлен");
                f.Print();
                Program.Log("Результат перемножения факторизации:");
                res.Print();
                Program.recDepth--;

                if (f == res)
                {
                    Program.Log("Верно!");
                }
                else
                {
                    Program.Log("Неверно...");
                }
            }
            else if (chosen_example == 3)
            {
                IntPolynomial f = new IntPolynomial {
                    1, 2
                } *new IntPolynomial {
                    1, 4
                } *new IntPolynomial {
                    1, 4
                } *new IntPolynomial {
                    1, 5
                } *new IntPolynomial {
                    1, 3, 4, 2, 3, 4, 6
                };

                IntPolynomial hasSquares;
                IntPolynomial.GCD(f, f.Derivative(), out hasSquares);
                IntPolynomial SquareFreef = (f / hasSquares).Quotient;

                Console.WriteLine("Выбран алгоритм Гензеля подъема многочленов.");

                Console.WriteLine("Поиск подходящего модуля кольца: ");
                BigInteger mod = IntPolynomial.SelectAppropriateMod(f, SquareFreef);
                Console.WriteLine("Найденный модуль: " + mod);

                RingPolynomial.SetModContext(mod);

                Console.WriteLine("Изначальный многочлен над Z[x]");
                f.Print();
                RingPolynomial f_inring = new RingPolynomial(f);
                Console.WriteLine("Разложение его над Z" + mod + "[x]:");
                var            factorization = f_inring.BerlekampFactor();
                var            GCDfactor     = RingPolynomial.GetGCDCoefficientForHensel(factorization);
                RingPolynomial allGCDResult  = new RingPolynomial {
                    0
                };

                List <RingPolynomial> factorsOfCoeff = new List <RingPolynomial>();
                Console.WriteLine("Подбор коэффициентов для представления единицы в алгоритме Гензеля:");
                Console.WriteLine("Отдельные слагаемые с коэффициентами:");
                for (int i = 0; i < factorization.CountUniq; i++)
                {
                    factorsOfCoeff.Add(new RingPolynomial {
                        1
                    });
                }
                for (int i = 0; i < factorization.CountUniq; i++)
                {
                    for (int j = 0; j < factorization.CountUniq; j++)
                    {
                        if (i != j)
                        {
                            factorsOfCoeff[i] *= factorization[j];
                            Console.Write("(" + factorization[j] + ")*");
                        }
                    }
                    if (i != 0)
                    {
                        factorsOfCoeff[i] *= factorization.polyCoef;
                    }
                    allGCDResult += factorsOfCoeff[i] * GCDfactor[i];
                    Console.Write("(" + GCDfactor[i] + ")\n");
                }
                Console.WriteLine("Проверка их суммы на равенство 1:");
                allGCDResult.Print();

                // после поднятия mod уже увеличился
                var            liftedDecomposition      = RingPolynomial.HenselLifting(f, factorization, GCDfactor, 4);
                RingPolynomial checkLiftedDecomposition = new RingPolynomial {
                    1
                };

                Console.WriteLine("Поднятая факторизация:");
                for (int i = 0; i < liftedDecomposition.CountUniq; i++)
                {
                    for (int j = 0; j < factorization.divisors[i].count; j++)
                    {
                        if (i == 0 && j == 0)
                        {
                            (liftedDecomposition[i] * f[f.size - 1]).Print();
                            checkLiftedDecomposition *= (liftedDecomposition[i] * f[f.size - 1]);
                        }
                        else
                        {
                            liftedDecomposition[i].Print();
                            checkLiftedDecomposition *= liftedDecomposition[i];
                        }
                    }
                }
                Program.Log("Проверяем декомпозицию поднятую:");
                checkLiftedDecomposition.Print('r');
                f.Print();
            }

            Console.Read();
        }