public RingPolynomial(IntPolynomial p1) { for (int i = 0; i < p1.size; i++) { this.Add(p1[i]); } }
public static RingDecomposeList HenselLifting(IntPolynomial f, RingDecomposeList fFactorization, List <RingPolynomial> GCDCoeffs, int liftingDegree) { IntPolynomial hasSquares; IntPolynomial.GCD(f, f.Derivative(), out hasSquares); IntPolynomial SquareFreef = (f / hasSquares).Quotient; BigInteger squareCoeff = hasSquares[hasSquares.size - 1]; SquareFreef *= squareCoeff; BigInteger p = RingBint.mod; BigInteger OriginalCoeff = SquareFreef[SquareFreef.size - 1]; List <IntPolynomial> LiftingList = new List <IntPolynomial>(); for (int i = 0; i < fFactorization.CountUniq; i++) { LiftingList.Add(new IntPolynomial(fFactorization[i])); } LiftingList[0] *= OriginalCoeff; for (int t = 1; t < liftingDegree; t++) { IntPolynomial multiplyFactor = new IntPolynomial { 1 }; for (int i = 0; i < LiftingList.Count; i++) { multiplyFactor *= new IntPolynomial(LiftingList[i]); } var temp = SquareFreef - multiplyFactor; RingPolynomial d = new RingPolynomial(temp / BigInteger.Pow(p, t)); for (int i = 0; i < fFactorization.CountUniq; i++) { RingPolynomial CurrUniqPoly = fFactorization[i]; if (i == 0) { CurrUniqPoly *= fFactorization.polyCoef; } RingPolynomial Gc = (d * GCDCoeffs[i] / CurrUniqPoly).Reminder; SetModContext(p, t + 1); LiftingList[i] = LiftingList[i] + new IntPolynomial(Gc) * BigInteger.Pow(p, t); SetModContext(p); } Program.Log("Разложение поднято до " + BigInteger.Pow(p, t + 1)); } SetModContext(p, liftingDegree); RingDecomposeList liftigRes = new RingDecomposeList(); for (int i = 0; i < LiftingList.Count; i++) { liftigRes.Add(new RingPolynomial(LiftingList[i])); } liftigRes.polyCoef = OriginalCoeff; return(liftigRes); }
static bool IntPolynomialFactorisationTest(string mode = "easy") { IntPolynomial f = prepareIntPolyForFactor(mode); RingDecomposeList fFactorisation; var LiftedFactorisation = f.FactorIntPolynomialOverBigModule(out fFactorisation); RingPolynomial res = new RingPolynomial { 1 }; Program.Log(); Program.Log("Получена факторизация:"); for (int i = 0; i < LiftedFactorisation.CountUniq; i++) { for (int j = 0; j < fFactorisation.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.Log("Проверка на соответствие исходному многочлену произведения:"); Program.recDepth++; Program.Log("Исходный многочлен"); f.Print(); Program.Log("Результат перемножения факторизации:"); res.Print(); Program.recDepth--; IntPolynomial resInt = new IntPolynomial(res); if (f == resInt) { Program.Log("Верно!"); return(true); } else { Program.Log("Неверно..."); return(false); } }
static IntPolynomial prepareIntPolyForFactor(string mode) { int minCoef = 1; int maxCoef = 1; int minNumMult = 1; int maxNumMult = 1; int minSize = 1; int maxSize = 1; switch (mode) { case "easy": minCoef = 1; maxCoef = 6; minNumMult = 3; maxNumMult = 3; minSize = 2; maxSize = 2; break; case "medium": minCoef = 1; maxCoef = 10; minNumMult = 3; maxNumMult = 3; minSize = 3; maxSize = 3; break; case "post-medium": minCoef = 1; maxCoef = 5; minNumMult = 4; maxNumMult = 5; minSize = 3; maxSize = 5; break; case "hard": minCoef = 1; maxCoef = 5; minNumMult = 10; maxNumMult = 10; minSize = 2; maxSize = 5; break; case "ultra": minCoef = 1; maxCoef = 5; minNumMult = 10; maxNumMult = 30; minSize = 2; maxSize = 15; break; } Random rnd = new Random(); IntPolynomial f = new IntPolynomial { rnd.Next(minCoef, maxCoef) }; int NumCoeffs = rnd.Next(minNumMult, maxNumMult); for (int i = 0; i < NumCoeffs; i++) { IntPolynomial temp = new IntPolynomial { rnd.Next(minCoef, maxCoef) }; int SizeCoeff = rnd.Next(minSize, maxSize); for (int j = 0; j < SizeCoeff; j++) { temp[j] = (BigInteger)rnd.Next(minCoef, maxCoef); } f *= temp; } return(f); }
static void LiftingTest() { IntPolynomial f = new IntPolynomial { 1, 2, 3 } *new IntPolynomial { 1, 2 }; IntPolynomial squares; IntPolynomial.GCD(f, f.Derivative(), out squares); IntPolynomial SquareFreef = (f / squares).Quotient; BigInteger mod = IntPolynomial.SelectAppropriateMod(f, SquareFreef); RingPolynomial.SetModContext(mod); Console.WriteLine("Выбранный модуль кольца: " + mod + "\n"); RingPolynomial f_inring = new RingPolynomial(f); var factorization = f_inring.BerlekampFactor(); var GCDfactor = RingPolynomial.GetGCDCoefficientForHensel(factorization); RingPolynomial allGCDResult = new RingPolynomial { 0 }; List <RingPolynomial> factorsOfCoeff = new List <RingPolynomial>(); 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"); } allGCDResult.Print(); // после поднятия mod уже увеличился var liftedDecomposition = RingPolynomial.HenselLifting(f, factorization, GCDfactor, 20); RingPolynomial checkLiftedDecomposition = new RingPolynomial { 1 }; 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(); }
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(); }
public static RingDecomposeList HenselLiftingUntilTheEnd(IntPolynomial f, RingDecomposeList fFactorization, List <RingPolynomial> GCDCoeffs) { IntPolynomial hasSquares; IntPolynomial.GCD(f, f.Derivative(), out hasSquares); IntPolynomial SquareFreef = (f / hasSquares).Quotient; BigInteger squareCoeff = hasSquares[hasSquares.size - 1]; SquareFreef *= squareCoeff; BigInteger p = RingBint.mod; BigInteger OriginalCoeff = f[f.size - 1]; BigInteger biggestCoeff = SquareFreef[0]; for (int i = 1; i < SquareFreef.size; i++) { if (SquareFreef[i] > biggestCoeff) { biggestCoeff = SquareFreef[i]; } } List <IntPolynomial> LiftingList = new List <IntPolynomial>(); for (int i = 0; i < fFactorization.CountUniq; i++) { LiftingList.Add(new IntPolynomial(fFactorization[i])); } LiftingList[0] *= OriginalCoeff; bool Decomposed = false; int t = 1; BigInteger currMod = p; while (!Decomposed) { currMod = BigInteger.Pow(p, t + 1); IntPolynomial multiplyFactor = new IntPolynomial { 1 }; for (int i = 0; i < LiftingList.Count; i++) { multiplyFactor *= LiftingList[i]; } var temp = SquareFreef - multiplyFactor; RingPolynomial d = new RingPolynomial(temp / BigInteger.Pow(p, t)); for (int i = 0; i < fFactorization.CountUniq; i++) { RingPolynomial CurrUniqPoly = new RingPolynomial(fFactorization[i]); if (i == 0) { CurrUniqPoly *= fFactorization.polyCoef; } RingPolynomial Gc = ((d * GCDCoeffs[i]) / CurrUniqPoly).Reminder; SetModContext(p, t + 1); LiftingList[i] = LiftingList[i] + new IntPolynomial(Gc) * BigInteger.Pow(p, t); SetModContext(p); } t++; Program.Log("Разложение поднято до " + currMod); if (currMod > biggestCoeff) { SetModContext(p, t); RingPolynomial res = new RingPolynomial { 1 }; RingPolynomial FirstWithoutCoeff = new RingPolynomial(LiftingList[0]) / LiftingList[0][LiftingList[0].degree]; for (int u = 0; u < fFactorization.CountUniq; u++) { for (int j = 0; j < fFactorization.divisors[u].count; j++) { if (j != 0 && u == 0) { res *= FirstWithoutCoeff; } else { res *= new RingPolynomial(LiftingList[u]); } } } IntPolynomial resInt = new IntPolynomial(res); if (f == resInt) { Decomposed = true; } } } SetModContext(p, t); RingDecomposeList liftigRes = new RingDecomposeList(); for (int i = 0; i < LiftingList.Count; i++) { liftigRes.Add(new RingPolynomial(LiftingList[i])); } liftigRes.polyCoef = OriginalCoeff; return(liftigRes); }