Usage ===== Depending on the intended usage, choose one of the :class:`MVPoly` subclasses: at present these are * :class:`~mvpoly.cube.MVPolyCube`, which uses a :class:`numpy.ndarray` for efficient storage of dense polynomials; or * :class:`~mvpoly.dict.MVPolyDict`, which uses a dictionary for a sparse representation. Import the required subclass in the usual way, for example .. code-block:: python from mvpoly.cube import MVPolyCube If you are not sure which subclass you want then something like .. code-block:: python from mvpoly.cube import MVPolyCube as Poly would allow you to switch classes by a single-line edit. Construction ------------ Assignment of coefficients .......................... The coefficients of an :class:`~mvpoly.base.MVPoly` object can be accessed and assigned by index; so one can create a polynomial by assigning the coefficients one-by-one .. code-block:: python p = MVPolyCube.zero() p[0, 0] = 3 p[2, 2] = 2 The :meth:`zero` method returns the representation of the zero polynomial, and the get/set operations ignore trailing zeros, so ``p[2, 2, 0]`` is 2 in the above. Variables ......... For a more symbolic method of creating polynomial we can generate :class:`MVPoly` variables and combine them using the standard arithmetic operators .. code-block:: python x, y, z = MVPolyCube.variables(3) p = (x + y + z**2)**2 - 3 Note, however, that such manipulation is relatively slow. By direct access ................ One can create a polynomials from the underlying data structure via the main class constructor .. code-block:: python import numpy coefs = numpy.eye(2) p = MVPolyCube(coefs) or by assigning the coefficient .. code-block:: python p = MVPolyCube.zero() p.coef = coef Naturally, such code is dependant on the subclass used. From another subclass ..................... Finally, one can create a polynomial of one subclass from one of any other just by passing it to the subclass constructor; equivalently one can use the :meth:`asclass` method .. code-block:: python from mvpoly.cube import MVPolyCube from mvpoly.dict import MVPolyDict p = MVPolyDict.zero(dtype=int) p[3, 2] = 7 # these are the same thing q = MVPolyCube(p) q = p.asclass(MVPolyCube) Data types .......... Constructor methods take an optional argument which specifies the datatype of the coefficient representation .. code-block:: python x, y, z = MVPolyCube.variables(3, dtype=int) Any Python or :class:`numpy` dtype can be used with ``numpy.double`` being the default. A polynomial's :meth:`dtype` method can be used to interrogate the datatype, and one can convert to other types with the :meth:`astype` method .. code-block:: python p = MVPolyDict.zero(dtype=int) p[3, 2] = 7 q = p.astype(float) Manipulation ------------ One can add, subtract and multiply :class:`MVPoly` polynomials, by other polynomials (of the same class) or by numbers. One can compose polynomials .. code-block:: python x, y = MVPolyCube.variables(2) p = x * y q = p.compose(x + y, x - y) and the polynomial call operator uses this method when the arguments are polynomials, so .. code-block:: python q = p(x + y, x - y) will give the same result. The :meth:`diff` and :meth:`int` methods return the differential and indefinite integral of a polynomial. Evaluation ---------- A polynomial can be evaluated at a point .. code-block:: python x, y = MVPolyCube.variables(2) p = (x - y)**2 val = p.eval(3, 3) or on an array (specified by as many arrays as the polynomial has variables, each array of the same shape) .. code-block:: python L = np.linspace(0, 1, 50) Gx, Gy = np.meshgrid(L, L) Gp = p.eval(Gx, Gy) Note that the polynomial call operator uses this method when the arguments are all scalars or arrays, so .. code-block:: python Gp = p(Gx, Gy) will give the same result. Other functions --------------- One can find the (total-, homogeneous-) degree with the property :meth:`degree`, the degree of each variable (and so the number of variables) with :meth:`degrees` .. code-block:: python p = MVPolyDict.zero(dtype=int) p[3, 2] = 7 numvar = len(p.degrees) d = p.degree The indefinite integral with :meth:`intd`: pass the intervals over which to integrate, one for each variable, as 2-element lists .. code-block:: python x, y = MVPolyDict.variables(2) p = (x + y)**2 val = p.intd([0, 1], [0, 1]) To extract the coefficients in a uniform manner (i.e., independent of the underlying data representation) use the :meth:`nonzero` property. This returns a list of index-coefficient pairs for the non-zero coefficients.