def to_number_field(extension, theta=None, **args): """Express `extension` in the field generated by `theta`. """ gen = args.get('gen') if hasattr(extension, '__iter__'): extension = list(extension) else: extension = [extension] if len(extension) == 1 and type(extension[0]) is tuple: return AlgebraicNumber(extension[0]) minpoly, coeffs = primitive_element(extension, gen, polys=True) root = sum([coeff * ext for coeff, ext in zip(coeffs, extension)]) if theta is None: return AlgebraicNumber((minpoly, root)) else: theta = sympify(theta) if not theta.is_AlgebraicNumber: theta = AlgebraicNumber(theta, gen=gen) coeffs = field_isomorphism(root, theta) if coeffs is not None: return AlgebraicNumber(theta, coeffs) else: raise IsomorphismFailed("%s is not in a subfield of %s" % (root, theta.root))
def to_number_field(extension, theta=None, *, gen=None, alias=None): r""" Express one algebraic number in the field generated by another. Explanation =========== Given two algebraic numbers $\eta, \theta$, this function either expresses $\eta$ as an element of $\mathbb{Q}(\theta)$, or else raises an exception if $\eta \not\in \mathbb{Q}(\theta)$. This function is essentially just a convenience, utilizing :py:func:`~.field_isomorphism` (our solution of the Subfield Problem) to solve this, the Field Membership Problem. As an additional convenience, this function allows you to pass a list of algebraic numbers $\alpha_1, \alpha_2, \ldots, \alpha_n$ instead of $\eta$. It then computes $\eta$ for you, as a solution of the Primitive Element Problem, using :py:func:`~.primitive_element` on the list of $\alpha_i$. Examples ======== >>> from sympy import sqrt, to_number_field >>> eta = sqrt(2) >>> theta = sqrt(2) + sqrt(3) >>> a = to_number_field(eta, theta) >>> print(type(a)) <class 'sympy.core.numbers.AlgebraicNumber'> >>> a.root sqrt(2) + sqrt(3) >>> print(a) sqrt(2) >>> a.coeffs() [1/2, 0, -9/2, 0] We get an :py:class:`~.AlgebraicNumber`, whose ``.root`` is $\theta$, whose value is $\eta$, and whose ``.coeffs()`` show how to write $\eta$ as a $\mathbb{Q}$-linear combination in falling powers of $\theta$. Parameters ========== extension : :py:class:`~.Expr` or list of :py:class:`~.Expr` Either the algebraic number that is to be expressed in the other field, or else a list of algebraic numbers, a primitive element for which is to be expressed in the other field. theta : :py:class:`~.Expr`, None, optional (default=None) If an :py:class:`~.Expr` representing an algebraic number, behavior is as described under **Explanation**. If ``None``, then this function reduces to a shorthand for calling :py:func:`~.primitive_element` on ``extension`` and turning the computed primitive element into an :py:class:`~.AlgebraicNumber`. gen : :py:class:`~.Symbol`, None, optional (default=None) If provided, this will be used as the generator symbol for the minimal polynomial in the returned :py:class:`~.AlgebraicNumber`. alias : str, :py:class:`~.Symbol`, None, optional (default=None) If provided, this will be used as the alias symbol for the returned :py:class:`~.AlgebraicNumber`. Returns ======= AlgebraicNumber Belonging to $\mathbb{Q}(\theta)$ and equaling $\eta$. Raises ====== IsomorphismFailed If $\eta \not\in \mathbb{Q}(\theta)$. See Also ======== field_isomorphism primitive_element """ if hasattr(extension, '__iter__'): extension = list(extension) else: extension = [extension] if len(extension) == 1 and isinstance(extension[0], tuple): return AlgebraicNumber(extension[0], alias=alias) minpoly, coeffs = primitive_element(extension, gen, polys=True) root = sum([ coeff*ext for coeff, ext in zip(coeffs, extension) ]) if theta is None: return AlgebraicNumber((minpoly, root), alias=alias) else: theta = sympify(theta) if not theta.is_AlgebraicNumber: theta = AlgebraicNumber(theta, gen=gen, alias=alias) coeffs = field_isomorphism(root, theta) if coeffs is not None: return AlgebraicNumber(theta, coeffs, alias=alias) else: raise IsomorphismFailed( "%s is not in a subfield of %s" % (root, theta.root))
def test_pickling_polys_errors(): from sympy.polys.polyerrors import ( ExactQuotientFailed, OperationNotSupported, HeuristicGCDFailed, HomomorphismFailed, IsomorphismFailed, ExtraneousFactors, EvaluationFailed, RefinementFailed, CoercionFailed, NotInvertible, NotReversible, NotAlgebraic, DomainError, PolynomialError, UnificationFailed, GeneratorsError, GeneratorsNeeded, ComputationFailed, UnivariatePolynomialError, MultivariatePolynomialError, PolificationFailed, OptionError, FlagError) x = Symbol('x') # TODO: TypeError: __init__() takes at least 3 arguments (1 given) # for c in (ExactQuotientFailed, ExactQuotientFailed(x, 3*x, ZZ)): # check(c) # TODO: TypeError: can't pickle instancemethod objects # for c in (OperationNotSupported, OperationNotSupported(Poly(x), Poly.gcd)): # check(c) for c in (HeuristicGCDFailed, HeuristicGCDFailed()): check(c) for c in (HomomorphismFailed, HomomorphismFailed()): check(c) for c in (IsomorphismFailed, IsomorphismFailed()): check(c) for c in (ExtraneousFactors, ExtraneousFactors()): check(c) for c in (EvaluationFailed, EvaluationFailed()): check(c) for c in (RefinementFailed, RefinementFailed()): check(c) for c in (CoercionFailed, CoercionFailed()): check(c) for c in (NotInvertible, NotInvertible()): check(c) for c in (NotReversible, NotReversible()): check(c) for c in (NotAlgebraic, NotAlgebraic()): check(c) for c in (DomainError, DomainError()): check(c) for c in (PolynomialError, PolynomialError()): check(c) for c in (UnificationFailed, UnificationFailed()): check(c) for c in (GeneratorsError, GeneratorsError()): check(c) for c in (GeneratorsNeeded, GeneratorsNeeded()): check(c) # TODO: PicklingError: Can't pickle <function <lambda> at 0x38578c0>: it's not found as __main__.<lambda> # for c in (ComputationFailed, ComputationFailed(lambda t: t, 3, None)): # check(c) for c in (UnivariatePolynomialError, UnivariatePolynomialError()): check(c) for c in (MultivariatePolynomialError, MultivariatePolynomialError()): check(c) # TODO: TypeError: __init__() takes at least 3 arguments (1 given) # for c in (PolificationFailed, PolificationFailed({}, x, x, False)): # check(c) for c in (OptionError, OptionError()): check(c) for c in (FlagError, FlagError()): check(c)