public int FindNumOfMultipliers() { RingPolynomial poly = this; RingBint[,] matrix = new RingBint[poly.degree, poly.degree - 1]; // транспонированное заполнение матрицы RingBint[][] decomposingPoly; for (int i = 1; i < poly.degree; i++) { RingPolynomial edinica = new RingPolynomial() { [i * (int)RingBint.mod] = 1 }; var reminder = (edinica / poly).Reminder; for (int j = 0; j < poly.degree; j++) { matrix[j, i - 1] = reminder[j]; } matrix[i, i - 1] -= 1; } decomposingPoly = RingMatrix.SolveHSLE(matrix); return(decomposingPoly.Length); }
public RingDecomposeList BerlekampFactor() { Program.recDepth++; RingPolynomial poly = this.Normalize(); if (poly.degree < 2) // если многочлен меньше второй степени, то и раскладывать смысла нет { Program.Log("Разложение для " + poly + " не требуется."); //end Program.recDepth--; return(new RingDecomposeList { poly }); } Program.Log("Поиск разложения для многочлена:"); if (Program.LogEnabled) { poly.Print('a'); } RingDecomposeList factorRes = new RingDecomposeList(); // результат - список делителей factorRes.polyCoef = poly[poly.degree]; poly *= 1 / factorRes.polyCoef; // 1) убираем кратные множители bool recheckPower = false; RingPolynomial multipleFators, newFactors; GCD(poly, poly.Derivative(), out multipleFators); if (multipleFators.degree > 0) { //1.1) Обнаружены кратные множители. Разделение исходного многочлена a(x) на b(x) * c(x) // - c(x) гарантированно не содержит кратных корней // - b(x) - это оставшаяся часть обрабатывается пробным делением в конце алгоритма multipleFators *= (new RingBint(1) / multipleFators[multipleFators.degree]); Program.Log("Обнаружены кратные множители. b(x) = " + multipleFators); poly = (poly / multipleFators).Quotient; //текущий многочлен теперь c(x) recheckPower = true; } newFactors = multipleFators; multipleFators = new RingPolynomial(); while (multipleFators != newFactors && newFactors.degree > 0) { multipleFators = newFactors; GCD(multipleFators, multipleFators.Derivative(), out newFactors); } if (multipleFators == newFactors) { // 1.2) особый случай, когда производная равна 0. Тогда f(x) = g(x)^p, но тогда f(x) = g(x^p) - воспользуемся этим Program.Log("Обнаружена общая степень кратная модулю поля (" + RingBint.mod + ")"); RingPolynomial g = new RingPolynomial((newFactors.size - 1) / (int)RingBint.mod + 1); for (int i = 0; i < g.size; i++) { g[i] = newFactors[i * (int)RingBint.mod]; } g *= 1 / g[g.degree]; RingDecomposeList gFactorRes = g.BerlekampFactor(); factorRes.AddRange(gFactorRes); recheckPower = true; } // 2) Обработка c(x) Program.Log("Разложение многочлена без кратных корней c(x) = " + poly); if (poly.degree < 2) // если многочлен меньше второй степени, то и раскладывать смысла нет { Program.Log("Разложение для " + poly + " не требуется."); if (poly.degree == 1) { factorRes.Add(poly); } else { factorRes.polyCoef *= poly[0]; } //end if (recheckPower) { for (int i = 0; i < factorRes.CountUniq; i++) { RingPolynomial divisor = factorRes.divisors[i].poly; int count = 1; RingPolynomial temp = divisor; while (true) { temp *= divisor; if ((this / temp).Reminder.IsNull()) { count++; } else { break; } } while (count > factorRes.divisors[i].count) { factorRes.Add(factorRes.divisors[i].poly); } } } Program.Log("Общее разложение на данном этапе: "); PrintDecompositionResult(factorRes); Program.recDepth--; return(factorRes); } // 2.1) Построение матрицы и нахождение ФСР ОСЛУ RingBint[,] matrix = new RingBint[poly.degree, poly.degree - 1]; // транспонированное заполнение матрицы RingBint[][] decomposingPoly; for (int i = 1; i < poly.degree; i++) { RingPolynomial edinica = new RingPolynomial() { [i * (int)RingBint.mod] = 1 }; var reminder = (edinica / poly).Reminder; for (int j = 0; j < poly.degree; j++) { matrix[j, i - 1] = reminder[j]; } matrix[i, i - 1] -= 1; } decomposingPoly = RingMatrix.SolveHSLE(matrix); // 2.2) рекурсивное разложение с помощью разлазающих многочленов (в статической переменной) if (decomposingPoly.Length > 0) { _BerlekampDecomposingPoly = decomposingPoly; RingBint leadingCoeff = poly[poly.degree]; poly *= 1 / (RingBint)leadingCoeff; //normalize senior coeff var decomposeResult = BerlekampDecompose(poly); factorRes.AddRange(decomposeResult); factorRes.polyCoef *= leadingCoeff; } else { //end Program.Log("Разложение для " + poly + " не требуется. Многочлен неприводимый."); factorRes.Add(poly); if (recheckPower) { for (int i = 0; i < factorRes.CountUniq; i++) { RingPolynomial divisor = factorRes.divisors[i].poly; int count = 1; RingPolynomial temp = divisor; while (true) { temp *= divisor; if ((this / temp).Reminder.IsNull()) { count++; } else { break; } } while (count > factorRes.divisors[i].count) { factorRes.Add(factorRes.divisors[i].poly); } } } Program.Log("Общее разложение на данном этапе: "); PrintDecompositionResult(factorRes); Program.recDepth--; return(factorRes); } //end if (recheckPower) { for (int i = 0; i < factorRes.CountUniq; i++) { RingPolynomial divisor = factorRes.divisors[i].poly; int count = 1; RingPolynomial temp = divisor; while (true) { temp *= divisor; if ((this / temp).Reminder.IsNull()) { count++; } else { break; } } while (count > factorRes.divisors[i].count) { factorRes.Add(factorRes.divisors[i].poly); } } } Program.Log("Общее разложение на данном этапе: "); PrintDecompositionResult(factorRes); Program.recDepth--; return(factorRes); }