10 votos

Cómo de manera eficiente representar y manipular los polinomios en el software?

He empezado a trabajar en un paquete (escrito en matlab por ahora) que entre otras cosas debe ser capaz de representar y manipular (comparar, sumar, multiplicar, diferencia, etc) polinomios en varias variables. Hasta el momento, mi enfoque ha sido el siguiente

  • Tengo una clase de cada uno de los objetos de los cuales representa un polinomio.
  • En cada polinomio objeto, yo almacenar los símbolos de las variables que aparecen en el polinomio (decir $x$$y$), el número de componentes de cada una de estas variables (decir $3$ $2$ si $x\in\mathbb{R}^3$$y\in\mathbb{R}^2$).
  • También tengo un modo fijo (algunas de función $r$) de la generación de todos los multi-índices de alguna dimensión y un poco de orden. Por ejemplo, le digo a esta función que la dimensión de la base de que el espacio es $2$, y el orden de la monomials estoy interesado en el es $3$ y devuelve

$$r(2,3)=\left(\begin{bmatrix}3\\ 0\end{bmatrix},\begin{bmatrix}2\\ 1\end{bmatrix},\begin{bmatrix}1\\ 2\end{bmatrix},\begin{bmatrix}0\\ 3\end{bmatrix}\right)$$

  • Using $r$ I can systematically construct on the go the monomial basis for the space of polynomials of some degree in some variables (just identify the monomial $x_1^3$ with $[3,0]^T$, etc). Furthermore, once I fix how I order the variables (for example, first $x$ then $s$), and the number of components each has, then the order in which $r$ escupe los vectores de la base es fija.

  • Yo uso el orden en que $r$ devuelve a cabo los vectores para representar el polinomio de interés como el vector de los coeficientes de dicho polinomio con respecto a la monomio base, en el que el $i^{th}$ entrada del vector a es el coeficiente de la $i^{th}$ polinomio devuelto por $r$.

Por ejemplo, para representar

$$q(x)=2x_1^2+x_1x_2-3x_2+1$$

$r$ gives us

$$r(2,0)=\left(\begin{bmatrix}0\\ 0\end{bmatrix}\right),\quad r(2,1) =\left(\begin{bmatrix}1\\ 0\end{bmatrix},\begin{bmatrix}0\\ 1\end{bmatrix}\right),\quad r(2,2) =\left(\begin{bmatrix}2\\ 0\end{bmatrix},\begin{bmatrix}1\\ 1\end{bmatrix},\begin{bmatrix}0\\ 2\end{bmatrix}\right).$$

and thus I end up representing $q$ as

q.symbols = x
q.varnumber = 2
q.coefs = [1,0,-3,2,1]

However, I this seems to me as a poor way of doing things. In particular, I end up having to do a lot of searching through the results returned by $r$. For example, if I'd like to combine a polynomial $p$ in $x$ and another $q$ in $y$ (say add them together), I end up doing something along the lines as

  • Use $r$ to generate a basis of monomials of sufficiently high degree (in the case of adding of degree $\max\{\deg(p),\deg(q)\}$) in both $x\in\mathbb{R}^3$ and $y\in\mathbb{R}^2$.

  • Buscar y comparar los componentes apropiados de la ($5$-dimensional) vectores de la base para $p+q$ ($3$- dimensional) vectores de la base de $p$ y por separado el ($2$-dimensional) de $q$. Una vez que identificar cuál de los vectores de la base de $p+q$ corresponden a cual de $p$ y que de $q$, entonces sé que los coeficientes para sumar y donde almacenarlos. En realidad, en este ejemplo, no hay coeficientes se suman porque $p$ $q$ están en diferentes variables, pero en general este no es el caso...

Ahora muchos de estos problemas se resolverían si hubo un bijection que era barato para calcular e invertir de $\mathbb{N}$ y el conjunto de monomials en varias variables. Por ejemplo, uno en el que tenemos una fórmula analítica para (sin embargo, yo no podía pensar en uno, y estoy seguro de que hay uno). También he mirado en línea y he visto menciones de diferentes formas de ordenar los polinomios (lexicográfica, clasificados lexicográfica, ponderado, etc), con propiedades diferentes.

Sin embargo, es claro para mí que uno a utilizar y por qué (yo también sé nada de nada acerca de álgebra computacional). Así que mis preguntas son:

  • Alguna sugerencia sobre cómo mejorar el anterior, reducir el coste computacional en su mayoría, pero consideraciones acerca de la memoria también sería genial (estoy abierto a cambiar por completo la manera en la que he estado en representación de polinomios).
  • ¿Cómo es esto generalmente se hace en álgebra computacional paquetes?
  • Y/o sugerencias para referencias donde puedo encontrar las respuestas a estas preguntas.

PD: me importa sobre todo la manipulación arbitraria, reales, polinomios en $\mathbb{R}^n$, y no aquellas que se encuentran algunos de módulo, ideales, etc. Así las cosas así que de manera eficiente puede calcular la mínima generación de conjuntos de estos, Grobner base, etc, no es probablemente muy importante para mí (puedo estar equivocado, en cuyo caso, por favor me corrija). Tampoco estoy muy preocupado acerca de la aplicación de algoritmos para la división de polinomios y factorización.

Edit: Gracias a todos por las respuestas. Han sido útiles en la mejora de (mucho) de la aplicación. En caso de que alguien curioso, un (siendo muy duro, pero funciona), la versión de el código se puede encontrar aquí.

Edit 2: En caso de que alguien esté interesado, actualmente estoy almacenar los polinomios mediante el almacenamiento de su no-cero de los coeficientes en una matriz junto con su clasificación en la gradual lexicográfica del orden (la matriz ordenados por el orden). Para multiplicar y agregar voy de ida y vuelta desde las filas de la monomials el uso de alguna función recursiva he cocinado.

9voto

Cem Kalyoncu Puntos 4740

Nota: esta respuesta resultó un poco TLDR; si quieres una sugerencia directa (en lugar de una encuesta), saltar el último párrafo.

Desde el típico caso de uso se ha convertido ahora en claro (en el último comentario), sugiero que usted debe ir a través de este 2007 presentación por M. Gastineau, especialmente diapositivas 8-15. Es un resumen de la disposición opciones de representación y también lo que es utilizado por varios CAS. A continuación, usted debe descremada sobre la secuela de esa presentación, especialmente diapositivas 28-30, suponiendo que la multiplicación es un caso de uso habitual para usted, incluso si eso no es realmente el caso, es que vale la pena mirar esta presentación también porque se menciona lo que es utilizado por varios otros CAS paquetes como la representación que de alguna manera no se menciona en la primera presentación.

Poniendo a estos en conjunto, hay una buena cantidad de información, por ejemplo, GIAC y MAGMA uso hashmaps, GINAC y Mathematica 5 el uso de árboles de Arce 10 usa Dag, Maxima utiliza una lista recursiva, Singular utiliza monomio listas ordenadas (que funcionan sorprendentemente bien) etc. [Supongo que no hay ninguna aplicación información sobre las versiones más recientes de los productos comerciales.] Sospecho que algunos de los más oscuros de las representaciones, como los utilizados por VIAJE (que es Gastineau la propia CAS kernel) a pesar de ser rápido, puede ser difícil de código... Pari/GP aparece demasiado rápido basado en la apertura de la diapositiva de la primera presentación, pero no nos dice lo que la representación que se utiliza. Buscando en su FAQ parece que multivariante polinomios se simuló utilizando univariante, así que tal vez es por eso que la info no estaba allí... y supongo que ese truco no puede ser satisfactoria en su aplicación. (SAGE cual ha sido discutido por MvG en su respuesta también se utiliza hashmaps [Python dicts].)

He mirado en Singular fuentes un poco porque a juzgar por su idea de la aplicación que se comprometió a ser relativamente sencillo. Por desgracia, el código fuente de Singular es bastante desordenado y desigual, comentó. Una cosa que yo podía reunir a pesar de que es que el uso de cubo tipo para mantener su monomio listas en orden.

Desde los puntos de referencia en las diapositivas son ~8 años de edad, yo no los toman por su valor nominal para la versión actual de los sistemas mencionados. La conclusión es que hay muchas opciones de representación y necesita experimentar para encontrar lo que funciona mejor para usted. Si va a implementar esto en lenguaje de alto nivel como Python, algunos de los de bajo nivel de optimizaciones que dependen de la estructura de diseño para lograr la caché de la localidad puede que no funcione a menos que use algo como arrays de NumPy.

Hay una más reciente (2010) el papel de la (nueva) aplicación de la "escasa" multivariante de polinomios en Maple 14 por M. Monagan y R. Pearce. Es interesante que se revive una vieja idea de embalaje de varios exponentes en una palabra; además de eso, es simplemente lleno, ordenados lexicográficamente monomio de la matriz, por lo que la implementación es bastante simple. Y afirma haber golpeado VIAJE. El documento también puntos de referencia de los otros sospechosos habituales, pero en las versiones más recientes (por ejemplo, Mathematica 7) y en más operaciones que sólo la multiplicación. La razón por la que pongo "disperso" entre comillas es que los polinomios utilizados en este trabajo, no son todos los que dispersa; de hecho, son similares a lo que fue utilizado en el 2007 VIAJE de presentación que no llame a tales polinomios dispersas, por ejemplo, este trabajo es el uso de $(1+x+y+z)^{20}+1$ a que ~1700 términos. Así que yo sugeriría el uso de este Arce 14 representación tal y como parece estar cerca (si no elactual "estado del arte" en lo que a rendimiento se va y es bastante simple de implementar.

5voto

gagneet Puntos 4565

Como Alex escribió, me gustaría dejar de pensar en varias variables con múltiples componentes. Si usted tiene $x\in\mathbb R^3$$y\in\mathbb R^2$, entonces usted tiene cinco variables escalares $x_1,x_2,x_3,y_1,y_2$ o, equivalentemente, uno de los cinco dimensiones vector de la variable. Es posible que desee mantener un seguimiento de la original de la agrupación en algún lugar, y utilizar esa información en la construcción de polinomios o la presentación o la interpretación de los resultados, pero para el grueso de la operación, esta información simplemente debe ser llevada, sin ningún impacto en las operaciones de ir.

Una advertencia aquí es que usted debe asegurarse de que esta información es consistente. Si usted tiene un polinomio en $x_1,x_2,x_3$ y otro polinomio en $y_1,y_2$ y queremos multiplicar estas acciones, es posible que primero debas convertir a un solo cinco dimensiones de la representación. Al declarar todas las variables que va a utilizar hasta el frente, usted puede evitar realizar este tipo de conversiones en varias ocasiones durante el curso de su cálculo. Sage, PARI y probablemente otros también requiere la declaración de un polinomio anillo, explícitamente nombramiento de todos los indeterminates, antes de que usted puede construir polinomios.

En mi experiencia, polinomios multivariados en la práctica tienden a ser bastante escasa. Esto significa que si usted arreglar el total de la medida, sólo una pequeña fracción de los posibles monomials que podría encajar en que el total de grado están presentes, con los no-cero coeficiente. Por lo tanto, yo no usaría un vector que almacena todos los coeficientes. En su lugar yo haría uso de una escasa representación, donde tienen esencialmente un mapa de una tupla de poderes (es decir, $x_1^2x_3x_4^3$ sería representado como $(2,0,1,3)$) a la correspondiente a los no-cero de los coeficientes.

Sé que al menos una implementación dentro de Sage va un paso más allá, y hace incluso que el exponente de la tupla escasa, por lo que las variables no utilizar en su polinomio no perder espacio.

Formalmente hablando, un mapa de coeficientes de $n$ variables con coeficientes reales sería una función $f:\mathbb N^n\to\mathbb R$. Poder vectores que no están explícitamente almacenada resultaría en $f$ cero para estos. Que corresponde a un polinomio de la siguiente manera:

$$ p(X_1,\dots,X_n) = \sum_{v\in\mathbb N^n}\left(f(v)\cdot\prod_{i=1}^nX_i^{v_i}\right)$$

Puede ser beneficioso si el mapa se puede iterar sobre todas sus entradas en el plazo de la orden (por ejemplo, primer grado, y luego invertir lexicográficamente), en lugar de orden arbitrario. Un árbol rojo-negro como el backend de la aplicación podría ser mejor que un hash mapa, al menos para algunas operaciones. Entonces, ¿cómo hacer tus operaciones básicas de trabajo en esta configuración?

  • Comparación: Iterar a través de las teclas en orden, en ambos polinomios de forma simultánea. Una vez que haya una diferencia clave, o un coeficiente de diferencia por la misma llave, conocer el orden.
  • Además: Hacer una copia de un argumento (a menos que usted sabe que usted puede modificar la entrada), luego iterar sobre el otro argumento. Para cada una de las teclas durante la iteración, comprobar si la clave ya está presente en la suma. Si es así, añadir los coeficientes, de lo contrario agregar un nuevo par clave-valor para el resultado. Usted desea asegurarse de que usted caída de los coeficientes que se convierten en cero.
  • Multiplicación: el Uso de dos bucles anidados, se itera sobre todos los vínculos, y agregar resultante de los coeficientes como he descrito para la adición.

2voto

Yves Daoust Puntos 30126

A menos que su polinomios son siempre denso (en el que caso de que un tensor sería apropiado, pero enorme), veo dos opciones:

  • mantener la lista de variables, y para cada término de mantener el coeficiente y la lista de los exponentes. Para $v$ variables e $t$ términos, podrás almacenar una lista de $v$ identificadores, una lista de $t$ y los coeficientes de una $t\times v$ matriz de los exponentes.

  • mantener la lista de términos, cada uno representado por un coeficiente y una lista de los identificadores de variable con un exponente. Para un promedio de $f$ factores por plazo, vas a la tienda de $t$ coeficientes, $t\times f$ identificadores y $t\times f$ exponentes. (Esencialmente, usted está almacenando la cruda expresión polinómica.)

Los costes de almacenamiento son $vI+tC+tvE$ vs $tfI+tC+tfE$. El acceso de los costos dependen de los patrones de acceso.

En ambos casos, es probablemente aconsejable mantener los términos en una normalizado de la orden (variables en orden y los términos en orden lexicográfico, $a^2b^3=aabbb$ después $ab^5=abbbbb$).

1voto

AlexR Puntos 20704

¿Por qué no almacenar los coeficientes en un $n$-tensor de donde $n$ es el número de variables? Tenga en cuenta que usted está exagerando distinguiendo $x_i$$y_i$, acaba de hacer un nuevo vector $$z = \pmatrix{x\\y}$$ and store the "original" dimensions. This will mean you only need to represent polynomials of one $$n-dimensional de las variables.

Este pierda un poco de memoria, pero será menos podar a errores de programación. También se puede utilizar un soarse tensor de paquete para almacenar los tensores como disperso. Esto debería reducir la cantidad de la pérdida de memoria y puede ser incluso mejor en algunos casos (cuando los polinomios tienen escasa coeficientes)

0voto

mathreadler Puntos 3517

En Matlab, podría almacenar los índices en un ND-matriz de, al menos si hay un límite superior en el orden. para un N-variable polinomio : [c1,c2,...,cN] = ndgrid(1:max,1:max,...,1:max);

A continuación, puede vectorizar el c:s, con matlab de la indización puede entonces definir lo que los operadores que usted desea (integración, la diferenciación, la multiplicación) muy bien sistemática y jerárquica con productos de kronecker.

Edit: por supuesto, para el alta de los pedidos y de muchas dimensiones/variables tendríamos que ser capaces de utilizar escasa vectores y matrices o los requisitos de almacenamiento sería poco práctico, pero que está bien, puesto matrices y vectores son compatibles con Matlab hoy en día.

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