Processing math: 100%

9 votos

Multiplicar las raíces de polinomios utilizando sólo sus coeficientes enteros

Estoy tratando de escribir una función que toma los coeficientes enteros de dos polinomios y devuelve los coeficientes de un polinomio que tiene una raíz para cada forma en que se puede multiplicar un par de raíces del par de polinomios de entrada.

La aplicación que tenía en mente es la representación exacta de números algebraicos. En lugar de almacenar un número dado x como un flotador o un símbolo, almacenaría los coeficientes de un polinomio que tiene x como raíz. Operar con números almacenados de esa manera, sin perder precisión, requiere operar con las raíces sin calcularlas realmente.

(Tengo claro que esta estrategia de representación tiene graves defectos, tanto en términos de eficiencia como de multiplicidad de soluciones, pero sigo queriendo resolver el problema).

Ejemplo

Supongamos que las listas de coeficientes de los polinomios de entrada son [1,0,-1] y [1,5,6]. Es decir, la entrada es el polinomio x21 y el polinomio x2+5x+6 . Tienen raíces 1,+1 y 2,3 respectivamente. Por lo tanto, el polinomio de salida debe tener raíces 12,13,12,13=3,2,2,3 y es igual a (x3)(x2)(x+2)(x+3) que es x413x2+36 y así la salida es [1,0,-13,0,36].

Parcialmente resuelto

He trabajado en el problema, y he conseguido factorizar los efectos de los polinomios de entrada en piezas separadas (eso creo, al menos). Me llevaría demasiado tiempo explicar cómo llegué a donde estoy... basta con decir que fue muy ad-hoc.

La siguiente función parece calcular lo que quiero, y es casi independiente de las raíces:

var decreasings = DecreasingSequencesOfSize(
    length: poly1.Degree, 
    total: indexOfOutputCoefficient, 
    max: poly2.Degree);

var outputCoefficient =
    (from coefRepeatSequence in decreasings
     let coefs2Factor = 
        coefRepeatSequence
        .Select(e => coefs2[e])
        .Product()
     let coefs1Factor = F(coefRepeatSequence, roots1, coefs1)
     select coefs2Factor*coefs1Factor
    ).Sum();

private static BigInteger F(IReadOnlyList<int> d, IReadOnlyList<BigInteger> roots, IReadOnlyList<BigInteger> coefs) {
    return (from p in d.DistinctPermutations()
            select p.Select((e, i) => BigInteger.Pow(roots[i], e)).Product()
           ).Sum();
}

Lo siento si no ha quedado del todo claro. He reducido el código todo lo posible.

He aquí una formulación alternativa de F, como función recursiva:

private static BigInteger F2(IReadOnlyList<int> d, IReadOnlyList<BigInteger> roots) {
    var zeroes = d.Count(e => e == 0);
    if (zeroes == d.Count) return 1;

    var min = d.Min();
    if (min > 0) {
        var mecs = d.Where(e => e > 0).Select(e => e - min).ToArray();
        return BigInteger.Pow(roots.Product(), min) * F2(mecs, roots);
    }

    var decs = d.Where(e => e > 0).ToArray();
    return (from x in roots.Choose(d.Count - zeroes)
            select F2(decs, x)
            ).Sum();
}

Como puedes ver, la única dependencia de las raíces es para calcular la función F. Parece que siempre se puede reducir a una expresión en términos de los coeficientes... Puedo hacerlo a mano para polinomios de grado pequeño, y puedo tropezar para reducirlo para los más grandes, pero no veo el patrón todavía...

Question

Así que...

  • ¿Está ya resuelto este problema?
  • ¿Hay alguna técnica que deba conocer y que pueda ayudar?
  • ¿Me estoy perdiendo algo obvio?

Actualización

He utilizado la solución de Jyrki y la he puesto en práctica. Puedes encontrar el código en mi Repo de github de PolyNumber .

6voto

Noam D. Elkies Puntos 17729

El problema se puede resolver en general utilizando la teoría clásica de resultantes . Para formar el polinomio cuyas raíces son productos z=xy de raíces de P(x)=0 y Q(y)=0 , toma la resultante de P(x) y xdQ(z/x) con respecto a x , donde d=degQ . En gp :

M(P,Q) = polresultant(P, x^poldegree(Q)*subst(Q,y,z/x), x)

y luego para su ejemplo

M(x^2-1, y^2+5*y+6)

devuelve z413z2+36 como debería.

5voto

Se sugiere el siguiente algoritmo. Sea α sea una raíz desconocida de un polinomio f(x) de grado n y β sea una raíz desconocida de un polinomio g(x) de grado m .

Utilizando la ecuación f(α)=0 nos permite reescribir cualquier poder αk como una combinación lineal de 1,α,α2,,αn1 . Del mismo modo, utilizando la ecuación g(β)=0 nos permite reescribir cualquier poder β como un lineal combinación lineal de 1,β,β2,,βm1 . Uniendo estas dos piezas se demuestra que podemos escribir cualquier monomio αkβ como una combinación lineal del mn cantidades αiβj,0i<n,0j<m. Denote ck=αiβj , donde k=mi+j oscila entre 0 a mn1 .

A continuación vamos a utilizar las expansiones de (αβ)t , 0tmn en términos de ck :s. Que estos sean (αβ)t=mn1k=0aktck. Aquí los coeficientes atk son números enteros. Buscamos encontrar enteros xt,t=0,1,,mn , de tal manera que mnt=0xt(αβ)t=0.() Sustituyamos nuestra fórmula para la potencia (αβ)t arriba. La ecuación () se convierte en 0=tkxtatkck=k(txtakt)ck. Esto será trivialmente cierto, si los coeficientes de todos los ck :s se desvanecen, es decir, es la ecuación mnt=0aktxt=0() es válida para todos los k=0,1,2,,mn1 . Aquí hay mn ecuaciones lineales homogéneas en el mn+1 incógnitas xt . Por tanto, el álgebra lineal dice que tenemos garantizado el éxito en el sentido de que existe un vector no trivial (x0,x1,,xmn) de números racionales que es una solución de () . Además, multiplicando por el mínimo común múltiplo de los denominadores podemos hacer que todos los xt :s enteros.

El polinomio F(x)=mnt=0xtxt es entonces una respuesta.


Hagamos su ejemplo de f(x)=x21 y g(x)=x2+3x+2 . Aquí f(α)=0 nos dice que α2=1 . Del mismo modo, g(β)=0 nos dice que β2=3β2 . Esto es todo lo que necesitamos de los polinomios. Aquí c0=1 , c1=β , c2=α y c3=αβ . Escribamos la potencia (αβ)t , t=0,1,2,3,4 en términos de ck :s. (αβ)0=1=c0. (αβ)1=αβ=c3. (αβ)2=α2β2=1(3β2)=2c03c1. (αβ)3=αβ(3β2)=α(3β22β)=α(9β+62β)=α(7β+6)=6c2+7c3. (αβ)4=(3β2)2=9β2+12β+4=(27β18)+12β+4=1415β=14c015c1. Así pues, buscamos soluciones del sistema lineal homogéneo (1020140030150006001070)(x0x1x2x3x4)=0. Busquemos una solución con x4=1 (si los polinomios con los que comenzó son mónicos, entonces esto siempre funciona AFAICT). La tercera ecuación nos dice que deberíamos tener x3=0 . La segunda ecuación nos permite resolver que x2=5 . La última ecuación y nuestro conocimiento de x3 dice que x1=0 . La primera ecuación dice entonces que x0=4. Esto nos da la salida x45x2+4. Las posibilidades de α son ±1 y las posibilidades de β son 1 y 2 . Podemos comprobar fácilmente que los cuatro productos posibles ±1 y ±2 son ceros de este polinomio cuártico.

Mi solución al sistema lineal fue ad hoc, pero hay algoritmos conocidos para ello: eliminación, solución explícita en términos de menores,...

3voto

El problema se ha resuelto, entran en el polinomio simétrico:

http://en.wikipedia.org/wiki/Symmetric_polynomial#Relation_with_the_roots_of_a_monic_univariate_polynomial

1voto

Cameron MacFarland Puntos 27240

Auto-respuesta. El código relevante de mi implementación actual, que sólo maneja polinomios enteros mónicos (sin incluir las toneladas de cosas de tipo matriz/polinomio):

private static IEnumerable<IntPolynomial<XTerm>> RewritePolyBasisUsing(XTerm termToRewrite,
                                                                       IntPolynomial<XTerm> rewrittenTerm) {
    var X = new XTerm(1);
    var r = rewrittenTerm - termToRewrite;

    var cur = (IntPolynomial<XTerm>)1;
    yield return cur;

    for (var i = 1; i < termToRewrite.XPower; i++) {
        cur *= X;
        yield return cur;
    }
    while (true) {
        cur = cur*X;
        var factor = cur.Coefficient(termToRewrite);
        cur += r*factor;
        yield return cur;
    }
}
private static IEnumerable<IntPolynomial<XTerm>> RewritePolyBasisUsing(IntPolynomial<XTerm> poly) {
    var termToRewrite = poly.Coefficients.MaxBy(e => e.Key.XPower);
    if (termToRewrite.Value != 1) throw new NotImplementedException();
    var rewrittenTerm = termToRewrite - poly;
    return RewritePolyBasisUsing(termToRewrite.Key, rewrittenTerm);
}

public static IntPolynomial<XTerm> MultiplyRoots(this IntPolynomial<XTerm> poly1,
                                                 IntPolynomial<XTerm> poly2) {
    var deg1 = poly1.Degree();
    var deg2 = poly2.Degree();

    var maxDegreeOfResult = deg1*deg2;
    if (maxDegreeOfResult == 0) return 1;

    var rewrittenPowers1 = RewritePolyBasisUsing(poly1).Select(p => p.ToPolynomialOverVariable1Of2());
    var rewrittenPowers2 = RewritePolyBasisUsing(poly2).Select(p => p.ToPolynomialOverVariable2Of2());
    var rewrittenPowerPairs =
        rewrittenPowers1.Zip(rewrittenPowers2,
                             IntPolynomial<XYTerm>.Multiply)
                        .Take(maxDegreeOfResult + 1);

    var linearSystem = IntMatrix.FromColumns(
        from col in rewrittenPowerPairs
        select from row in maxDegreeOfResult.Range()
               let exponentForX = row/deg2
               let exponentForY = row%deg2
               select col.Coefficient(new XYTerm(exponentForX, exponentForY)));

    var solvedSystem = linearSystem.Reduced();

    var degreeOfSolution = solvedSystem.Rows.Count(row => row.Any(cell => cell != 0));

    var lowCoefficients = solvedSystem.Columns[degreeOfSolution].Take(degreeOfSolution);

    return Polynomial.XToThe(degreeOfSolution) - lowCoefficients.TimesPolynomialBasis();
}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X