(Esta respuesta se divide en cuatro secciones. La primera sección es una implementación en Mathematica de Daniel Schepler 's respuesta . La segunda sección describe el uso de las funciones incorporadas de Mathematica para abordar el ejemplo muy simétrico de la pregunta. Las secciones tercera y cuarta son código de Mathematica para el problema general de encontrar una reducción explícita de un polinomio dado en el álgebra abarcada por un conjunto dado de polinomios sin usar la maquinaria de Bases Groebner . La tercera sección, que implementa la versión multivariable de SmileyCraft 's respuesta , amplía los productos de las potencias de los generadores por el grado total $1$ , lo que probablemente requerirá menos tiempo y memoria para encontrar una reducción que el código de la cuarta sección (que se escribió al mismo tiempo y sin conocer la respuesta de SmileyCraft), que se expande tomando todos los productos de los pares del conjunto parcial actual).
inAlgebra[gens_List, vars_List, target_, gensSymbol_Symbol: None] :=
(* Adapted by Eric Towers from a description in https://math.stackexchange.com/a/3516363/123905 *)
Module[{
P, kernelGens, answerRels
},
kernelGens = GroebnerBasis[Join[Array[P, Length[gens]] - gens, {P - target}],
Join[Array[P, Length[gens]], {P}], vars, MonomialOrder -> EliminationOrder];
answerRels = Simplify[P /. Solve[# == 0, P]] & /@
Select[kernelGens, And[NumericQ[D[#, P]], D[#, P] != 0] &];
Flatten[ReplaceAll[
answerRels,
Rule @@ # & /@ Transpose[{Array[P, Length[gens]],
If[gensSymbol === None, gens, Array[gensSymbol, Length[gens]]]}]
], 1]
]
Esta versión añade una opción que no estaba presente en las versiones anteriores: la salida puede ser en términos de potencias de un símbolo indexado, en lugar de literalmente los generadores. El cuarto argumento es opcional. Si no se da, o se da como None
entonces la reducción del polinomio objetivo a una combinación lineal de productos de potencias de los generadores se da explícitamente. Si el cuarto argumento es un Símbolo, P
por ejemplo, entonces la salida se escribe como una combinación lineal de productos de potencias de ese símbolo indexado por el ordinal del generador en el gens
argumento. Ejemplo:
inAlgebra[{x1 + x2, x1 x2}, {x1, x2}, x1^2 + x2^2]
inAlgebra[{x1 + x2, x1 x2}, {x1, x2}, x1^2 + x2^2, None]
inAlgebra[{x1 + x2, x1 x2}, {x1, x2}, x1^2 + x2^2, P]
(* {-2 x1 x2 + (x1 + x2)^2} *)
(* {-2 x1 x2 + (x1 + x2)^2} *)
(* {P[1]^2 - 2 P[2]} *)
Aquí, P[1]
es el primer generador, x1 + x2
y P[2]
es el segundo generador, x1 x2
.
Ahora los otros ejemplos, duplicados usando el nuevo argumento opcional.
inAlgebra[{x1 + x2, x1^2 + x2^2}, {x1, x2}, x1 x2]
inAlgebra[{x1 + x2, x1^2 + x2^2}, {x1, x2}, x1 x2, Gen]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 + x1 x3 + x2 x3]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 + x1 x3 + x2 x3, P]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 x3]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 x3, T]
(* {1/2 (-x1^2 - x2^2 + (x1 + x2)^2)} *)
(* {1/2 (Gen[1]^2 - Gen[2])} *)
(* {1/2 (-x1^2 - x2^2 - x3^2 + (x1 + x2 + x3)^2)} *)
(* {1/2 (P[1]^2 - P[2])} *)
(* {1/6 ((x1 + x2 + x3)^3 - 3 (x1 + x2 + x3) (x1^2 + x2^2 + x3^2) + 2 (x1^3 + x2^3 + x3^3))} *)
(* {1/6 (T[1]^3 - 3 T[1] T[2] + 2 T[3])} *)
El ejemplo está mucho más estructurado que el problema general del que parte la pregunta. El siguiente código de Mathematica expresa el polinomios simétricos elementales en términos de suma de potencias de polinomios simétricos mucho más directamente que calcular el $\Bbb{R}$ -span de aproximaciones sucesivas al monoide de potencias de los generadores. Para ello se utiliza el teorema fundamental de los polinomios simétricos, según el cual cualquier polinomio simétrico puede escribirse como un polinomio en los polinomios simétricos elementales. Entonces, invertimos la relación para escribir los polinomios simétricos elementales en términos de los polinomios simétricos de la suma de potencias.
elementariesAsSymmetricPowerSums[n_] := Module[{
vars,
powerSumsymmetricPolynomials,
elementarySymmetricReductions
},
vars = Array[x, n];
powerSumsymmetricPolynomials = Table[Sum[x[i]^power, {i, 1, n}], {power, 1, n}];
elementarySymmetricReductions =
SymmetricReduction[#, vars, Array[(esp[n, #] &), n]][[1]] & /@
powerSumsymmetricPolynomials;
Solve[Array[pssp[n, #] &, n] == elementarySymmetricReductions, Array[(esp[n, #] &), n]]
]
En este caso, utilizamos los símbolos \begin{align*} \mathrm{pssp}[v,p] &= \sum_{i=1}^v x_i^p \\ \mathrm{esp}[v,p] &= \sum_{1 \leq i_1 \leq i_2 \leq \cdots \leq i_p \leq v} x_{i_1} x _{i_2}\cdots x_{i_p} \text{,} \end{align*} donde $v$ es el número de variables, $p$ es el grado total de los términos del polinomio, $\mathrm{pssp}$ da polinomios simétricos de suma de potencias, y $\mathrm{esp}$ da los polinomios simétricos elementales.
elementariesAsSymmetricPowerSums[3]
(* {{esp[3, 1] -> pssp[3, 1],
esp[3, 2] -> 1/2 (pssp[3, 1]^2 - pssp[3, 2]),
esp[3, 3] -> 1/6 (pssp[3, 1]^3 - 3 pssp[3, 1] pssp[3, 2] + 2 pssp[3, 3])}} *)
Esto dice \begin{align*} x_1 + x_2 + x_3 &= x_1 + x_2 + x_3 \\ x_1 x_2 + x_1 x_3 + x_2 x_3 &= \frac{1}{2}(x_1 + x_2 + x_3)^2 - (x_1^2 + x_2^2 + x_3^2) \\ x_1 x_2 x_3 &= \frac{1}{6}(x_1 + x_2 + x_3)^3 - 3(x_1 + x_2 + x_3)(x_1^2 + x_2^2 + x_3^2) + 2 (x_1^3 + x_2^3 + x_3^3) \end{align*}
Este método debería ser capaz de manejar rápidamente instancias mucho más grandes. Como ejemplo...
elementariesAsSymmetricPowerSums[8]
(* {{esp[8, 1] -> pssp[8, 1],
esp[8, 2] -> 1/2 (pssp[8, 1]^2 - pssp[8, 2]),
esp[8, 3] -> 1/6 (pssp[8, 1]^3 - 3 pssp[8, 1] pssp[8, 2] + 2 pssp[8, 3]),
esp[8, 4] -> 1/24 (pssp[8, 1]^4 - 6 pssp[8, 1]^2 pssp[8, 2] + 3 pssp[8, 2]^2 + 8 pssp[8, 1] pssp[8, 3] - 6 pssp[8, 4]),
esp[8, 5] -> 1/120 (pssp[8, 1]^5 - 10 pssp[8, 1]^3 pssp[8, 2] + 15 pssp[8, 1] pssp[8, 2]^2 + 20 pssp[8, 1]^2 pssp[8, 3] - 20 pssp[8, 2] pssp[8, 3] - 30 pssp[8, 1] pssp[8, 4] + 24 pssp[8, 5]),
esp[8, 6] -> 1/720 (pssp[8, 1]^6 - 15 pssp[8, 1]^4 pssp[8, 2] + 45 pssp[8, 1]^2 pssp[8, 2]^2 - 15 pssp[8, 2]^3 + 40 pssp[8, 1]^3 pssp[8, 3] - 120 pssp[8, 1] pssp[8, 2] pssp[8, 3] + 40 pssp[8, 3]^2 - 90 pssp[8, 1]^2 pssp[8, 4] + 90 pssp[8, 2] pssp[8, 4] + 144 pssp[8, 1] pssp[8, 5] - 120 pssp[8, 6]),
esp[8, 7] -> (1/5040)(pssp[8, 1]^7 - 21 pssp[8, 1]^5 pssp[8, 2] + 105 pssp[8, 1]^3 pssp[8, 2]^2 - 105 pssp[8, 1] pssp[8, 2]^3 + 70 pssp[8, 1]^4 pssp[8, 3] - 420 pssp[8, 1]^2 pssp[8, 2] pssp[8, 3] + 210 pssp[8, 2]^2 pssp[8, 3] + 280 pssp[8, 1] pssp[8, 3]^2 - 210 pssp[8, 1]^3 pssp[8, 4] + 630 pssp[8, 1] pssp[8, 2] pssp[8, 4] - 420 pssp[8, 3] pssp[8, 4] + 504 pssp[8, 1]^2 pssp[8, 5] - 504 pssp[8, 2] pssp[8, 5] - 840 pssp[8, 1] pssp[8, 6] + 720 pssp[8, 7]),
esp[8, 8] -> (1/40320)(pssp[8, 1]^8 - 28 pssp[8, 1]^6 pssp[8, 2] + 210 pssp[8, 1]^4 pssp[8, 2]^2 - 420 pssp[8, 1]^2 pssp[8, 2]^3 + 105 pssp[8, 2]^4 + 112 pssp[8, 1]^5 pssp[8, 3] - 1120 pssp[8, 1]^3 pssp[8, 2] pssp[8, 3] + 1680 pssp[8, 1] pssp[8, 2]^2 pssp[8, 3] + 1120 pssp[8, 1]^2 pssp[8, 3]^2 - 1120 pssp[8, 2] pssp[8, 3]^2 - 420 pssp[8, 1]^4 pssp[8, 4] + 2520 pssp[8, 1]^2 pssp[8, 2] pssp[8, 4] - 1260 pssp[8, 2]^2 pssp[8, 4] - 3360 pssp[8, 1] pssp[8, 3] pssp[8, 4] + 1260 pssp[8, 4]^2 + 1344 pssp[8, 1]^3 pssp[8, 5] - 4032 pssp[8, 1] pssp[8, 2] pssp[8, 5] + 2688 pssp[8, 3] pssp[8, 5] - 3360 pssp[8, 1]^2 pssp[8, 6] + 3360 pssp[8, 2] pssp[8, 6] + 5760 pssp[8, 1] pssp[8, 7] - 5040 pssp[8, 8])}} *)
Lo anterior es muy específico para su ejemplo. Pero si su ejemplo es muy cercano a sus problemas más generales, esto podría ser un mejor punto de partida que el código genérico, a continuación.
La primera versión de la búsqueda de propósito general a través del tramo de productos de potencias de generadores de bajo grado total era muy ineficiente a la hora de ampliar la colección de productos de potencias de generadores. En lugar de generar los nuevos términos multiplicando (frecuentemente de forma redundante) pares de miembros de $\Sigma$ . En lugar de ello, utilizamos los composiciones enteras para construir directamente los vectores de los exponentes en los productos de las potencias, por lo que generamos directamente todos los términos de grado total específico de una vez, sin producir ningún duplicado que debamos eliminar posteriormente.
inAlgebra[gens_List, vars_List, target_] :=
Module[{
C,
compositions, expansion,
partialRSpanningSet, realSolution,
iterationDepth, attemptedSolution
},
compositions[total_, parts_] :=
Flatten[Table[
Join[{k}, #] & /@ compositions[total - k, parts - 1],
{k, 0, total}
], 1];
compositions[total_, 1] := {{total}};
expansion[set_List, totalOrder_] := (Times @@ Power[set, #]) & /@ compositions[totalOrder, Length[set]];
realSolution[set_] :=
SolveAlways[C[0] + Table[C[i], {i, 1, Length[set]}].set == target, vars];
iterationDepth = 1;
partialRSpanningSet = Union[{}, expansion[gens, iterationDepth]];
attemptedSolution = realSolution[partialRSpanningSet];
While[Not[And[Head[attemptedSolution] === List, Length[attemptedSolution] > 0]],
iterationDepth++;
If[iterationDepth > $IterationLimit,
Print["$IterationLimit exceeded. See documentation for $IterationLimit to see how to increase $IterationLimit in a Block[]."];
Abort[];
];
partialRSpanningSet = Join[partialRSpanningSet, expansion[gens, iterationDepth]];
attemptedSolution = realSolution[partialRSpanningSet];
];
(C[0] + Table[C[i], {i, 1, Length[partialRSpanningSet]}].partialRSpanningSet) /. attemptedSolution
]
Comprobando la salida de nuevo...
inAlgebra[{x1 + x2, x1^2 + x2^2}, {x1, x2}, x1 x2]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 + x1 x3 + x2 x3]
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 x3]
(* {1/2 (x1 + x2)^2 + 1/2 (-x1^2 - x2^2)} *)
(* {1/2 (x1 + x2 + x3)^2 + 1/2 (-x1^2 - x2^2 - x3^2)} *)
(* {1/6 (x1 + x2 + x3)^3 - 1/2 (x1 + x2 + x3) (x1^2 + x2^2 + x3^2) + 1/3 (x1^3 + x2^3 + x3^3)} *)
(Esta es la primera versión del código de Mathematica para reducir un polinomio dado en una combinación lineal de productos de potencias de un conjunto dado de generadores. Más arriba aparece una versión a veces más rápida y, muy probablemente, con menos consumo de memoria).
El siguiente código de Mathematica hace lo que usted solicita.
inAlgebra[gens_List, vars_List, target_] :=
Module[{C,
iterate,
partialRSpanningSet, realSolution,
iterationDepth, attemptedSolution
},
iterate[set_List] := Union[set,
Reap[
Table[
Sow[Times[set[[f]], set[[g]] ]],
{f, 1, Length[set]}, {g, f, Length[set]}]][[2, 1]]
];
realSolution[set_] :=
SolveAlways[C[0] + Table[C[i], {i, 1, Length[set]}].set == target,
vars];
partialRSpanningSet = gens;
iterationDepth = 0;
attemptedSolution = realSolution[partialRSpanningSet];
While[Not[And[Head[attemptedSolution] === List,
Length[attemptedSolution] > 0]],
partialRSpanningSet = iterate[partialRSpanningSet];
iterationDepth++;
If[iterationDepth > $IterationLimit,
Print[
"$IterationLimit exceeded. See documentation for $IterationLimit to see how to increase $IterationLimit in a Block[]."];
Abort[];
];
attemptedSolution = realSolution[partialRSpanningSet];
];
(C[0] + Table[C[i], {i, 1, Length[partialRSpanningSet]}].partialRSpanningSet) /. attemptedSolution
]
Se basa en la siguiente observación: un producto de combinaciones lineales de elementos de $\Sigma$ es una combinación lineal de productos de potencias del $P_i$ . Así, primero buscamos una combinación lineal de los $P_i$ que da el polinomio objetivo. Luego buscamos combinaciones lineales entre los productos de $\leq 2$ de la $P_i$ entonces entre los productos de $\leq 3$ de la $P_i$ continuando hasta que encontremos una solución, abortemos por exceso de iteración o se termine externamente. Usos:
inAlgebra[{x1 + x2, x1^2 + x2^2}, {x1, x2}, x1 x2]
(* {1/2 (x1 + x2)^2 + 1/2 (-x1^2 - x2^2)} *)
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 + x1 x3 + x2 x3]
(* {1/2 (x1 + x2 + x3)^2 + 1/2 (-x1^2 - x2^2 - x3^2)} *)
inAlgebra[{x1 + x2 + x3, x1^2 + x2^2 + x3^2, x1^3 + x2^3 + x3^3}, {x1, x2, x3}, x1 x2 x3]
(* {1/6 (x1 + x2 + x3)^3 - 1/2 (x1 + x2 + x3) (x1^2 + x2^2 + x3^2) + 1/3 (x1^3 + x2^3 + x3^3)} *)