Mapytex/mapytex/calculus/core/MO/polynomial.py

169 lines
4.7 KiB
Python
Raw Permalink Normal View History

2018-11-12 08:41:39 +00:00
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# Distributed under terms of the MIT license.
from collections import OrderedDict
2018-11-12 08:41:39 +00:00
from mapytex.calculus.core.tree import Tree
from . import MO, MOstr
from .mo import Molecule
2018-11-12 08:41:39 +00:00
from .exceptions import MOError
from .monomial import MOMonomial, MOstrPower
2018-11-12 08:41:39 +00:00
__all__ = ["MOpolynomial"]
2019-05-14 04:55:56 +00:00
class MOpolynomial(Molecule):
2018-11-12 08:41:39 +00:00
""" MO polynomial: ax^n + ... + z (can't be a monomial)"""
2018-11-12 08:41:39 +00:00
MAINOP = "+"
2018-11-12 08:41:39 +00:00
def __init__(self, variable, coefs):
""" Initiate a MOpolynomial
:param variable: variable of the monomial (a MOstr or later a MOSqrt)
:param coefs: dictionnary {deg: coef} or a list [coef0, coef1...]
:example:
>>> MOpolynomial('x', [1, 2, 3])
2018-11-13 09:58:32 +00:00
<MOpolynomial 3x^2 + 2x + 1>
2018-11-12 08:41:39 +00:00
>>> MOpolynomial('x', [1, 0, 3])
2018-11-13 09:58:32 +00:00
<MOpolynomial 3x^2 + 1>
2018-11-12 08:41:39 +00:00
>>> MOpolynomial('x', {0: 1, 1: 2, 2: 3})
2018-11-13 09:58:32 +00:00
<MOpolynomial 3x^2 + 2x + 1>
2018-11-12 08:41:39 +00:00
>>> MOpolynomial('x', {0: 1, 3: 4})
2018-11-13 09:58:32 +00:00
<MOpolynomial 4x^3 + 1>
>>> MOpolynomial('x', {0: 1, 3: 1})
<MOpolynomial x^3 + 1>
>>> MOpolynomial('x', [0, 0, 3])
Traceback (most recent call last):
...
TypeError: A MOpolynomial can't be monomial it has to have more than one coefficient.
>>> MOpolynomial('x', {3: 1})
Traceback (most recent call last):
...
TypeError: A MOpolynomial can't be monomial it has to have more than one coefficient.
2018-11-12 08:41:39 +00:00
"""
_variable = MO.factory(variable)
if not isinstance(_variable, MOstr):
raise MOError("The variable of a monomial should be convertible into MOstr")
self._variable = _variable
if isinstance(coefs, dict):
2019-05-14 04:55:56 +00:00
_coefs = {
MO.factory(d): MO.factory(c) for (d, c) in coefs.items() if c != 0
}
2018-11-12 08:41:39 +00:00
elif isinstance(coefs, list):
2019-05-14 04:55:56 +00:00
_coefs = {
MO.factory(d): MO.factory(c) for (d, c) in enumerate(coefs) if c != 0
}
2018-11-12 08:41:39 +00:00
else:
raise TypeError("Coefs needs to be a dictionnary or a list")
self._coefs = _coefs
if len(self._coefs) == 1:
raise TypeError("A MOpolynomial can't be monomial it has to have more than one coefficient.")
monomials = OrderedDict()
for deg in sorted(self._coefs.keys()):
coef = self._coefs[deg]
2018-11-12 08:41:39 +00:00
if deg == 0:
monomials[deg] = coef
elif deg == 1 and coef == 1:
monomials[deg] = MOstr(self._variable)
elif coef == 1:
monomials[deg] = MOstrPower(self._variable, deg)
2018-11-13 09:58:32 +00:00
else:
monomials[deg] = MOMonomial(coef, self._variable, deg)
2018-11-13 09:58:32 +00:00
self._monomials = monomials
tree = Tree.from_list("+", list(self._monomials.values())[::-1])
Molecule.__init__(self, tree)
2018-11-12 08:41:39 +00:00
@property
def variable(self):
return self._variable
@property
def degree(self):
"""
Maximum degree of its coefficient
:example:
>>> p = MOpolynomial('x', [1, 2, 3])
>>> p.degree
2
>>> p = MOpolynomial('x', {0: 1, 3: 4})
>>> p.degree
3
"""
return self.power.value
2018-11-12 08:41:39 +00:00
@property
def power(self):
"""
Maximum degree of its coefficient
:example:
>>> p = MOpolynomial('x', [1, 2, 3])
>>> p.power
<MOnumber 2>
>>> p = MOpolynomial('x', {0: 1, 3: 4})
>>> p.power
<MOnumber 3>
"""
return max(self._coefs.keys())
@property
def coefficients(self):
return self._coefs
@property
def monomials(self):
""" Return dictionnary with degree in keys and monomial in value
:example:
>>> p = MOpolynomial('x', [1, 2, 3])
>>> p.monomials
OrderedDict([(<MOnumber 0>, <MOnumber 1>), (<MOnumber 1>, <MOMonomial 2x>), (<MOnumber 2>, <MOMonomial 3x^2>)])
>>> p.monomials.values()
odict_values([<MOnumber 1>, <MOMonomial 2x>, <MOMonomial 3x^2>])
"""
return self._monomials
def differentiate(self):
""" Differentiate a MOMonomial and get a tree
:example:
>>> p = MOpolynomial('x', [1, 2, 3])
>>> print(p)
3x^2 + 2x + 1
>>> print(p.differentiate())
+
> 0
> +
| > 2
| > *
| | > 3
| | > *
| | | > 2
| | | > x
"""
monomials_d = [m.differentiate() for m in self.monomials.values()]
return Tree.from_list("+", monomials_d)
2018-11-12 08:41:39 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del