Exemplo n.º 1
0
    def _fastpolys(self):
        """
        Lazy attribute for fast_callable polynomials for affine morphsims.

        EXAMPLES::

            sage: P.<x,y> = AffineSpace(QQ, 2)
            sage: H = Hom(P, P)
            sage: f = H([x^2+y^2, y^2/(1+x)])
            sage: [t.op_list() for g in f._fastpolys for t in g]
            [[('load_const', 0), ('load_const', 1), ('load_arg', 1), ('ipow', 2),
            'mul', 'add', ('load_const', 1), ('load_arg', 0), ('ipow', 2), 'mul',
            'add', 'return'], [('load_const', 0), ('load_const', 1), ('load_arg',
            1), ('ipow', 2), 'mul', 'add', 'return'], [('load_const', 0),
            ('load_const', 1), 'add', 'return'], [('load_const', 0), ('load_const',
            1), ('load_arg', 0), ('ipow', 1), 'mul', 'add', ('load_const', 1),
            'add', 'return']]
        """
        polys = self._polys

        R = self.domain().ambient_space().coordinate_ring()
        # fastpolys[0] corresponds to the numerator polys, fastpolys[1] corresponds to denominator polys
        fastpolys = [[], []]
        for poly in polys:
            # Determine if truly polynomials. Store the numerator and denominator as separate polynomials
            # and repeat the normal process for both.
            try:
                poly_numerator = R(poly)
                poly_denominator = R.one()
            except TypeError:
                poly_numerator = R(poly.numerator())
                poly_denominator = R(poly.denominator())

            # These tests are in place because the float and integer domain evaluate
            # faster than using the base_ring
            if self._is_prime_finite_field:
                prime = polys[0].base_ring().characteristic()
                degree = max(poly_numerator.degree(), poly_denominator.degree())
                height = max(
                    [abs(c.lift()) for c in poly_numerator.coefficients()]
                    + [abs(c.lift()) for c in poly_denominator.coefficients()]
                )
                num_terms = max(len(poly_numerator.coefficients()), len(poly_denominator.coefficients()))
                largest_value = num_terms * height * (prime - 1) ** degree
                # If the calculations will not overflow the float data type use domain float
                # Else use domain integer
                if largest_value < (2 ** sys.float_info.mant_dig):
                    fastpolys[0].append(fast_callable(poly_numerator, domain=float))
                    fastpolys[1].append(fast_callable(poly_denominator, domain=float))
                else:
                    fastpolys[0].append(fast_callable(poly_numerator, domain=ZZ))
                    fastpolys[1].append(fast_callable(poly_denominator, domain=ZZ))
            else:
                fastpolys[0].append(fast_callable(poly_numerator, domain=poly.base_ring()))
                fastpolys[1].append(fast_callable(poly_denominator, domain=poly.base_ring()))
        return fastpolys
Exemplo n.º 2
0
    def _fastpolys(self):
        """
        Lazy attribute for fast_callable polynomials for ``self``.

        EXAMPLES::

            sage: P.<x,y> = AffineSpace(QQ,2)
            sage: H = Hom(P,P)
            sage: f = H([x^2+y^2,y^2/(1+x)])
            sage: [t.op_list() for g in f._fastpolys for t in g]
            [[('load_const', 0), ('load_const', 1), ('load_arg', 1), ('ipow', 2),
            'mul', 'add', ('load_const', 1), ('load_arg', 0), ('ipow', 2), 'mul',
            'add', 'return'], [('load_const', 0), ('load_const', 1), ('load_arg',
            1), ('ipow', 2), 'mul', 'add', 'return'], [('load_const', 0),
            ('load_const', 1), 'add', 'return'], [('load_const', 0), ('load_const',
            1), ('load_arg', 0), ('ipow', 1), 'mul', 'add', ('load_const', 1),
            'add', 'return']]
        """
        polys = self._polys

        R = self.domain().ambient_space().coordinate_ring()
        # fastpolys[0] corresponds to the numerator polys, fastpolys[1] corresponds to denominator polys
        fastpolys = [[], []]
        for poly in polys:
            # Determine if truly polynomials. Store the numerator and denominator as separate polynomials
            # and repeat the normal process for both.
            try:
                poly_numerator=R(poly)
                poly_denominator=R.one()
            except TypeError:
                poly_numerator=R(poly.numerator())
                poly_denominator=R(poly.denominator())

            # These tests are in place because the float and integer domain evaluate
            # faster than using the base_ring
            if self._is_prime_finite_field:
                prime = polys[0].base_ring().characteristic()
                degree = max(poly_numerator.degree(), poly_denominator.degree())
                height = max([abs(c.lift()) for c in poly_numerator.coefficients()]\
                              + [abs(c.lift()) for c in poly_denominator.coefficients()])
                num_terms = max(len(poly_numerator.coefficients()), len(poly_denominator.coefficients()))
                largest_value = num_terms * height * (prime - 1) ** degree
                # If the calculations will not overflow the float data type use domain float
                # Else use domain integer
                if largest_value < (2 ** sys.float_info.mant_dig):
                    fastpolys[0].append(fast_callable(poly_numerator, domain=float))
                    fastpolys[1].append(fast_callable(poly_denominator, domain=float))
                else:
                    fastpolys[0].append(fast_callable(poly_numerator, domain=ZZ))
                    fastpolys[1].append(fast_callable(poly_denominator, domain=ZZ))
            else:
                fastpolys[0].append(fast_callable(poly_numerator, domain=poly.base_ring()))
                fastpolys[1].append(fast_callable(poly_denominator, domain=poly.base_ring()))
        return fastpolys
Exemplo n.º 3
0
 def _eval_single_expr(self, expression):
     '''Evaluate one single expanded expression'''
     if not isinstance(expression, sage_expr):
         raise TypeError('_eval_single_expr takes only single expressions')
     arglist = []
     vallist = []
     args = expression.arguments()
     #print (expression) # DEBUG
     # loop over arguments
     found = False  # an indicator that unresolved peTab-related arguments are found
     for arg in args:
         str_arg = repr(arg)
         #print (repr(str_arg)) # DEBUG
         if str_arg in self:  # found 'our' argument
             found = True
             arglist.append(arg)
             if isinstance(self[str_arg], peScriptRef):
                 vallist.append(self[str_arg].value)
             else:
                 vallist.append(self[str_arg])
         elif str_arg in unitdict:  # found a unit, which is not overridden by parameter name
             found = True
             arglist.append(arg)
             vallist.append(unitdict[str_arg])
         else:  # found unknown argument, leave it as is
             arglist.append(arg)
             vallist.append(arg)
     #print (arglist)  #DEBUG
     # check if we have found 'our' unresolved arguments
     #print (arglist) #DEBUG
     #print (vallist) #DEBUG
     if (found):
         from sage.ext.fast_callable import fast_callable
         pExpr = fast_callable(expression, vars=arglist)
         #print (pExpr(*(vallist))) #debug
         return pExpr(*(vallist))
     else:  # no unresolved arguments - the end
         return expression
Exemplo n.º 4
0
def subexpressions_list(f, pars=None):
    """
    Construct the lists with the intermediate steps on the evaluation of the
    function.

    INPUT:

    - ``f`` -- a symbolic function of several components.

    - ``pars`` -- a list of the parameters that appear in the function
      this should be the symbolic constants that appear in f but are not
      arguments.

    OUTPUT:

    - a list of the intermediate subexpressions that appear in the evaluation
      of f.

    - a list with the operations used to construct each of the subexpressions.
      each element of this list is a tuple, formed by a string describing the
      operation made, and the operands.

    For the trigonometric functions, some extra expressions will be added.
    These extra expressions will be used later to compute their derivatives.


    EXAMPLES::

        sage: from sage.interfaces.tides import subexpressions_list
        sage: var('x,y')
        (x, y)
        sage: f(x,y) = [x^2+y, cos(x)/log(y)]
        sage: subexpressions_list(f)
        ([x^2, x^2 + y, sin(x), cos(x), log(y), cos(x)/log(y)],
        [('mul', x, x),
        ('add', y, x^2),
        ('sin', x),
        ('cos', x),
        ('log', y),
        ('div', log(y), cos(x))])

    ::

        sage: f(a)=[cos(a), arctan(a)]
        sage: from sage.interfaces.tides import subexpressions_list
        sage: subexpressions_list(f)
        ([sin(a), cos(a), a^2, a^2 + 1, arctan(a)],
        [('sin', a), ('cos', a), ('mul', a, a), ('add', 1, a^2), ('atan', a)])

    ::

        sage: from sage.interfaces.tides import subexpressions_list
        sage: var('s,b,r')
        (s, b, r)
        sage: f(t,x,y,z)= [s*(y-x),x*(r-z)-y,x*y-b*z]
        sage: subexpressions_list(f,[s,b,r])
        ([-y,
        x - y,
        s*(x - y),
        -s*(x - y),
        -z,
        r - z,
        (r - z)*x,
        -y,
        (r - z)*x - y,
        x*y,
        b*z,
        -b*z,
        x*y - b*z],
        [('mul', -1, y),
        ('add', -y, x),
        ('mul', x - y, s),
        ('mul', -1, s*(x - y)),
        ('mul', -1, z),
        ('add', -z, r),
        ('mul', x, r - z),
        ('mul', -1, y),
        ('add', -y, (r - z)*x),
        ('mul', y, x),
        ('mul', z, b),
        ('mul', -1, b*z),
        ('add', -b*z, x*y)])

    ::

        sage: var('x, y')
        (x, y)
        sage: f(x,y)=[exp(x^2+sin(y))]
        sage: from sage.interfaces.tides import *
        sage: subexpressions_list(f)
        ([x^2, sin(y), cos(y), x^2 + sin(y), e^(x^2 + sin(y))],
        [('mul', x, x),
        ('sin', y),
        ('cos', y),
        ('add', sin(y), x^2),
        ('exp', x^2 + sin(y))])


    """
    from sage.functions.trig import sin, cos, arcsin, arctan, arccos
    variables = f[0].arguments()
    if not pars:
        parameters = []
    else:
        parameters = pars
    varpar = list(parameters) + list(variables)
    F = symbolic_expression([i(*variables) for i in f]).function(*varpar)
    lis = flatten([fast_callable(i,vars=varpar).op_list() for i in F], max_level=1)
    stack = []
    const =[]
    stackcomp=[]
    detail=[]
    for i in lis:
        if i[0] == 'load_arg':
            stack.append(varpar[i[1]])
        elif i[0] == 'ipow':
            if i[1] in NN:
                basis = stack[-1]
                for j in range(i[1]-1):
                    a=stack.pop(-1)
                    detail.append(('mul', a, basis))
                    stack.append(a*basis)
                    stackcomp.append(stack[-1])
            else:
                detail.append(('pow',stack[-1],i[1]))
                stack[-1]=stack[-1]**i[1]
                stackcomp.append(stack[-1])

        elif i[0] == 'load_const':
            const.append(i[1])
            stack.append(i[1])
        elif i == 'mul':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('mul', a, b))
            stack.append(a*b)
            stackcomp.append(stack[-1])

        elif i == 'div':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('div', a, b))
            stack.append(b/a)
            stackcomp.append(stack[-1])

        elif i == 'add':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('add',a,b))
            stack.append(a+b)
            stackcomp.append(stack[-1])

        elif i == 'pow':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('pow', b, a))
            stack.append(b**a)
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='log':
            a=stack.pop(-1)
            detail.append(('log', a))
            stack.append(log(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='exp':
            a=stack.pop(-1)
            detail.append(('exp', a))
            stack.append(exp(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='sin':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(sin(a))

        elif i[0] == 'py_call' and str(i[1])=='cos':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(cos(a))

        elif i[0] == 'py_call' and str(i[1])=='tan':
            a=stack.pop(-1)
            b = sin(a)
            c = cos(a)
            detail.append(('sin', a))
            detail.append(('cos', a))
            detail.append(('div', b, c))
            stackcomp.append(b)
            stackcomp.append(c)
            stackcomp.append(b/c)
            stack.append(b/c)

        elif i[0] == 'py_call' and str(i[1])=='arctan':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('add', 1, a*a))
            detail.append(('atan', a))
            stackcomp.append(a*a)
            stackcomp.append(1+a*a)
            stackcomp.append(arctan(a))
            stack.append(arctan(a))

        elif i[0] == 'py_call' and str(i[1])=='arcsin':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('mul', -1, a*a))
            detail.append(('add', 1, -a*a))
            detail.append(('pow', 1- a*a, 0.5))
            detail.append(('asin', a))
            stackcomp.append(a*a)
            stackcomp.append(-a*a)
            stackcomp.append(1-a*a)
            stackcomp.append(sqrt(1-a*a))
            stackcomp.append(arcsin(a))
            stack.append(arcsin(a))

        elif i[0] == 'py_call' and str(i[1])=='arccos':
            a=stack.pop(-1)
            detail.append(('mul', a, a))
            detail.append(('mul', -1, a*a))
            detail.append(('add', 1, -a*a))
            detail.append(('pow', 1- a*a, 0.5))
            detail.append(('mul', -1, sqrt(1-a*a)))
            detail.append(('acos', a))
            stackcomp.append(a*a)
            stackcomp.append(-a*a)
            stackcomp.append(1-a*a)
            stackcomp.append(sqrt(1-a*a))
            stackcomp.append(-sqrt(1-a*a))
            stackcomp.append(arccos(a))
            stack.append(arccos(a))

        elif i[0] == 'py_call' and 'sqrt' in str(i[1]):
            a=stack.pop(-1)
            detail.append(('pow', a, 0.5))
            stackcomp.append(sqrt(a))
            stack.append(sqrt(a))


        elif i == 'neg':
            a = stack.pop(-1)
            detail.append(('mul', -1, a))
            stack.append(-a)
            stackcomp.append(-a)

    return stackcomp,detail
Exemplo n.º 5
0
def find_fit(data,
             model,
             initial_guess=None,
             parameters=None,
             variables=None,
             solution_dict=False):
    r"""
    Finds numerical estimates for the parameters of the function model to
    give a best fit to data.


    INPUT:

    - ``data`` -- A two dimensional table of floating point numbers of the
      form `[[x_{1,1}, x_{1,2}, \ldots, x_{1,k}, f_1],
      [x_{2,1}, x_{2,2}, \ldots, x_{2,k}, f_2],
      \ldots,
      [x_{n,1}, x_{n,2}, \ldots, x_{n,k}, f_n]]` given as either a list of
      lists, matrix, or numpy array.

    - ``model`` -- Either a symbolic expression, symbolic function, or a
      Python function. ``model`` has to be a function of the variables
      `(x_1, x_2, \ldots, x_k)` and free parameters
      `(a_1, a_2, \ldots, a_l)`.

    - ``initial_guess`` -- (default: ``None``) Initial estimate for the
      parameters `(a_1, a_2, \ldots, a_l)`, given as either a list, tuple,
      vector or numpy array. If ``None``, the default estimate for each
      parameter is `1`.

    - ``parameters`` -- (default: ``None``) A list of the parameters
      `(a_1, a_2, \ldots, a_l)`. If model is a symbolic function it is
      ignored, and the free parameters of the symbolic function are used.

    - ``variables`` -- (default: ``None``) A list of the variables
      `(x_1, x_2, \ldots, x_k)`. If model is a symbolic function it is
      ignored, and the variables of the symbolic function are used.

    - ``solution_dict`` -- (default: ``False``) if ``True``, return the
      solution as a dictionary rather than an equation.


    EXAMPLES:

    First we create some data points of a sine function with some "random"
    perturbations::

        sage: set_random_seed(0)
        sage: data = [(i, 1.2 * sin(0.5*i-0.2) + 0.1 * normalvariate(0, 1)) for i in xsrange(0, 4*pi, 0.2)]
        sage: var('a, b, c, x')
        (a, b, c, x)

    We define a function with free parameters `a`, `b` and `c`::

        sage: model(x) = a * sin(b * x - c)

    We search for the parameters that give the best fit to the data::

        sage: find_fit(data, model)
        [a == 1.21..., b == 0.49..., c == 0.19...]

    We can also use a Python function for the model::

        sage: def f(x, a, b, c): return a * sin(b * x - c)
        sage: fit = find_fit(data, f, parameters = [a, b, c], variables = [x], solution_dict = True)
        sage: fit[a], fit[b], fit[c]
        (1.21..., 0.49..., 0.19...)

    We search for a formula for the `n`-th prime number::

        sage: dataprime = [(i, nth_prime(i)) for i in range(1, 5000, 100)]
        sage: find_fit(dataprime, a * x * log(b * x), parameters = [a, b], variables = [x])
        [a == 1.11..., b == 1.24...]


    ALGORITHM:

    Uses ``scipy.optimize.leastsq`` which in turn uses MINPACK's lmdif and
    lmder algorithms.
    """
    import numpy

    if not isinstance(data, numpy.ndarray):
        try:
            data = numpy.array(data, dtype=float)
        except (ValueError, TypeError):
            raise TypeError(
                "data has to be a list of lists, a matrix, or a numpy array")
    elif data.dtype == object:
        raise ValueError("the entries of data have to be of type float")

    if data.ndim != 2:
        raise ValueError(
            "data has to be a two dimensional table of floating point numbers")

    from sage.structure.element import Expression

    if isinstance(model, Expression):
        if variables is None:
            variables = list(model.arguments())
        if parameters is None:
            parameters = list(model.variables())
            for v in variables:
                parameters.remove(v)

    if data.shape[1] != len(variables) + 1:
        raise ValueError(
            "each row of data needs %d entries, only %d entries given" %
            (len(variables) + 1, data.shape[1]))

    if parameters is None or len(parameters) == 0 or \
       variables is None or len(variables) == 0:
        raise ValueError("no variables given")

    if initial_guess is None:
        initial_guess = len(parameters) * [1]

    if not isinstance(initial_guess, numpy.ndarray):
        try:
            initial_guess = numpy.array(initial_guess, dtype=float)
        except (ValueError, TypeError):
            raise TypeError(
                "initial_guess has to be a list, tuple, or numpy array")
    elif initial_guess.dtype == object:
        raise ValueError(
            "the entries of initial_guess have to be of type float")

    if len(initial_guess) != len(parameters):
        raise ValueError(
            "length of initial_guess does not coincide with the number of parameters"
        )

    if isinstance(model, Expression):
        from sage.ext.fast_callable import fast_callable
        var_list = variables + parameters
        func = fast_callable(model, vars=var_list, domain=float)
    else:
        func = model

    def function(x_data, params):
        result = numpy.zeros(len(x_data))
        for row in range(len(x_data)):
            fparams = numpy.hstack((x_data[row], params)).tolist()
            result[row] = func(*fparams)
        return result

    def error_function(params, x_data, y_data):
        result = numpy.zeros(len(x_data))
        for row in range(len(x_data)):
            fparams = x_data[row].tolist() + params.tolist()
            result[row] = func(*fparams)
        return result - y_data

    x_data = data[:, 0:len(variables)]
    y_data = data[:, -1]

    from scipy.optimize import leastsq
    estimated_params, d = leastsq(error_function,
                                  initial_guess,
                                  args=(x_data, y_data))

    if isinstance(estimated_params, float):
        estimated_params = [estimated_params]
    else:
        estimated_params = estimated_params.tolist()

    if solution_dict:
        dict = {}
        for item in zip(parameters, estimated_params):
            dict[item[0]] = item[1]
        return dict

    return [item[0] == item[1] for item in zip(parameters, estimated_params)]
Exemplo n.º 6
0
def minimize_constrained(func,
                         cons,
                         x0,
                         gradient=None,
                         algorithm='default',
                         **args):
    r"""
    Minimize a function with constraints.


    INPUT:

    - ``func`` -- Either a symbolic function, or a Python function whose
      argument is a tuple with n components

    - ``cons`` -- constraints. This should be either a function or list of
      functions that must be positive. Alternatively, the constraints can
      be specified as a list of intervals that define the region we are
      minimizing in. If the constraints are specified as functions, the
      functions should be functions of a tuple with `n` components
      (assuming `n` variables). If the constraints are specified as a list
      of intervals and there are no constraints for a given variable, that
      component can be (``None``, ``None``).

    - ``x0`` -- Initial point for finding minimum

    - ``algorithm`` -- Optional, specify the algorithm to use:

      - ``'default'``  -- default choices

      - ``'l-bfgs-b'`` -- only effective if you specify bound constraints.
        See [ZBN1997]_.

    - ``gradient`` -- Optional gradient function. This will be computed
      automatically for symbolic functions. This is only used when the
      constraints are specified as a list of intervals.


    EXAMPLES:

    Let us maximize `x + y - 50` subject to the following constraints:
    `50x + 24y \leq 2400`, `30x + 33y \leq 2100`, `x \geq 45`,
    and `y \geq 5`::

        sage: y = var('y')
        sage: f = lambda p: -p[0]-p[1]+50
        sage: c_1 = lambda p: p[0]-45
        sage: c_2 = lambda p: p[1]-5
        sage: c_3 = lambda p: -50*p[0]-24*p[1]+2400
        sage: c_4 = lambda p: -30*p[0]-33*p[1]+2100
        sage: a = minimize_constrained(f,[c_1,c_2,c_3,c_4],[2,3])
        sage: a
        (45.0, 6.25...)

    Let's find a minimum of `\sin(xy)`::

        sage: x,y = var('x y')
        sage: f = sin(x*y)
        sage: minimize_constrained(f, [(None,None),(4,10)],[5,5])
        (4.8..., 4.8...)

    Check if L-BFGS-B finds the same minimum::

        sage: minimize_constrained(f, [(None,None),(4,10)],[5,5], algorithm='l-bfgs-b')
        (4.7..., 4.9...)

    Rosenbrock function (see the :wikipedia:`Rosenbrock_function`)::

        sage: from scipy.optimize import rosen, rosen_der
        sage: minimize_constrained(rosen, [(-50,-10),(5,10)],[1,1],gradient=rosen_der,algorithm='l-bfgs-b')
        (-10.0, 10.0)
        sage: minimize_constrained(rosen, [(-50,-10),(5,10)],[1,1],algorithm='l-bfgs-b')
        (-10.0, 10.0)

    TESTS:

    Check if :trac:`6592` is fixed::

        sage: x, y = var('x y')
        sage: f = (100 - x) + (1000 - y)
        sage: c = x + y - 479 # > 0
        sage: minimize_constrained(f, [c], [100, 300])
        (805.985..., 1005.985...)
        sage: minimize_constrained(f, c, [100, 300])
        (805.985..., 1005.985...)
    """
    from sage.structure.element import Expression
    from sage.ext.fast_callable import fast_callable
    import numpy
    from scipy import optimize
    function_type = type(lambda x, y: x + y)

    if isinstance(func, Expression):
        var_list = func.variables()
        fast_f = fast_callable(func, vars=var_list, domain=float)
        f = lambda p: fast_f(*p)
        gradient_list = func.gradient()
        fast_gradient_functions = [
            fast_callable(gi, vars=var_list, domain=float)
            for gi in gradient_list
        ]
        gradient = lambda p: numpy.array(
            [a(*p) for a in fast_gradient_functions])
        if isinstance(cons, Expression):
            fast_cons = fast_callable(cons, vars=var_list, domain=float)
            cons = lambda p: numpy.array([fast_cons(*p)])
        elif isinstance(cons, list) and isinstance(cons[0], Expression):
            fast_cons = [
                fast_callable(ci, vars=var_list, domain=float) for ci in cons
            ]
            cons = lambda p: numpy.array([a(*p) for a in fast_cons])
    else:
        f = func

    if isinstance(cons, list):
        if isinstance(cons[0], tuple) or isinstance(cons[0],
                                                    list) or cons[0] is None:
            if gradient is not None:
                if algorithm == 'l-bfgs-b':
                    min = optimize.fmin_l_bfgs_b(f,
                                                 x0,
                                                 gradient,
                                                 bounds=cons,
                                                 iprint=-1,
                                                 **args)[0]
                else:
                    min = optimize.fmin_tnc(f,
                                            x0,
                                            gradient,
                                            bounds=cons,
                                            messages=0,
                                            **args)[0]
            else:
                if algorithm == 'l-bfgs-b':
                    min = optimize.fmin_l_bfgs_b(f,
                                                 x0,
                                                 approx_grad=True,
                                                 bounds=cons,
                                                 iprint=-1,
                                                 **args)[0]
                else:
                    min = optimize.fmin_tnc(f,
                                            x0,
                                            approx_grad=True,
                                            bounds=cons,
                                            messages=0,
                                            **args)[0]
        elif isinstance(cons[0], function_type) or isinstance(
                cons[0], Expression):
            min = optimize.fmin_cobyla(f, x0, cons, **args)
    elif isinstance(cons, function_type) or isinstance(cons, Expression):
        min = optimize.fmin_cobyla(f, x0, cons, **args)
    return vector(RDF, min)
Exemplo n.º 7
0
def minimize(func,
             x0,
             gradient=None,
             hessian=None,
             algorithm="default",
             verbose=False,
             **args):
    r"""
    This function is an interface to a variety of algorithms for computing
    the minimum of a function of several variables.

    INPUT:

    - ``func`` -- Either a symbolic function or a Python function whose
      argument is a tuple with `n` components

    - ``x0`` -- Initial point for finding minimum.

    - ``gradient`` -- Optional gradient function. This will be computed
      automatically for symbolic functions.  For Python functions, it allows
      the use of algorithms requiring derivatives.  It should accept a
      tuple of arguments and return a NumPy array containing the partial
      derivatives at that point.

    - ``hessian`` --  Optional hessian function. This will be computed
      automatically for symbolic functions. For Python functions, it allows
      the use of algorithms requiring derivatives. It should accept a tuple
      of arguments and return a NumPy array containing the second partial
      derivatives of the function.

    - ``algorithm`` -- String specifying algorithm to use. Options are
      ``'default'`` (for Python functions, the simplex method is the default)
      (for symbolic functions bfgs is the default):

       - ``'simplex'`` -- using the downhill simplex algorithm

       - ``'powell'`` -- use the modified Powell algorithm

       - ``'bfgs'`` -- (Broyden-Fletcher-Goldfarb-Shanno) requires gradient

       - ``'cg'`` -- (conjugate-gradient) requires gradient

       - ``'ncg'`` -- (newton-conjugate gradient) requires gradient and hessian

    - ``verbose`` -- (optional, default: False) print convergence message

    .. NOTE::

        For additional information on the algorithms implemented in this function,
        consult SciPy's `documentation on optimization and root
        finding <https://docs.scipy.org/doc/scipy/reference/optimize.html>`_

    EXAMPLES:

    Minimize a fourth order polynomial in three variables (see the
    :wikipedia:`Rosenbrock_function`)::

        sage: vars = var('x y z')
        sage: f = 100*(y-x^2)^2+(1-x)^2+100*(z-y^2)^2+(1-y)^2
        sage: minimize(f, [.1,.3,.4]) # abs tol 1e-6
        (1.0, 1.0, 1.0)

    Try the newton-conjugate gradient method; the gradient and hessian are
    computed automatically::

        sage: minimize(f, [.1, .3, .4], algorithm="ncg") # abs tol 1e-6
        (1.0, 1.0, 1.0)

    We get additional convergence information with the `verbose` option::

        sage: minimize(f, [.1, .3, .4], algorithm="ncg", verbose=True)
        Optimization terminated successfully.
        ...
        (0.9999999..., 0.999999..., 0.999999...)

    Same example with just Python functions::

        sage: def rosen(x): # The Rosenbrock function
        ....:    return sum(100.0r*(x[1r:]-x[:-1r]**2.0r)**2.0r + (1r-x[:-1r])**2.0r)
        sage: minimize(rosen, [.1,.3,.4]) # abs tol 3e-5
        (1.0, 1.0, 1.0)

    Same example with a pure Python function and a Python function to
    compute the gradient::

        sage: def rosen(x): # The Rosenbrock function
        ....:    return sum(100.0r*(x[1r:]-x[:-1r]**2.0r)**2.0r + (1r-x[:-1r])**2.0r)
        sage: import numpy
        sage: from numpy import zeros
        sage: def rosen_der(x):
        ....:    xm = x[1r:-1r]
        ....:    xm_m1 = x[:-2r]
        ....:    xm_p1 = x[2r:]
        ....:    der = zeros(x.shape, dtype=float)
        ....:    der[1r:-1r] = 200r*(xm-xm_m1**2r) - 400r*(xm_p1 - xm**2r)*xm - 2r*(1r-xm)
        ....:    der[0] = -400r*x[0r]*(x[1r]-x[0r]**2r) - 2r*(1r-x[0])
        ....:    der[-1] = 200r*(x[-1r]-x[-2r]**2r)
        ....:    return der
        sage: minimize(rosen, [.1,.3,.4], gradient=rosen_der, algorithm="bfgs") # abs tol 1e-6
        (1.0, 1.0, 1.0)
    """
    from sage.structure.element import Expression
    from sage.ext.fast_callable import fast_callable
    import numpy
    from scipy import optimize
    if isinstance(func, Expression):
        var_list = func.variables()
        var_names = [str(_) for _ in var_list]
        fast_f = fast_callable(func, vars=var_names, domain=float)
        f = lambda p: fast_f(*p)
        gradient_list = func.gradient()
        fast_gradient_functions = [
            fast_callable(gradient_list[i], vars=var_names, domain=float)
            for i in range(len(gradient_list))
        ]
        gradient = lambda p: numpy.array(
            [a(*p) for a in fast_gradient_functions])
    else:
        f = func

    if algorithm == "default":
        if gradient is None:
            min = optimize.fmin(f, [float(_) for _ in x0],
                                disp=verbose,
                                **args)
        else:
            min = optimize.fmin_bfgs(f, [float(_) for _ in x0],
                                     fprime=gradient,
                                     disp=verbose,
                                     **args)
    else:
        if algorithm == "simplex":
            min = optimize.fmin(f, [float(_) for _ in x0],
                                disp=verbose,
                                **args)
        elif algorithm == "bfgs":
            min = optimize.fmin_bfgs(f, [float(_) for _ in x0],
                                     fprime=gradient,
                                     disp=verbose,
                                     **args)
        elif algorithm == "cg":
            min = optimize.fmin_cg(f, [float(_) for _ in x0],
                                   fprime=gradient,
                                   disp=verbose,
                                   **args)
        elif algorithm == "powell":
            min = optimize.fmin_powell(f, [float(_) for _ in x0],
                                       disp=verbose,
                                       **args)
        elif algorithm == "ncg":
            if isinstance(func, Expression):
                hess = func.hessian()
                hess_fast = [[
                    fast_callable(a, vars=var_names, domain=float) for a in row
                ] for row in hess]
                hessian = lambda p: [[a(*p) for a in row] for row in hess_fast]
                from scipy import dot
                hessian_p = lambda p, v: dot(numpy.array(hessian(p)), v)
                min = optimize.fmin_ncg(f, [float(_) for _ in x0], fprime=gradient, \
                      fhess=hessian, fhess_p=hessian_p, disp=verbose, **args)
    return vector(RDF, min)
Exemplo n.º 8
0
def createLists(f, pars):
    '''
	Creates list1 and list 2 from the right side function f of an ODE:
	input: 
		f -> right side function for ODE system
		pars -> list with the parameters on f
	output:
		list1 and list2


	Example with Lorenz Equation
	sage: var('t, x, y, z')		# variables for lorenz equations
	sage: var('s, r, b')		# parameters for lorenz equations
	sage: f(t,x,y,z) = [s*(y-x), x*(r-z) - y, x*y - b*z]	# Right side function for Lorenz equation

	'''
    vars = f[0].arguments()  # gets the list of variables from function f
    varpar = list(vars) + list(pars)  # gets the list of vars and pars totegher
    _f = f(*vars).function(
        varpar)  # _f is f but with vars and pars as arguments

    fastCallList = flatten(
        [fast_callable(i, vars=varpar).op_list() for i in f], max_level=1)
    # This list is the fast callable version of f using a stack-mode call
    '''
	We create create the lists list1, list2 and stack.
	stack will be expresion stack-list

	'''
    list1 = []
    list2 = []
    stack = []
    '''
	Starts parser on fastCallList. 
	'''
    for s in fastCallList:
        if s[0] == 'load_arg':  # Loads a variable in stack. no changes on list1, or list2
            stack.append(varpar[
                s[1]])  # appends the variable or parameter on symbolic stack

        elif s[0] == 'ipow':  # Integer power.
            if s[1] in NN:  # If natural, parser as products
                basis = stack[-1]
                for j in range(s[1] - 1):
                    a = stack.pop(-1)
                    stack.append(a * basis)
                    list1.append(stack[-1])
                    list2.append(('mul', a, basis))
            elif -s[1] in NN:
                basis = stack[-1]
                for j in range(-s[1] - 1):
                    a = stack.pop(-1)
                    stack.append(a * basis)
                    list1.append(stack[-1])
                    list2.append(('mul', a, basis))
                a = stack.pop(-1)
                stack.append(1 / a)
                list1.append(stack[-1])
                list2.append(('div', 1, a))
            else:  # Attach as normal power
                a = stack.pop(-1)  #basis
                stack.append(a**s[1])
                list1.append(stack[-1])
                list2.append(('pow', a, s[1]))

        elif s[0] == 'load_const':  # Loads a constant value on stack. Not in list1 or list2
            stack.append(s[1])

        elif s == 'neg':  # multiplies by -1.0
            a = stack.pop(-1)  # expresion to be multiplied by -1
            stack.append(-a)
            list1.append(stack[-1])
            list2.append(('mul', -1, a))

        elif s == 'mul':  # Product
            a = stack.pop(-1)
            b = stack.pop(-1)
            list2.append(('mul', a, b))
            stack.append(a * b)
            list1.append(stack[-1])

        elif s == 'div':  # divission Numerator First.
            b = stack.pop(-1)  # denominator (after a in stack)
            a = stack.pop(-1)  # numerator (before b in stack)
            if expresionIsConstant(b, pars):
                list1.append(1 / b)
                list2.append(('div', 1, b))
                b = 1 / b
                stack.append(a * b)
                list1.append(stack[-1])
                list2.append(('mul', a, b))
            else:
                list2.append(('div', a, b))
                stack.append(a / b)
                list1.append(stack[-1])

        elif s == 'add':  # addition
            b = stack.pop(-1)  # second operand
            a = stack.pop(-1)  # first operand
            stack.append(a + b)
            list1.append(stack[-1])
            list2.append(('add', a, b))

        elif s == 'pow':  # any other pow
            b = stack.pop(-1)  # exponent
            a = stack.pop(-1)  # basis
            stack.append(a**b)
            list1.append(stack[-1])
            list2.append(('pow', a, b))

        elif s[0] == 'py_call' and 'sqrt' in str(
                s[1]):  # square root. Compute as power
            a = stack.pop(-1)  # argument of sqrt
            stack.append(sqrt(a))
            list1.append(stack[-1])
            list2.append(('pow', a, 0.5))

        elif s[0] == 'py_call' and str(s[1]) == 'log':  # logarithm
            a = stack.pop(-1)
            # argument of log
            stack.append(log(a))
            list1.append(stack[-1])
            list2.append(('log', a))

        elif s[0] == 'py_call' and str(s[1]) == 'exp':
            a = stack.pop(-1)
            # argument of exp
            stack.append(exp(a))
            list1.append(stack[-1])
            list2.append(('exp', a))

        elif s[0] == 'py_call' and str(
                s[1]) == 'sin':  # sine. For AD needs computation of cos
            a = stack.pop(-1)
            stack.append(sin(a))
            list1.append(sin(a))
            list1.append(cos(a))
            list2.append(('sin', a))
            list2.append(('cos', a))

        elif s[0] == 'py_call' and str(
                s[1]) == 'cos':  # cosine. For AD needs computation of sin
            a = stack.pop(-1)
            stack.append(cos(a))
            list1.append(sin(a))
            list1.append(cos(a))
            list2.append(('sin', a))
            list2.append(('cos', a))
        elif s[0] == 'py_call' and str(s[1]) == 'tan':
            a = stack.pop(-1)
            stack.append(tan(a))
            list1.append(sin(a))
            list1.append(cos(a))
            list1.append(tan(a))
            list2.append(('sin', a))
            list2.append(('cos', a))
            list2.append(('div', sin(a), cos(a)))

    return list1, list2
Exemplo n.º 9
0
def createLists (f, pars):
	'''
	Creates list1 and list 2 from the right side function f of an ODE:
	input: 
		f -> right side function for ODE system
		pars -> list with the parameters on f
	output:
		list1 and list2


	Example with Lorenz Equation
	sage: var('t, x, y, z')		# variables for lorenz equations
	sage: var('s, r, b')		# parameters for lorenz equations
	sage: f(t,x,y,z) = [s*(y-x), x*(r-z) - y, x*y - b*z]	# Right side function for Lorenz equation

	'''
	vars = f[0].arguments ()				# gets the list of variables from function f
	varpar = list (vars) + list (pars)			# gets the list of vars and pars totegher
	_f = f (*vars).function (varpar)	# _f is f but with vars and pars as arguments


	fastCallList = flatten ([fast_callable (i,vars=varpar).op_list () for i in f], max_level=1)
		# This list is the fast callable version of f using a stack-mode call
	'''
	We create create the lists list1, list2 and stack.
	stack will be expresion stack-list

	'''
	list1 = []; list2 = []; stack = [];
	'''
	Starts parser on fastCallList. 
	'''
	for s in fastCallList:
		if s[0] == 'load_arg':			# Loads a variable in stack. no changes on list1, or list2
			stack.append (varpar[s[1]])	# appends the variable or parameter on symbolic stack

		elif s[0] == 'ipow':			# Integer power. 
			if s[1] in NN:			# If natural, parser as products
				basis = stack[-1]
				for j in range (s[1]-1):
					a=stack.pop (-1)
					stack.append (a*basis)
					list1.append (stack[-1])
					list2.append (('mul', a, basis))
			elif -s[1] in NN:
				basis = stack[-1]
				for j in range (-s[1]-1):
					a=stack.pop (-1)
					stack.append (a*basis)
					list1.append (stack[-1])
					list2.append (('mul', a, basis))
				a = stack.pop (-1);
				stack.append (1/a);
				list1.append (stack[-1])
				list2.append (('div', 1, a))
			else:				# Attach as normal power
				a = stack.pop (-1)	#basis
				stack.append (a ** s[1])
				list1.append (stack[-1])
				list2.append (('pow', a, s[1]))

		elif s[0] == 'load_const':		# Loads a constant value on stack. Not in list1 or list2
			stack.append (s[1])

		elif s == 'neg':			# multiplies by -1.0
			a = stack.pop (-1)		# expresion to be multiplied by -1
			stack.append (-a)
			list1.append (stack[-1])
			list2.append (('mul', -1, a))

		elif s == 'mul':			# Product
			a=stack.pop (-1)
			b=stack.pop (-1)
			list2.append (('mul', a, b))
			stack.append (a*b)
			list1.append (stack[-1])

		elif s == 'div':			# divission Numerator First.
			b=stack.pop (-1)		# denominator (after a in stack)
			a=stack.pop (-1)		# numerator (before b in stack)
			if expresionIsConstant (b, pars):
				list1.append(1/b)
				list2.append(('div', 1, b))
				b = 1/b;
				stack.append (a*b)
				list1.append(stack[-1])
				list2.append (('mul', a, b))
			else:
				list2.append (('div', a, b))
				stack.append (a/b)
				list1.append (stack[-1])

		elif s == 'add':			# addition
			b = stack.pop (-1)		# second operand
			a = stack.pop (-1)		# first operand
			stack.append (a+b)
			list1.append (stack[-1])
			list2.append (('add', a, b))

		elif s == 'pow':			# any other pow
			b = stack.pop (-1)		# exponent
			a = stack.pop (-1)		# basis
			stack.append (a**b)
			list1.append (stack[-1])
			list2.append (('pow', a, b))

		elif s[0] == 'py_call' and 'sqrt' in str (s[1]):	# square root. Compute as power
			a = stack.pop (-1)		# argument of sqrt
			stack.append (sqrt (a))
			list1.append (stack[-1])
			list2.append (('pow', a, 0.5))

		elif s[0] == 'py_call' and str (s[1]) == 'log':	# logarithm
			a = stack.pop (-1);		# argument of log
			stack.append (log (a))
			list1.append (stack[-1])
			list2.append (('log', a))

		elif s[0] == 'py_call' and str (s[1]) == 'exp':
			a = stack.pop (-1);		# argument of exp
			stack.append (exp (a))
			list1.append (stack[-1])
			list2.append (('exp', a))

		elif s[0] == 'py_call' and str (s[1]) == 'sin':		# sine. For AD needs computation of cos
			a = stack.pop (-1)
			stack.append (sin (a))
			list1.append (sin (a))
			list1.append (cos (a))
			list2.append (('sin', a))
			list2.append (('cos', a))

		elif s[0] == 'py_call' and str (s[1]) == 'cos':		# cosine. For AD needs computation of sin
			a = stack.pop (-1)
			stack.append (cos (a))
			list1.append (sin (a))
			list1.append (cos (a))
			list2.append (('sin', a))
			list2.append (('cos', a))
		elif s[0] == 'py_call' and str (s[1]) == 'tan':
			a = stack.pop (-1)
			stack.append (tan (a))
			list1.append (sin (a))
			list1.append (cos (a))
			list1.append (tan (a))
			list2.append (('sin', a))
			list2.append (('cos', a))
			list2.append (('div', sin (a), cos (a)))

	return list1, list2
Exemplo n.º 10
0
def desolve_mintides(f, ics, initial, final, delta,  tolrel=1e-16, tolabs=1e-16):
    r"""
    Solve numerically a system of first order differential equations using the
    taylor series integrator implemeted in mintides.

    INPUT:

    - ``f`` - symboli

    """
    # get the list of operators called
    from sage.misc.misc import SAGE_ROOT
    RR = RealField()
    variables = f[0].arguments()
    nvars = len(variables)
    lis = flatten([fast_callable(i,vars=variables).op_list() for i in f], max_level=1)
    deflist = []
    stack = []
    const =[]
    stackcomp=[]
    detail=[]
    for i in lis:
        if i[0] == 'load_arg':
            stack.append(variables[i[1]])
        elif i[0] == 'ipow':
            if i[1] in NN:
                basis = stack[-1]
                for j in range(i[1]-1):
                    a=stack.pop(-1)
                    detail.append(('mul', a, basis))
                    stack.append(a*basis)
                    stackcomp.append(stack[-1])
            else:
                detail.append(('pow',stack[-1],i[1]))
                stack[-1]=stack[-1]**i[1]
                stackcomp.append(stack[-1])

        elif i[0] == 'load_const':
            const.append(i[1])
            stack.append(i[1])
        elif i == 'mul':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('mul', a, b))
            stack.append(a*b)
            stackcomp.append(stack[-1])

        elif i == 'div':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('div', a, b))
            stack.append(b/a)
            stackcomp.append(stack[-1])

        elif i == 'add':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('add',a,b))
            stack.append(a+b)
            stackcomp.append(stack[-1])

        elif i == 'pow':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('pow', b, a))
            stack.append(b**a)
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='log':
            a=stack.pop(-1)
            detail.append(('log', a))
            stack.append(log(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='exp':
            a=stack.pop(-1)
            detail.append(('exp', a))
            stack.append(exp(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='sin':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(sin(a))

        elif i[0] == 'py_call' and str(i[1])=='cos':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(cos(a))

        elif i == 'neg':
            a = stack.pop(-1)
            detail.append(('mul', -1, a))
            stack.append(-a)
            stackcomp.append(-a)

    l1, l2 = stackcomp, detail


    #remove the repeated expressions

    for i in range(len(l1)-1):
        j=i+1
        while j<len(l1):
            if l1[j] == l1[i]:
                l1.pop(j)
                l2.pop(j)
            else:
                j+=1

    #remove the constants

    i=0
    while i < len(l1):
        if l1[i] in RR:
            l1.pop(i)
            l2.pop(i)
        else:
            i+=1

    #generate the corresponding c lines

    l3=[]
    var = f[0].arguments()
    for i in l2:
        oper = i[0]
        if oper in ["log", "exp", "sin", "cos"]:
            a = i[1]
            if a in var:
                l3.append((oper, 'XX[{}]'.format(var.index(a))))
            elif a in l1:
                l3.append((oper, 'XX[{}]'.format(l1.index(a)+len(var))))

        else:
            a=i[1]
            b=i[2]
            consta=False
            constb=False

            if a in var:
                aa = 'XX[{}]'.format(var.index(a))
            elif a in l1:
                aa = 'XX[{}]'.format(l1.index(a)+len(var))
            else:
                consta=True
                aa = str(a)
            if b in var:
                bb = 'XX[{}]'.format(var.index(b))
            elif b in l1:
                bb = 'XX[{}]'.format(l1.index(b)+len(var))
            else:
                constb=True
                bb = str(b)
            if consta:
                oper += '_c'
                if not oper=='div':
                    bb, aa = aa,bb
            elif constb:
                oper += '_c'
            l3.append((oper, aa, bb))



    n = len(variables)
    res = []
    for i in range(len(l3)):
        el = l3[i]
        string = "XX[{}][i] = ".format(i + n)
        if el[0] == 'add':
            string += el[1] + "[i] + " + el[2] +"[i];"
        elif el[0] == 'add_c':
            string += "(i==0)? {}+".format(N(el[2])) + el[1] + "[0] : "+ el[1]+ "[i];"
        elif el[0] == 'mul':
            string += "mul_mc("+el[1]+","+el[2]+",i);"
        elif el[0] == 'mul_c':
            string += str(N(el[2])) + "*"+ el[1] + "[i];"
        elif el[0] == 'pow_c':
            string += "pow_mc_c("+el[1]+","+str(N(el[2]))+",XX[{}], i);".format(i+n)
        elif el[0] == 'div':
            string += "div_mc_c("+el[2]+","+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'div_c':
            string += "inv_mc_c("+str(N(el[2]))+","+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'log':
            string += "log_mc("+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'exp':
            string += "exp_mc("+el[1]+",XX[{}], i);".format(i+n)
        elif el[0] == 'sin':
            string += "sin_mc("+el[1]+",XX[{}], i);".format(i+n+1)
        elif el[0] == 'cos':
            string += "cos_mc("+el[1]+",XX[{}], i);".format(i+n-1)


        res.append(string)

    l1 = list(variables)+l1
    indices = [l1.index(i(*variables))+n for i in f]
    for i in range (1,len(variables)):
        res.append("XX[{}][i+1] = XX[{}][i] / (i+1.0);".format(i,indices[i-1]-len(variables)))


    code = res
    VAR = len(variables)
    PAR =0
    TT = len(res)
    tempdir = mkdtemp()
    fname = tempdir + '/integrator.c'
    shutil.copy(SAGE_ROOT+'/src/sage/calculus/tides/seriesFile00.txt', fname)
    outfile = open(fname, 'a')
    outfile.write("\tVAR = {};\n".format(VAR))
    outfile.write("\tPAR = {};\n".format(PAR))
    outfile.write("\tTT = {};\n".format(TT))
    infile = open(SAGE_ROOT+'/src/sage/calculus/tides/seriesFile01.txt')
    for i in infile:
        outfile.write(i)
    infile.close()
    outfile.writelines(["\t\t"+i+"\n" for i in code])

    infile = open(SAGE_ROOT+'/src/sage/calculus/tides/seriesFile02.txt')
    for i in infile:
        outfile.write(i)
    outfile.close()

    fname = tempdir + '/driver.c'
    fileoutput = tempdir + '/output'

    shutil.copy(SAGE_ROOT+'/src/sage/calculus/tides/driverFile00.txt', fname)
    outfile = open(fname, 'a')
    outfile.write('\n\tVARS = {} ;\n'.format(nvars-1))
    outfile.write('\tPARS = 1;\n')
    outfile.write('\tdouble tolrel, tolabs, tini, tend, dt; \n')
    outfile.write('\tdouble v[VARS], p[PARS]; \n')
    for i in range(len(ics)):
        outfile.write('\tv[{}] = {} ; \n'.format(i, ics[i]))
    outfile.write('\ttini = {} ;\n'.format(initial))
    outfile.write('\ttend = {} ;\n'.format(final))
    outfile.write('\tdt   = {} ;\n'.format(delta))
    outfile.write('\ttolrel = {} ;\n'.format(tolrel))
    outfile.write('\ttolabs = {} ;\n'.format(tolabs))
    outfile.write('\textern char ofname[500];')
    outfile.write('\tstrcpy(ofname, "'+ fileoutput +'");\n')
    outfile.write('\tminc_tides(v,VARS,p,PARS,tini,tend,dt,tolrel,tolabs);\n')
    outfile.write('\treturn 0; \n }')
    outfile.close()

    runmefile = tempdir + '/runme'


    shutil.copy(SAGE_ROOT+'/src/sage/calculus/tides/minc_tides.c', tempdir)
    shutil.copy(SAGE_ROOT+'/src/sage/calculus/tides/minc_tides.h', tempdir)

    os.system('gcc -o ' + runmefile + ' ' + tempdir + '/*.c  -lm  -O2')
    os.system(tempdir+'/runme ')
    outfile = open(fileoutput)
    res = outfile.readlines()
    outfile.close()
    for i in range(len(res)):
        l=res[i]
        l = l.split(' ')
        l = filter(lambda a: len(a) > 2, l)
        res[i] = map(RR,l)
    #shutil.rmtree(tempdir)

    return res
Exemplo n.º 11
0
def convert_list(f):
    """
    - f is a vectorial function f(x1, x2, ...) -> [...]

    Create two lists:

    - The first list contains the subexpressions that appear in the construction
    of the function

    - The second one contains the corresponding operation used to create each subexpression
    """
    variables = f[0].arguments()
    lis = flatten([fast_callable(i,vars=variables).op_list() for i in f], max_level=1)
    deflist = []
    stack = []
    const =[]
    stackcomp=[]
    detail=[]
    for i in lis:
        if i[0] == 'load_arg':
            stack.append(variables[i[1]])
        elif i[0] == 'ipow':
            if i[1] in NN:
                basis = stack[-1]
                for j in range(i[1]-1):
                    a=stack.pop(-1)
                    detail.append(('mul', a, basis))
                    stack.append(a*basis)
                    stackcomp.append(stack[-1])
            else:
                detail.append(('pow',stack[-1],i[1]))
                stack[-1]=stack[-1]**i[1]
                stackcomp.append(stack[-1])

        elif i[0] == 'load_const':
            const.append(i[1])
            stack.append(i[1])
        elif i == 'mul':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('mul', a, b))
            stack.append(a*b)
            stackcomp.append(stack[-1])

        elif i == 'div':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('div', a, b))
            stack.append(b/a)
            stackcomp.append(stack[-1])

        elif i == 'add':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('add',a,b))
            stack.append(a+b)
            stackcomp.append(stack[-1])

        elif i == 'pow':
            a=stack.pop(-1)
            b=stack.pop(-1)
            detail.append(('pow', b, a))
            stack.append(b**a)
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='log':
            a=stack.pop(-1)
            detail.append(('log', a))
            stack.append(log(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='exp':
            a=stack.pop(-1)
            detail.append(('exp', a))
            stack.append(exp(a))
            stackcomp.append(stack[-1])

        elif i[0] == 'py_call' and str(i[1])=='sin':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(sin(a))

        elif i[0] == 'py_call' and str(i[1])=='cos':
            a=stack.pop(-1)
            detail.append(('sin', a))
            detail.append(('cos', a))
            stackcomp.append(sin(a))
            stackcomp.append(cos(a))
            stack.append(cos(a))

        elif i == 'neg':
            a = stack.pop(-1)
            detail.append(('mul', -1, a))
            stack.append(-a)
            stackcomp.append(-a)

    return stackcomp,detail
Exemplo n.º 12
0
def function_builder(eq):
    print("Preparing 4x{}x{} symbolic variables".format(nr, nt))
    p = np.array([[SR.var("p_{}_{}".format(i, j)) for i in range(nr)]
                  for j in range(nt)],
                 dtype=object)
    wr = np.array([[SR.var("wr_{}_{}".format(i, j)) for i in range(nr)]
                   for j in range(nt)],
                  dtype=object)
    wt = np.array([[SR.var("wt_{}_{}".format(i, j)) for i in range(nr)]
                   for j in range(nt)],
                  dtype=object)
    wp = np.array([[SR.var("wp_{}_{}".format(i, j)) for i in range(nr)]
                   for j in range(nt)],
                  dtype=object)

    fun = np.array([SR(0)] * (4 * nr * nt), dtype=object)

    print("Discretizing equations")
    for i in range(1, nr - 1):
        for j in range(1, nt - 1):
            scheme = inner_scheme(p, wr, wt, wp, i, j)
            fun[i * nt + j] = eq[0].subs(scheme)
            fun[400 + i * nt + j] = eq[1].subs(scheme)
            fun[800 + i * nt + j] = eq[2].subs(scheme)
            fun[1200 + i * nt + j] = eq[3].subs(scheme)
    for i in range(1, nt - 1):
        scheme = border_scheme_inner(p, wr, wt, wp, i, j)
        fun[i] = eq[4].subs(scheme)
        fun[400 + i] = eq[5].subs(scheme)
        fun[800 + i] = eq[6].subs(scheme)
        fun[1200 + i] = eq[7].subs(scheme)
    for i in range(1, nt - 1):
        scheme = border_scheme_outer(p, wr, wt, wp, i, j)
        fun[380 + i] = eq[8].subs(scheme)
        fun[780 + i] = eq[9].subs(scheme)
        fun[1180 + i] = eq[10].subs(scheme)
        fun[1580 + i] = eq[11].subs(scheme)
    for i in range(1, nr - 1):
        scheme = border_scheme_up(p, wr, wt, wp, i, j)
        fun[i * nt] = eq[12].subs(scheme)
        fun[400 + i * nt] = eq[13].subs(scheme)
        fun[800 + i * nt] = eq[14].subs(scheme)
        fun[1200 + i * nt] = eq[15].subs(scheme)
    for i in range(1, nr - 1):
        scheme = border_scheme_down(p, wr, wt, wp, i, j)
        fun[19 + i * nt] = eq[12].subs(scheme)
        fun[419 + i * nt] = eq[13].subs(scheme)
        fun[819 + i * nt] = eq[14].subs(scheme)
        fun[1219 + i * nt] = eq[15].subs(scheme)

    #     fun[0] = eq[8].subs(scheme)
    #     fun[19] = eq[8].subs(scheme)
    #     fun[399] = eq[8].subs(scheme)
    #     fun[380] = eq[8.subs(scheme)] puis increments de 400

    for i in range(4 * nr * nt):
        fun[i] = fun[i].subs({x: (i + 1) * dr, y: j * dt})

    var = np.concatenate(
        (p.flatten(), wr.flatten(), wt.flatten(), wp.flatten()))
    print("Transforming function to fast callable")
    for i in range(4 * nr * nt):
        fun[i] = fast_callable(fun[i], vars=tuple(var), domain=float)
    return lambda x: map(methodcaller('__call__', *x), fun)