def construct_domain(obj, **args): """Construct a minimal domain for the list of coefficients. """ opt = build_options(args) if isinstance(obj, dict): monoms, coeffs = zip(*obj.items()) else: coeffs = obj coeffs = map(sympify, coeffs) result = _construct_simple(coeffs, opt) if result is not None: if result is not False: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) else: result = _construct_composite(coeffs, opt) if result is not None: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) if isinstance(obj, dict): return domain, dict(zip(monoms, coeffs)) else: return domain, coeffs
def sfield(exprs, *symbols, **options): """Construct a field deriving generators and domain from options and input expressions. Parameters ========== exprs : py:class:`~.Expr` or sequence of :py:class:`~.Expr` (sympifiable) symbols : sequence of :py:class:`~.Symbol`/:py:class:`~.Expr` options : keyword arguments understood by :py:class:`~.Options` Examples ======== >>> from sympy.core import symbols >>> from sympy.functions import exp, log >>> from sympy.polys.fields import sfield >>> x = symbols("x") >>> K, f = sfield((x*log(x) + 4*x**2)*exp(1/x + log(x)/3)/x**2) >>> K Rational function field in x, exp(1/x), log(x), x**(1/3) over ZZ with lex order >>> f (4*x**2*(exp(1/x)) + x*(exp(1/x))*(log(x)))/((x**(1/3))**5) """ single = False if not is_sequence(exprs): exprs, single = [exprs], True exprs = list(map(sympify, exprs)) opt = build_options(symbols, options) numdens = [] for expr in exprs: numdens.extend(expr.as_numer_denom()) reps, opt = _parallel_dict_from_expr(numdens, opt) if opt.domain is None: # NOTE: this is inefficient because construct_domain() automatically # performs conversion to the target domain. It shouldn't do this. coeffs = sum([list(rep.values()) for rep in reps], []) opt.domain, _ = construct_domain(coeffs, opt=opt) _field = FracField(opt.gens, opt.domain, opt.order) fracs = [] for i in range(0, len(reps), 2): fracs.append(_field(tuple(reps[i:i + 2]))) if single: return (_field, fracs[0]) else: return (_field, fracs)
def sfield(exprs, *symbols, **options): """Construct a field deriving generators and domain from options and input expressions. Parameters ========== exprs : :class:`Expr` or sequence of :class:`Expr` (sympifiable) symbols : sequence of :class:`Symbol`/:class:`Expr` options : keyword arguments understood by :class:`Options` Examples ======== >>> from sympy.core import symbols >>> from sympy.functions import exp, log >>> from sympy.polys.fields import sfield >>> x = symbols("x") >>> K, f = sfield((x*log(x) + 4*x**2)*exp(1/x + log(x)/3)/x**2) >>> K Rational function field in x, exp(1/x), log(x), x**(1/3) over ZZ with lex order >>> f (4*x**2*(exp(1/x)) + x*(exp(1/x))*(log(x)))/((x**(1/3))**5) """ single = False if not is_sequence(exprs): exprs, single = [exprs], True exprs = list(map(sympify, exprs)) opt = build_options(symbols, options) numdens = [] for expr in exprs: numdens.extend(expr.as_numer_denom()) reps, opt = _parallel_dict_from_expr(numdens, opt) if opt.domain is None: # NOTE: this is inefficient because construct_domain() automatically # performs conversion to the target domain. It shouldn't do this. coeffs = sum([list(rep.values()) for rep in reps], []) opt.domain, _ = construct_domain(coeffs, opt=opt) _field = FracField(opt.gens, opt.domain, opt.order) fracs = [] for i in range(0, len(reps), 2): fracs.append(_field(tuple(reps[i:i+2]))) if single: return (_field, fracs[0]) else: return (_field, fracs)
def _sort_gens(gens, **args): """Sort generators in a reasonably intelligent way. """ opt = build_options(args) gens_order, wrt = {}, None if opt is not None: gens_order, wrt = {}, opt.wrt for i, gen in enumerate(opt.sort): gens_order[gen] = i + 1 def order_key(gen): gen = str(gen) if wrt is not None: try: return (-len(wrt) + wrt.index(gen), gen, 0) except ValueError: pass name, index = _re_gen.match(gen).groups() if index: index = int(index) else: index = 0 try: return (gens_order[name], name, index) except KeyError: pass try: return (_gens_order[name], name, index) except KeyError: pass return (_max_order, name, index) try: gens = sorted(gens, key=order_key) except TypeError: # pragma: no cover pass return tuple(gens)
def _sort_gens(gens, **args): """Sort generators in a reasonably intelligent way. """ opt = build_options(args) gens_order, wrt = {}, None if opt is not None: gens_order, wrt = {}, opt.wrt for i, gen in enumerate(opt.sort): gens_order[gen] = i + 1 def order_key(gen): gen = str(gen) if wrt is not None: try: return (-len(wrt) + wrt.index(gen), gen, 0) except ValueError: pass name, index = _re_gen.match(gen).groups() if index: index = int(index) else: index = 0 try: return ( gens_order[name], name, index) except KeyError: pass try: return (_gens_order[name], name, index) except KeyError: pass return (_max_order, name, index) try: gens = sorted(gens, key=order_key) except TypeError: # pragma: no cover pass return tuple(gens)
def construct_domain(obj, **args): """Construct a minimal domain for the list of coefficients. """ opt = build_options(args) if hasattr(obj, '__iter__'): if isinstance(obj, dict): if not obj: monoms, coeffs = [], [] else: monoms, coeffs = list(zip(*list(obj.items()))) else: coeffs = obj else: coeffs = [obj] coeffs = list(map(sympify, coeffs)) result = _construct_simple(coeffs, opt) if result is not None: if result is not False: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) else: if opt.composite is False: result = None else: result = _construct_composite(coeffs, opt) if result is not None: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) if hasattr(obj, '__iter__'): if isinstance(obj, dict): return domain, dict(list(zip(monoms, coeffs))) else: return domain, coeffs else: return domain, coeffs[0]
def dict_from_expr(expr, **args): """Transform an expression into a multinomial form. """ rep, opt = _dict_from_expr(expr, build_options(args)) return rep, opt.gens
def parallel_dict_from_expr(exprs, **args): """Transform expressions into a multinomial form. """ reps, opt = _parallel_dict_from_expr(exprs, build_options(args)) return reps, opt.gens
def construct_domain(obj, **args): """Construct a minimal domain for a list of expressions. Explanation =========== Given a list of normal SymPy expressions (of type :py:class:`~.Expr`) ``construct_domain`` will find a minimal :py:class:`~.Domain` that can represent those expressions. The expressions will be converted to elements of the domain and both the domain and the domain elements are returned. Parameters ========== obj: list or dict The expressions to build a domain for. **args: keyword arguments Options that affect the choice of domain. Returns ======= (K, elements): Domain and list of domain elements The domain K that can represent the expressions and the list or dict of domain elements representing the same expressions as elements of K. Examples ======== Given a list of :py:class:`~.Integer` ``construct_domain`` will return the domain :ref:`ZZ` and a list of integers as elements of :ref:`ZZ`. >>> from sympy import construct_domain, S >>> expressions = [S(2), S(3), S(4)] >>> K, elements = construct_domain(expressions) >>> K ZZ >>> elements [2, 3, 4] >>> type(elements[0]) # doctest: +SKIP <class 'int'> >>> type(expressions[0]) <class 'sympy.core.numbers.Integer'> If there are any :py:class:`~.Rational` then :ref:`QQ` is returned instead. >>> construct_domain([S(1)/2, S(3)/4]) (QQ, [1/2, 3/4]) If there are symbols then a polynomial ring :ref:`K[x]` is returned. >>> from sympy import symbols >>> x, y = symbols('x, y') >>> construct_domain([2*x + 1, S(3)/4]) (QQ[x], [2*x + 1, 3/4]) >>> construct_domain([2*x + 1, y]) (ZZ[x,y], [2*x + 1, y]) If any symbols appear with negative powers then a rational function field :ref:`K(x)` will be returned. >>> construct_domain([y/x, x/(1 - y)]) (ZZ(x,y), [y/x, -x/(y - 1)]) Irrational algebraic numbers will result in the :ref:`EX` domain by default. The keyword argument ``extension=True`` leads to the construction of an algebraic number field :ref:`QQ(a)`. >>> from sympy import sqrt >>> construct_domain([sqrt(2)]) (EX, [EX(sqrt(2))]) >>> construct_domain([sqrt(2)], extension=True) # doctest: +SKIP (QQ<sqrt(2)>, [ANP([1, 0], [1, 0, -2], QQ)]) See also ======== Domain Expr """ opt = build_options(args) if hasattr(obj, '__iter__'): if isinstance(obj, dict): if not obj: monoms, coeffs = [], [] else: monoms, coeffs = list(zip(*list(obj.items()))) else: coeffs = obj else: coeffs = [obj] coeffs = list(map(sympify, coeffs)) result = _construct_simple(coeffs, opt) if result is not None: if result is not False: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) else: if opt.composite is False: result = None else: result = _construct_composite(coeffs, opt) if result is not None: domain, coeffs = result else: domain, coeffs = _construct_expression(coeffs, opt) if hasattr(obj, '__iter__'): if isinstance(obj, dict): return domain, dict(list(zip(monoms, coeffs))) else: return domain, coeffs else: return domain, coeffs[0]