Exemple #1
0
def test_products():
    assert TensorProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) == R2.dx(R2.e_x)*R2.dy(R2.e_y) == 1
    assert WedgeProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) == 1
    assert TensorProduct(R2.dx, R2.dy)(None, R2.e_y) == R2.dx
    assert TensorProduct(R2.dx, R2.dy)(R2.e_x, None) == R2.dy
    assert TensorProduct(R2.dx, R2.dy)(R2.e_x) == R2.dy
    assert TensorProduct(R2.x, R2.dx) == R2.x*R2.dx
Exemple #2
0
def test_lie_derivative():
    assert LieDerivative(R2.e_x, R2.y) == R2.e_x(R2.y) == 0
    assert LieDerivative(R2.e_x, R2.x) == R2.e_x(R2.x) == 1
    assert LieDerivative(R2.e_x, R2.e_x) == Commutator(R2.e_x, R2.e_x) == 0
    assert LieDerivative(R2.e_x, R2.e_r) == Commutator(R2.e_x, R2.e_r)
    assert LieDerivative(R2.e_x+R2.e_y, R2.x) == 1
    assert LieDerivative(R2.e_x, TensorProduct(R2.dx, R2.dy))(R2.e_x, R2.e_y) == 0
Exemple #3
0
def test_correct_arguments():
    raises(ValueError, lambda : R2.e_x(R2.e_x))
    raises(ValueError, lambda : R2.e_x(R2.dx))

    raises(ValueError, lambda : Commutator(R2.e_x, R2.x))
    raises(ValueError, lambda : Commutator(R2.dx, R2.e_x))

    raises(ValueError, lambda : Differential(Differential(R2.e_x)))

    raises(ValueError, lambda : R2.dx(R2.x))

    raises(ValueError, lambda : TensorProduct(R2.e_x, R2.dx))

    raises(ValueError, lambda : LieDerivative(R2.dx, R2.dx))
    raises(ValueError, lambda : LieDerivative(R2.x, R2.dx))

    raises(ValueError, lambda : CovarDerivativeOp(R2.dx, []))
    raises(ValueError, lambda : CovarDerivativeOp(R2.x, []))

    a = Symbol('a')
    raises(ValueError, lambda : intcurve_series(R2.dx, a, R2_r.point([1,2])))
    raises(ValueError, lambda : intcurve_series(R2.x, a, R2_r.point([1,2])))

    raises(ValueError, lambda : intcurve_diffequ(R2.dx, a, R2_r.point([1,2])))
    raises(ValueError, lambda : intcurve_diffequ(R2.x, a, R2_r.point([1,2])))

    raises(ValueError, lambda : contravariant_order(R2.e_x + R2.dx))
    raises(ValueError, lambda : covariant_order(R2.e_x + R2.dx))

    raises(ValueError, lambda : contravariant_order(R2.e_x*R2.e_y))
    raises(ValueError, lambda : covariant_order(R2.dx*R2.dy))
Exemple #4
0
def mobius_strip():
    import find_metric as fm
    import tensor as t
    g, diff = fm.mobius_strip()
    R = t.Riemann(g, dim=2, sys_title='mobius_strip', flat_diff=diff)
    #metric=R.metric
    from sympy.diffgeom import TensorProduct, Manifold, Patch, CoordSystem
    manifold = Manifold("M", 2)
    patch = Patch("P", manifold)
    system = CoordSystem('mobius_strip', patch, ["u", "v"])
    u, v = system.coord_functions()
    du, dv = system.base_oneforms()
    from sympy import cos
    metric = (cos(u / 2)**2 * v**2 / 4 + cos(u / 2) * v + v**2 / 16 +
              1) * TensorProduct(du, du) + 0.25 * TensorProduct(dv, dv)
    C = Christoffel_2nd(metric=metric)
    return C
Exemple #5
0
def flat_kerr(a=0, G=1, M=0.5):
    import find_metric as fm
    from sympy.diffgeom import CoordSystem, Manifold, Patch, TensorProduct

    manifold = Manifold("M", 3)
    patch = Patch("P", manifold)
    kerr = CoordSystem("kerr", patch, ["u", "v", "w"])
    u, v, w = kerr.coord_functions()
    du, dv, dw = kerr.base_oneforms()

    g11 = (a**2 * sym.cos(v) + u**2) / (-2 * G * M * u + a**2 + u**2)
    g22 = a**2 * sym.cos(v) + u**2
    g33 = -(1 - 2 * G * M * u / (u**2 + a**2 * sym.cos(v)))
    # time independent : unphysical ?
    #g33 = 2*G*M*a**2*sym.sin(v)**4*u/(a**2*sym.cos(v) + u**2)**2 + a**2*sym.sin(v)**2 + sym.sin(v)**2*u**2
    metric = g11 * TensorProduct(du, du) + g22 * TensorProduct(
        dv, dv) + g33 * TensorProduct(dw, dw)
    C = Christoffel_2nd(metric=metric)
    return C
Exemple #6
0
def test_helpers_and_coordinate_dependent():
    one_form = R2.dr + R2.dx
    two_form = Differential(R2.x * R2.dr + R2.r * R2.dx)
    three_form = Differential(R2.y * two_form) + Differential(
        R2.x * Differential(R2.r * R2.dr))
    metric = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dy, R2.dy)
    metric_ambig = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dr, R2.dr)
    misform_a = TensorProduct(R2.dr, R2.dr) + R2.dr
    misform_b = R2.dr**4
    misform_c = R2.dx * R2.dy
    twoform_not_sym = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dx, R2.dy)
    twoform_not_TP = WedgeProduct(R2.dx, R2.dy)

    one_vector = R2.e_x + R2.e_y
    two_vector = TensorProduct(R2.e_x, R2.e_y)
    three_vector = TensorProduct(R2.e_x, R2.e_y, R2.e_x)
    two_wp = WedgeProduct(R2.e_x, R2.e_y)

    assert covariant_order(one_form) == 1
    assert covariant_order(two_form) == 2
    assert covariant_order(three_form) == 3
    assert covariant_order(two_form + metric) == 2
    assert covariant_order(two_form + metric_ambig) == 2
    assert covariant_order(two_form + twoform_not_sym) == 2
    assert covariant_order(two_form + twoform_not_TP) == 2

    assert contravariant_order(one_vector) == 1
    assert contravariant_order(two_vector) == 2
    assert contravariant_order(three_vector) == 3
    assert contravariant_order(two_vector + two_wp) == 2

    raises(ValueError, lambda: covariant_order(misform_a))
    raises(ValueError, lambda: covariant_order(misform_b))
    raises(ValueError, lambda: covariant_order(misform_c))

    assert twoform_to_matrix(metric) == Matrix([[1, 0], [0, 1]])
    assert twoform_to_matrix(twoform_not_sym) == Matrix([[1, 0], [1, 0]])
    assert twoform_to_matrix(twoform_not_TP) == Matrix([[0, -1], [1, 0]])

    raises(ValueError, lambda: twoform_to_matrix(one_form))
    raises(ValueError, lambda: twoform_to_matrix(three_form))
    raises(ValueError, lambda: twoform_to_matrix(metric_ambig))

    raises(ValueError, lambda: metric_to_Christoffel_1st(twoform_not_sym))
    raises(ValueError, lambda: metric_to_Christoffel_2nd(twoform_not_sym))
    raises(ValueError, lambda: metric_to_Riemann_components(twoform_not_sym))
    raises(ValueError, lambda: metric_to_Ricci_components(twoform_not_sym))
Exemple #7
0
def matrix_to_twoform(matrix: Matrix, base_forms: Tuple[Expr, ...]) -> Expr:
    """Logical inverse of sympy.diffgeom.twoform_to_matrix

    Args:
        matrix:
            Matrix, the matrix representation of the twoform to produce
        base_forms:
            Tuple[Expr], tuple of oneforms representing a basis of the cotangent bundle

    Returns:
        Expression of the twoform of the matrix in terms of the base oneforms
    """
    return sum([(1 if i == j else Rational(1, 2)) * TensorProduct(dx_i, dx_j) *
                matrix[i, j] for i, dx_i in enumerate(base_forms)
                for j, dx_j in enumerate(base_forms)])
Exemple #8
0
    def _metric_to_twoform(self, g):
        dim = self.dim
        system = self.system
        diff_forms = system.base_oneforms()
        u_, v_ = self.u, self.v
        u = u_
        v = v_
        if dim >= 3:
            w_ = self.w
            w = w_
        if dim == 4:
            t_ = self.t
            t = t_

        from sympy import asin, acos, atan, cos, log, ln, exp, cosh, sin, sinh, sqrt, tan, tanh
        import sympy.abc as abc
        self._abc = abc
        self._symbols = ['*', '/', '(', ')', "'", '"']
        self._letters = []
        g_ = sympy.Matrix(dim * [dim * [0]])
        # re-evaluate the metric for (u,v,w,t if 4D) which are Basescalar objects
        for i in range(dim):
            for j in range(dim):
                expr = str(g[i, j])
                self._try_expr(expr)  # evaluate expr in a safe environment
                for letter in self._letters:
                    exec('from sympy.abc import %s' % letter)
                g_[i, j] = eval(
                    expr
                )  # this will now work for any variables defined in sympy.abc
                g_[i, j] = g_[i, j].subs(u, u_)
                g_[i, j] = g_[i, j].subs(v, v_)
                if dim >= 3:
                    g_[i, j] = g_[i, j].subs(w, w_)
                if dim == 4:
                    g_[i, j] = g_[i, j].subs(t, t_)
        from sympy.diffgeom import TensorProduct
        metric_diff_form = sum([
            TensorProduct(di, dj) * g_[i, j] for i, di in enumerate(diff_forms)
            for j, dj in enumerate(diff_forms)
        ])
        return metric_diff_form
Exemple #9
0
def test_products():
    assert TensorProduct(R2.dx, R2.dy)(
        R2.e_x, R2.e_y) == R2.dx(R2.e_x) * R2.dy(R2.e_y) == 1
    assert TensorProduct(R2.dx, R2.dy)(None, R2.e_y) == R2.dx
    assert TensorProduct(R2.dx, R2.dy)(R2.e_x, None) == R2.dy
    assert TensorProduct(R2.dx, R2.dy)(R2.e_x) == R2.dy
    assert TensorProduct(R2.x, R2.dx) == R2.x * R2.dx
    assert TensorProduct(R2.e_x, R2.e_y)(
        R2.x, R2.y) == R2.e_x(R2.x) * R2.e_y(R2.y) == 1
    assert TensorProduct(R2.e_x, R2.e_y)(None, R2.y) == R2.e_x
    assert TensorProduct(R2.e_x, R2.e_y)(R2.x, None) == R2.e_y
    assert TensorProduct(R2.e_x, R2.e_y)(R2.x) == R2.e_y
    assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x
    assert TensorProduct(R2.dx, R2.e_y)(
        R2.e_x, R2.y) == R2.dx(R2.e_x) * R2.e_y(R2.y) == 1
    assert TensorProduct(R2.dx, R2.e_y)(None, R2.y) == R2.dx
    assert TensorProduct(R2.dx, R2.e_y)(R2.e_x, None) == R2.e_y
    assert TensorProduct(R2.dx, R2.e_y)(R2.e_x) == R2.e_y
    assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x
    assert TensorProduct(R2.e_x, R2.dy)(
        R2.x, R2.e_y) == R2.e_x(R2.x) * R2.dy(R2.e_y) == 1
    assert TensorProduct(R2.e_x, R2.dy)(None, R2.e_y) == R2.e_x
    assert TensorProduct(R2.e_x, R2.dy)(R2.x, None) == R2.dy
    assert TensorProduct(R2.e_x, R2.dy)(R2.x) == R2.dy
    assert TensorProduct(R2.e_y, R2.e_x)(R2.x**2 + R2.y**2,
                                         R2.x**2 + R2.y**2) == 4 * R2.x * R2.y

    assert WedgeProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) == 1
    assert WedgeProduct(R2.e_x, R2.e_y)(R2.x, R2.y) == 1
Exemple #10
0
def ocp_to_bvp(ocp):
    ws = init_workspace(ocp)
    problem_name = ws['problem_name']
    independent_variable = ws['independent_var']
    independent_variable_units = ws['independent_var_units']
    states = ws['states']
    states_rates = ws['states_rates']
    states_units = ws['states_units']
    controls = ws['controls']
    controls_units = ws['controls_units']
    constants = ws['constants']
    constants_units = ws['constants_units']
    constants_values = ws['constants_values']
    constants_of_motion = ws['constants_of_motion']
    constants_of_motion_values = ws['constants_of_motion_values']
    constants_of_motion_units = ws['constants_of_motion_units']
    symmetries = ws['symmetries']
    constraints = ws['constraints']
    constraints_units = ws['constraints_units']
    quantities = ws['quantities']
    quantities_values = ws['quantities_values']
    parameters = ws['parameters']
    parameters_units = ws['parameters_units']
    initial_cost = ws['initial_cost']
    initial_cost_units = ws['initial_cost_units']
    terminal_cost = ws['terminal_cost']
    terminal_cost_units = ws['terminal_cost_units']
    path_cost = ws['path_cost']
    path_cost_units = ws['path_cost_units']

    if initial_cost != 0:
        cost_units = initial_cost_units
    elif terminal_cost != 0:
        cost_units = terminal_cost_units
    elif path_cost != 0:
        cost_units = path_cost_units * independent_variable_units
    else:
        raise ValueError(
            'Initial, path, and terminal cost functions are not defined.')

    dynamical_parameters = []

    quantity_vars, quantity_list, derivative_fn = process_quantities(
        quantities, quantities_values)
    for var in quantity_vars.keys():
        for ii in range(len(states_rates)):
            states_rates[ii] = states_rates[ii].subs(Symbol(var),
                                                     quantity_vars[var])

    Q = Manifold(states, 'State_Space')
    E = Manifold(states + controls, 'Input_Space')
    R = Manifold([independent_variable], 'Independent_Space')
    tau_Q = FiberBundle(Q, R, 'State_Bundle')
    tau_E = FiberBundle(E, R, 'Input_Bundle')
    J1tau_Q = JetBundle(tau_Q, 1, 'Jet_Bundle')
    num_states = len(states)
    num_states_total = len(J1tau_Q.vertical.base_coords)

    hamiltonian, hamiltonian_units, costates, costates_units = make_hamiltonian(
        states, states_rates, states_units, path_cost, cost_units)
    setx = dict(zip(states + costates, J1tau_Q.vertical.base_coords))
    vector_names = [Symbol('D_' + str(x)) for x in states]
    settangent = dict(
        zip(vector_names, J1tau_Q.vertical.base_vectors[:num_states]))

    # Change original terms to be written on manifolds so the diffy g calculations are handled properly
    states = [x.subs(setx, simultaneous=True) for x in states]
    states_rates = [x.subs(setx, simultaneous=True) for x in states_rates]
    costates = J1tau_Q.vertical.base_coords[num_states:]
    constants_of_motion_values = [
        x.subs(setx, simultaneous=True) for x in constants_of_motion_values
    ]
    symmetries = [x.subs(setx, simultaneous=True) for x in symmetries]
    symmetries = [x.subs(settangent, simultaneous=True) for x in symmetries]
    constraints['initial'] = [
        x.subs(setx, simultaneous=True) for x in constraints['initial']
    ]
    constraints['terminal'] = [
        x.subs(setx, simultaneous=True) for x in constraints['terminal']
    ]
    initial_cost = initial_cost.subs(setx, simultaneous=True)
    terminal_cost = terminal_cost.subs(setx, simultaneous=True)

    hamiltonian = hamiltonian.subs(setx, simultaneous=True)

    coparameters = make_costate_names(parameters)
    coparameters_units = [
        path_cost_units / parameter_units
        for parameter_units in parameters_units
    ]
    coparameters_rates = make_costate_rates(hamiltonian, parameters,
                                            coparameters, derivative_fn)

    quads = []
    quads_rates = []
    quads_units = []
    quads += coparameters
    quads_rates += coparameters_rates
    quads_units += coparameters_units

    pi = 0
    omega = 0
    for ii in range(num_states):
        pi += WedgeProduct(J1tau_Q.base_vectors[ii],
                           J1tau_Q.base_vectors[ii + num_states])
        omega += WedgeProduct(J1tau_Q.base_oneforms[ii],
                              J1tau_Q.base_oneforms[ii + num_states])

    state_costate_pairing = 0
    for ii in range(num_states):
        state_costate_pairing += TensorProduct(
            J1tau_Q.base_coords[ii + num_states] *
            J1tau_Q.base_vectors[ii]) + TensorProduct(
                J1tau_Q.base_coords[ii] *
                J1tau_Q.base_vectors[ii + num_states])

    constant_2_value = {
        c: v
        for c, v in zip(constants_of_motion, constants_of_motion_values)
    }
    constant_2_units = {
        c: u
        for c, u in zip(constants_of_motion, constants_of_motion_units)
    }

    reduced_states = states + costates
    original_states = copy.copy(reduced_states)
    reduced_states_units = states_units + costates_units
    state_2_units = {
        x: u
        for x, u in zip(reduced_states, reduced_states_units)
    }

    X_H = pi.rcall(None, hamiltonian)
    equations_of_motion = [X_H.rcall(x) for x in J1tau_Q.vertical.base_coords]

    augmented_initial_cost, augmented_initial_cost_units, initial_lm_params, initial_lm_params_units = make_augmented_cost(
        initial_cost,
        cost_units,
        constraints,
        constraints_units,
        location='initial')
    augmented_terminal_cost, augmented_terminal_cost_units, terminal_lm_params, terminal_lm_params_units = make_augmented_cost(
        terminal_cost,
        cost_units,
        constraints,
        constraints_units,
        location='terminal')

    dV_cost_initial = J1tau_Q.verticalexteriorderivative(
        augmented_initial_cost)
    dV_cost_terminal = J1tau_Q.verticalexteriorderivative(
        augmented_terminal_cost)
    bc_initial = constraints['initial'] + [
        costate + dV_cost_initial.rcall(D_x) for costate, D_x in zip(
            costates, J1tau_Q.vertical.base_vectors[:num_states])
    ] + [
        coparameter - derivative_fn(augmented_initial_cost, parameter)
        for parameter, coparameter in zip(parameters, coparameters)
    ]
    bc_terminal = constraints['terminal'] + [
        costate - dV_cost_terminal.rcall(D_x) for costate, D_x in zip(
            costates, J1tau_Q.vertical.base_vectors[:num_states])
    ] + [
        coparameter - derivative_fn(augmented_terminal_cost, parameter)
        for parameter, coparameter in zip(parameters, coparameters)
    ]
    bc_terminal = make_time_bc(constraints, hamiltonian, bc_terminal)
    dHdu = make_dhdu(hamiltonian, controls, derivative_fn)
    control_law = make_control_law(dHdu, controls)

    tf_var = sympify('tf')
    dynamical_parameters = [tf_var] + parameters
    dynamical_parameters_units = [independent_variable_units
                                  ] + parameters_units
    nondynamical_parameters = initial_lm_params + terminal_lm_params
    nondynamical_parameters_units = initial_lm_params_units + terminal_lm_params_units

    subalgebras = []
    if len(constants_of_motion) > 0:
        logging.info('Checking commutation relations... ')
        num_consts = len(constants_of_motion)

        commutation_relations = [[None for ii in range(num_consts)]
                                 for jj in range(num_consts)]
        for ii, c1 in enumerate(constants_of_motion_values):
            for jj, c2 in enumerate(constants_of_motion_values):
                commutation_relations[ii][jj] = pi.rcall(c1, c2)

        for ii, c1 in enumerate(constants_of_motion_values):
            subalgebras.append({constants_of_motion[ii]})
            for jj in range(0, num_consts):
                if commutation_relations[ii][jj] != 0:
                    subalgebras[-1] |= {constants_of_motion[jj]}

        subalgebras = [
            gs for ii, gs in enumerate(subalgebras)
            if gs not in subalgebras[ii + 1:]
        ]
        reducible_subalgebras = [len(gs) == 1 for gs in subalgebras]
        logging.info('Done. ' + str(sum(reducible_subalgebras)) + ' of ' +
                     str(len(subalgebras)) +
                     ' subalgebras are double reducible.')

    for subalgebra in subalgebras:
        free_vars = set()
        dim = len(subalgebra)
        if dim > 1:
            raise NotImplementedError

        for c in subalgebra:
            free_vars |= constant_2_value[c].atoms(reduced_states[0])

        logging.info('Attempting reduction of ' + str(subalgebra) + '...')

        eq_set = [c - constant_2_value[c] for ii, c in enumerate(subalgebra)]

        constants_sol = sympy.solve(eq_set,
                                    list(free_vars),
                                    dict=False,
                                    minimal=True,
                                    simplify=False)
        for x in constants_sol:
            reduced_states.remove(x)
            quads.append(state_costate_pairing.rcall(x))
            quant = [constant_2_value[c] for c in subalgebra][0]
            quads_rates.append(J1tau_Q.flat(X_H).rcall(pi.rcall(None, quant)))
            quads_units.append(state_2_units[state_costate_pairing.rcall(x)])
            reduced_states.remove(state_costate_pairing.rcall(x))

        temp = copy.copy(subalgebra)
        temp2 = copy.copy(temp)
        dynamical_parameters.append(temp.pop())
        dynamical_parameters_units.append(constant_2_units[temp2.pop()])

        hamiltonian = hamiltonian.subs(constants_sol, simultaneous=True)
        pi = pi.subs(constants_sol, simultaneous=True
                     )  # TODO: Also change the vectors and differential forms
        X_H = pi.rcall(None, hamiltonian)
        equations_of_motion = [X_H.rcall(x) for x in reduced_states]

        for ii in range(len(quads_rates)):
            quads_rates[ii] = quads_rates[ii].subs(constants_sol,
                                                   simultaneous=True)

        for ii in range(len(control_law)):
            for control in control_law[ii]:
                control_law[ii][control] = control_law[ii][control].subs(
                    constants_sol, simultaneous=True)

        for ii in range(len(bc_initial)):
            bc_initial[ii] = bc_initial[ii].subs(constants_sol,
                                                 simultaneous=True)

        for ii in range(len(bc_terminal)):
            bc_terminal[ii] = bc_terminal[ii].subs(constants_sol,
                                                   simultaneous=True)

        logging.info('Done.')

    # Generate the problem data
    control_law = [{str(u): str(law[u])
                    for u in law.keys()} for law in control_law]
    out = {
        'method':
        'diffyg',
        'problem_name':
        problem_name,
        'aux_list': [{
            'type': 'const',
            'vars': [str(k) for k in constants]
        }],
        'states': [str(x) for x in reduced_states],
        'states_units': [str(state_2_units[x]) for x in reduced_states],
        'deriv_list': [str(tf_var * rate) for rate in equations_of_motion],
        'quads': [str(x) for x in quads],
        'quads_rates': [str(tf_var * x) for x in quads_rates],
        'quads_units': [str(x) for x in quads_units],
        'constants': [str(c) for c in constants],
        'constants_units': [str(c) for c in constants_units],
        'constants_values': [float(c) for c in constants_values],
        'constants_of_motion': [str(c) for c in constants_of_motion],
        'dynamical_parameters': [str(c) for c in dynamical_parameters],
        'dynamical_parameters_units':
        [str(c) for c in dynamical_parameters_units],
        'nondynamical_parameters': [str(c) for c in nondynamical_parameters],
        'nondynamical_parameters_units':
        [str(c) for c in nondynamical_parameters_units],
        'independent_variable':
        str(independent_variable),
        'independent_variable_units':
        str(independent_variable_units),
        'control_list': [str(x) for x in it.chain(controls)],
        'controls': [str(u) for u in controls],
        'hamiltonian':
        str(hamiltonian),
        'hamiltonian_units':
        str(hamiltonian_units),
        'num_states':
        len(reduced_states),
        'dHdu':
        str(dHdu),
        'bc_initial': [str(_) for _ in bc_initial],
        'bc_terminal': [str(_) for _ in bc_terminal],
        'control_options':
        control_law,
        'num_controls':
        len(controls)
    }

    states_2_constants_fn = [
        make_jit_fn([str(x) for x in original_states], str(c))
        for c in constants_of_motion_values
    ]
    states_2_states_fn = [
        make_jit_fn([str(x) for x in original_states], str(y))
        for y in reduced_states
    ]

    def guess_mapper(sol):
        n_c = len(constants_of_motion)
        if n_c == 0:
            return sol
        sol_out = Solution()
        sol_out.t = copy.copy(sol.t)
        sol_out.y = np.array([[fn(*sol.y[0]) for fn in states_2_states_fn]])
        sol_out.q = sol.q
        if len(quads) > 0:
            sol_out.q = -0.0 * np.array([np.ones((len(quads)))])
        sol_out.dynamical_parameters = sol.dynamical_parameters
        sol_out.dynamical_parameters[-n_c:] = np.array(
            [fn(*sol.y[0]) for fn in states_2_constants_fn])
        sol_out.nondynamical_parameters = sol.nondynamical_parameters
        sol_out.aux = sol.aux
        return sol_out

    return out, guess_mapper
Exemple #11
0
from sympy import sin, trigsimp, simplify
from sympy.abc import r
from sympy.diffgeom import metric_to_Riemann_components

dim = 2
m = Manifold("M", dim)
patch = Patch("P", m)

cartesian = CoordSystem("cartesian", patch, ["x", "y"])
flat_sphere = CoordSystem("flat_sphere", patch, ["theta", "phi"])

x, y = cartesian.coord_functions()
theta, phi = flat_sphere.coord_functions()
dtheta, dphi = flat_sphere.base_oneforms()

metric_diff_form = r**2 * TensorProduct(
    dtheta, dtheta) + r**2 * sin(theta)**2 * TensorProduct(dphi, dphi)
R = metric_to_Riemann_components(metric_diff_form)


def tuple_to_list(t):
    return list(map(tuple_to_list, t)) if isinstance(t, (list, tuple)) else t


simpR = tuple_to_list(R)
for m in range(dim):
    for i in range(dim):
        for j in range(dim):
            for k in range(dim):
                expr = str(R[m][i][j][k])
                expr = trigsimp(expr)
                expr = simplify(expr)
Exemple #12
0
def ocp_to_bvp(ocp, **kwargs):
    """
    Converts an OCP to a BVP using diffy G methods.

    :param ocp: An OCP.
    :return: bvp, map, map_inverse
    """

    logging.warning(
        '\'diffyg_deprecated\' method is deprecated and will be removed in a later version, use \'indirect\'.'
    )

    ws = init_workspace(ocp)
    problem_name = ws['problem_name']
    independent_variable = ws['independent_var']
    independent_variable_units = ws['independent_var_units']
    states = ws['states']
    states_rates = ws['states_rates']
    states_units = ws['states_units']
    controls = ws['controls']
    controls_units = ws['controls_units']
    constants = ws['constants']
    constants_units = ws['constants_units']
    constants_values = ws['constants_values']
    constants_of_motion = ws['constants_of_motion']
    constants_of_motion_values = ws['constants_of_motion_values']
    constants_of_motion_values_original = copy.deepcopy(
        constants_of_motion_values)
    constants_of_motion_units = ws['constants_of_motion_units']
    symmetries = ws['symmetries']
    constraints = ws['constraints']
    constraints_units = ws['constraints_units']
    constraints_lower = ws['constraints_lower']
    constraints_upper = ws['constraints_upper']
    constraints_activators = ws['constraints_activators']
    constraints_method = ws['constraints_method']
    switches = ws['switches']
    switches_values = ws['switches_values']
    switches_conditions = ws['switches_conditions']
    switches_tolerance = ws['switches_tolerance']
    parameters = ws['parameters']
    parameters_units = ws['parameters_units']
    initial_cost = ws['initial_cost']
    initial_cost_units = ws['initial_cost_units']
    terminal_cost = ws['terminal_cost']
    terminal_cost_units = ws['terminal_cost_units']
    path_cost = ws['path_cost']
    path_cost_units = ws['path_cost_units']

    if initial_cost != 0:
        cost_units = initial_cost_units
    elif terminal_cost != 0:
        cost_units = terminal_cost_units
    elif path_cost != 0:
        cost_units = path_cost_units * independent_variable_units
    else:
        raise ValueError(
            'Initial, path, and terminal cost functions are not defined.')
    """
    Deal with path constraints
    """
    for ii, c in enumerate(constraints['path']):
        if constraints_method['path'] is None:
            raise NotImplementedError

        if constraints_method['path'][ii].lower() == 'utm':
            path_cost += utm_path(c, constraints_lower['path'][ii],
                                  constraints_upper['path'][ii],
                                  constraints_activators['path'][ii])
        elif constraints_method['path'][ii].lower() == 'epstrig':
            path_cost += epstrig_path(c, constraints_lower['path'][ii],
                                      constraints_upper['path'][ii],
                                      constraints_activators['path'][ii])
            upper = constraints_upper['path'][ii]
            lower = constraints_lower['path'][ii]
            subber = dict(
                zip([constraints['path'][ii]],
                    [(upper - lower) / 2 * sympy.sin(constraints['path'][ii]) +
                     (upper + lower) / 2]))
            for ii in range(len(states_rates)):
                states_rates[ii] = states_rates[ii].subs(subber,
                                                         simultaneous=True)
        else:
            raise NotImplementedError('Unknown path constraint method \"' +
                                      str(constraints_method['path'][ii]) +
                                      '\"')

    dynamical_parameters = []
    """
    Deal with staging and switches
    """
    for ii in range(len(switches)):
        if isinstance(switches_values[ii], list):
            true_value = 0
            for jj in range(len(switches_values[ii])):
                temp_value = switches_values[ii][jj]
                for kk in range(len(switches_conditions[ii][jj])):
                    temp_value *= rash_mult(switches_conditions[ii][jj][kk],
                                            switches_tolerance[ii])
                true_value += temp_value
            switches_values[ii] = true_value
    """
    Make substitutions with the switches
    """
    switch_vars, switch_list, derivative_fn = process_quantities(
        switches, switches_values)
    for var in switch_vars.keys():
        initial_cost = initial_cost.subs(Symbol(var), switch_vars[var])
        path_cost = path_cost.subs(Symbol(var), switch_vars[var])
        terminal_cost = terminal_cost.subs(Symbol(var), switch_vars[var])
        for ii in range(len(states_rates)):
            states_rates[ii] = states_rates[ii].subs(Symbol(var),
                                                     switch_vars[var])

    Q = Manifold(states, 'State_Space')
    E = Manifold(states + controls, 'Input_Space')
    R = Manifold([independent_variable], 'Independent_Space')
    tau_Q = FiberBundle(Q, R, 'State_Bundle')
    tau_E = FiberBundle(E, R, 'Input_Bundle')
    J1tau_Q = JetBundle(tau_Q, 1, 'Jet_Bundle')
    num_states = len(states)
    num_states_total = len(J1tau_Q.vertical.base_coords)

    hamiltonian, hamiltonian_units, costates, costates_units = make_hamiltonian(
        states, states_rates, states_units, path_cost, cost_units)

    setx = dict(zip(states + costates, J1tau_Q.vertical.base_coords))
    vector_names = [Symbol('D_' + str(x)) for x in states]
    settangent = dict(
        zip(vector_names, J1tau_Q.vertical.base_vectors[:num_states]))

    # Change original terms to be written on manifolds so the diffy g calculations are handled properly
    states = [x.subs(setx, simultaneous=True) for x in states]
    states_rates = [x.subs(setx, simultaneous=True) for x in states_rates]
    costates = J1tau_Q.vertical.base_coords[num_states:]
    constants_of_motion_values = [
        x.subs(setx, simultaneous=True) for x in constants_of_motion_values
    ]
    constants_of_motion_values_original = [
        x.subs(setx, simultaneous=True)
        for x in constants_of_motion_values_original
    ]
    symmetries = [x.subs(setx, simultaneous=True) for x in symmetries]
    symmetries = [x.subs(settangent, simultaneous=True) for x in symmetries]
    constraints['initial'] = [
        x.subs(setx, simultaneous=True) for x in constraints['initial']
    ]
    constraints['terminal'] = [
        x.subs(setx, simultaneous=True) for x in constraints['terminal']
    ]
    initial_cost = initial_cost.subs(setx, simultaneous=True)
    terminal_cost = terminal_cost.subs(setx, simultaneous=True)

    hamiltonian = hamiltonian.subs(setx, simultaneous=True)
    dhdt = derivative_fn(hamiltonian, independent_variable)
    # if dhdt == 0:
    #     constants_of_motion = constants_of_motion + [Symbol('hamiltonian')]
    #     constants_of_motion_values = constants_of_motion_values + [hamiltonian]
    #     constants_of_motion_units = constants_of_motion_units + [hamiltonian_units]

    coparameters = make_costate_names(parameters)
    coparameters_units = [
        path_cost_units / parameter_units
        for parameter_units in parameters_units
    ]
    coparameters_rates = make_costate_rates(hamiltonian, parameters,
                                            coparameters, derivative_fn)

    quads = []
    quads_rates = []
    quads_units = []
    quads += coparameters
    quads_rates += coparameters_rates
    quads_units += coparameters_units

    pi = 0
    omega = 0
    for ii in range(num_states):
        # pi += WedgeProduct(J1tau_Q.base_vectors[ii], J1tau_Q.base_vectors[ii + num_states])
        pi += TensorProduct(J1tau_Q.base_vectors[ii], J1tau_Q.base_vectors[ii + num_states]) - \
              TensorProduct(J1tau_Q.base_vectors[ii + num_states], J1tau_Q.base_vectors[ii])
        omega += WedgeProduct(J1tau_Q.base_oneforms[ii],
                              J1tau_Q.base_oneforms[ii + num_states])

    state_costate_pairing = 0
    for ii in range(num_states):
        state_costate_pairing += TensorProduct(J1tau_Q.base_coords[ii + num_states]*J1tau_Q.base_vectors[ii]) + \
                                 TensorProduct(J1tau_Q.base_coords[ii]*J1tau_Q.base_vectors[ii + num_states])

    constant_2_units = {
        c: u
        for c, u in zip(constants_of_motion, constants_of_motion_units)
    }

    reduced_states = states + costates
    original_states = copy.copy(reduced_states)
    reduced_states_units = states_units + costates_units
    state_2_units = {
        x: u
        for x, u in zip(reduced_states, reduced_states_units)
    }

    X_H = pi.rcall(None, hamiltonian)
    equations_of_motion = [X_H.rcall(x) for x in J1tau_Q.vertical.base_coords]

    augmented_initial_cost, augmented_initial_cost_units, initial_lm_params, initial_lm_params_units =\
        make_augmented_cost(initial_cost, cost_units, constraints, constraints_units, location='initial')
    augmented_terminal_cost, augmented_terminal_cost_units, terminal_lm_params, terminal_lm_params_units =\
        make_augmented_cost(terminal_cost, cost_units, constraints, constraints_units, location='terminal')

    dV_cost_initial = J1tau_Q.verticalexteriorderivative(
        augmented_initial_cost)
    dV_cost_terminal = J1tau_Q.verticalexteriorderivative(
        augmented_terminal_cost)
    bc_initial = constraints['initial'] + \
        [costate + dV_cost_initial.rcall(D_x) for costate, D_x
         in zip(costates, J1tau_Q.vertical.base_vectors[:num_states])] + \
        [coparameter - derivative_fn(augmented_initial_cost, parameter) for parameter, coparameter
         in zip(parameters, coparameters)]
    bc_terminal = constraints['terminal'] + \
        [costate - dV_cost_terminal.rcall(D_x) for costate, D_x
         in zip(costates, J1tau_Q.vertical.base_vectors[:num_states])] + \
        [coparameter - derivative_fn(augmented_terminal_cost, parameter) for parameter, coparameter
         in zip(parameters, coparameters)]
    time_bc = make_time_bc(constraints, derivative_fn, hamiltonian,
                           independent_variable)

    if time_bc is not None:
        bc_terminal += [time_bc]
    dHdu = make_dhdu(hamiltonian, controls, derivative_fn)
    control_law = make_control_law(dHdu, controls)

    tf = sympify('_tf')
    # bc_terminal = [bc.subs(independent_variable, tf, simultaneous=True) for bc in bc_terminal]
    dynamical_parameters = parameters + [tf]
    dynamical_parameters_units = parameters_units + [
        independent_variable_units
    ]
    nondynamical_parameters = initial_lm_params + terminal_lm_params
    nondynamical_parameters_units = initial_lm_params_units + terminal_lm_params_units

    subalgebras = []
    if len(constants_of_motion) > 0:
        logging.debug('Checking commutation relations... ')
        num_consts = len(constants_of_motion)

        commutation_relations = [[None for _ in range(num_consts)]
                                 for _ in range(num_consts)]
        for ii, c1 in enumerate(constants_of_motion_values):
            for jj, c2 in enumerate(constants_of_motion_values):
                commutation_relations[ii][jj] = pi.rcall(c1, c2)

        for ii, c1 in enumerate(constants_of_motion_values):
            subalgebras.append({constants_of_motion[ii]})
            for jj in range(0, num_consts):
                if commutation_relations[ii][jj] != 0:
                    subalgebras[-1] |= {constants_of_motion[jj]}

        subalgebras = [
            gs for ii, gs in enumerate(subalgebras)
            if gs not in subalgebras[ii + 1:]
        ]
        reducible_subalgebras = [len(gs) == 1 for gs in subalgebras]
        logging.debug('Done. ' + str(sum(reducible_subalgebras)) + ' of ' +
                      str(len(subalgebras)) +
                      ' subalgebras are double reducible.')

    for subalgebra in subalgebras:
        constant_2_value = {
            c: v
            for c, v in zip(constants_of_motion, constants_of_motion_values)
        }
        dim = len(subalgebra)
        if dim > 1:
            raise NotImplementedError
        # G_name = 'G_' + str(subalgebra).replace('{','').replace('}','')
        # G = LieGroup(list(subalgebra), G_name)
        # h = constant_2_value[constants_of_motion[0]]

        logging.debug('Attempting reduction of ' + str(subalgebra) + '...')
        # M_r, phi = restrictor(M, dict([(x, constant_2_value[x]) for x in list(subalgebra)]))
        free_vars = set()
        const = dict([(x, constant_2_value[x]) for x in list(subalgebra)])
        for c in const.keys():
            free_vars |= const[c].atoms(reduced_states[0])

        eq_set = [c - const[c] for c in const.keys()]
        constants_sol = sympy.solve(eq_set,
                                    list(free_vars),
                                    dict=True,
                                    minimal=True,
                                    simplify=False)[0]

        # hamiltonian = phi.pullback(hamiltonian)

        # g_ii = 0
        # for ii in range(len(M_r.base_coords)):
        #     for jj in range(len(M_r.base_coords)):
        #         g_ii += TensorProduct(M_r.base_oneforms[ii], M_r.base_oneforms[jj])
        # omega = phi.pullback(omega)
        # # pi = M_r.sharp(omega)
        # constants_of_motion = [phi.pullback(c) for c in constants_of_motion]
        # dH = M_r.exteriorderivative(hamiltonian)
        # eoms = omega.rcall(None, M_r.sharp(dH))
        # breakpoint()
        # eps_c = omega.rcall(None, M_r.sharp(M_r.exteriorderivative(constants_of_motion[0])))
        # quad_field = eoms.rcall(M_r.sharp(omega.rcall(None, constants_of_motion[0])))
        # breakpoint()
        #
        # breakpoint()
        for x in constants_sol:
            reduced_states.remove(x)
            quads.append(state_costate_pairing.rcall(x))
            quant = [constant_2_value[c] for c in subalgebra][0]
            quads_rates.append(J1tau_Q.flat(X_H).rcall(pi.rcall(None, quant)))
            quads_units.append(state_2_units[state_costate_pairing.rcall(x)])
            reduced_states.remove(state_costate_pairing.rcall(x))

        temp = copy.copy(subalgebra)
        temp2 = copy.copy(temp)
        dynamical_parameters.append(temp.pop())
        dynamical_parameters_units.append(constant_2_units[temp2.pop()])

        hamiltonian = hamiltonian.subs(constants_sol, simultaneous=True)
        pi = pi.subs(constants_sol, simultaneous=True
                     )  # TODO: Also change the vectors and differential forms
        X_H = pi.rcall(None, hamiltonian)
        equations_of_motion = [X_H.rcall(x) for x in reduced_states]

        for ii in range(len(quads_rates)):
            quads_rates[ii] = quads_rates[ii].subs(constants_sol,
                                                   simultaneous=True)

        for ii in range(len(control_law)):
            for control in control_law[ii]:
                control_law[ii][control] = control_law[ii][control].subs(
                    constants_sol, simultaneous=True)

        for ii in range(len(constants_of_motion_values)):
            constants_of_motion_values[ii] = constants_of_motion_values[
                ii].subs(constants_sol, simultaneous=True)

        for ii in range(len(bc_initial)):
            bc_initial[ii] = bc_initial[ii].subs(constants_sol,
                                                 simultaneous=True)

        for ii in range(len(bc_terminal)):
            bc_terminal[ii] = bc_terminal[ii].subs(constants_sol,
                                                   simultaneous=True)

        logging.debug('Done.')

    # Generate the problem data
    control_law = [{str(u): str(law[u])
                    for u in law.keys()} for law in control_law]
    out = {
        'method':
        'diffyg',
        'problem_name':
        problem_name,
        'control_method':
        '',
        'consts': [str(k) for k in constants],
        'initial_cost':
        None,
        'initial_cost_units':
        None,
        'path_cost':
        None,
        'path_cost_units':
        None,
        'terminal_cost':
        None,
        'terminal_cost_units':
        None,
        'states': [str(x) for x in reduced_states],
        'states_units': [str(state_2_units[x]) for x in reduced_states],
        'states_rates': [str(tf * rate) for rate in equations_of_motion],
        'states_jac': [None, None],
        'quads': [str(x) for x in quads],
        'quads_rates': [str(tf * x) for x in quads_rates],
        'quads_units': [str(x) for x in quads_units],
        'path_constraints': [],
        'path_constraints_units': [],
        'constants': [str(c) for c in constants],
        'constants_units': [str(c) for c in constants_units],
        'constants_values': [float(c) for c in constants_values],
        'constants_of_motion': [str(c) for c in constants_of_motion],
        'dynamical_parameters': [str(c) for c in dynamical_parameters],
        'dynamical_parameters_units':
        [str(c) for c in dynamical_parameters_units],
        'nondynamical_parameters': [str(c) for c in nondynamical_parameters],
        'nondynamical_parameters_units':
        [str(c) for c in nondynamical_parameters_units],
        'control_list': [str(x) for x in it.chain(controls)],
        'controls': [str(u) for u in controls],
        'hamiltonian':
        str(hamiltonian),
        'hamiltonian_units':
        str(hamiltonian_units),
        'num_states':
        len(reduced_states),
        'dHdu': [str(x) for x in dHdu],
        'bc_initial': [str(_) for _ in bc_initial],
        'bc_terminal': [str(_) for _ in bc_terminal],
        'control_options':
        control_law,
        'num_controls':
        len(controls)
    }

    states_2_constants_fn = [
        make_jit_fn([str(x) for x in original_states + controls], str(c))
        for c in constants_of_motion_values_original
    ]
    states_2_reduced_states_fn = [
        make_jit_fn([str(x) for x in original_states], str(y))
        for y in reduced_states
    ]

    constants_2_states_fn = [
        make_jit_fn([str(x) for x in reduced_states + constants_of_motion],
                    str(y)) for y in constants_of_motion
    ]

    def guess_map(sol, _compute_control=None):
        if _compute_control is None:
            raise ValueError(
                'Guess mapper not properly set up. Bind the control law to keyword \'_compute_control\''
            )
        sol_out = copy.deepcopy(sol)
        nodes = len(sol.t)
        n_c = len(constants_of_motion)
        sol_out.t = copy.copy(sol.t / sol.t[-1])
        sol_out.y = np.array([[
            fn(*sol.y[ii], *sol.dual[ii]) for fn in states_2_reduced_states_fn
        ] for ii in range(sol.t.size)])
        sol_out.q = sol.q
        if len(quads) > 0:
            sol_out.q = -0.0 * np.array([np.ones((len(quads)))])
        sol_out.dynamical_parameters = np.hstack(
            (sol.dynamical_parameters, sol.t[-1],
             np.array([
                 fn(*sol.y[0], *sol.dual[0], *sol.u[0])
                 for fn in states_2_constants_fn
             ])))
        sol_out.nondynamical_parameters = np.ones(len(nondynamical_parameters))
        sol_out.u = np.array([]).reshape((nodes, 0))
        sol_out.const = sol.const
        return sol_out

    def guess_map_inverse(sol, _compute_control=None):
        if _compute_control is None:
            raise ValueError(
                'Guess mapper not properly set up. Bind the control law to keyword \'_compute_control\''
            )
        sol_out = copy.deepcopy(sol)
        sol_out.u = np.vstack([
            _compute_control(yi, None, sol.dynamical_parameters, sol.const)
            for yi in sol.y
        ])
        return sol_out

    return out, guess_map, guess_map_inverse
from sympy import pprint
g = Function('g')
s_field = g(R2.x, R2.y)
#Vector fields:
e_x, e_y, = R2.e_x, R2.e_y
#Differentials:
dg = Differential(s_field)
dg
pprint(dg(e_x))
pprint(dg(e_y))
# TensorProduct Examples
from sympy import Function
from sympy.diffgeom.rn import R2
from sympy.diffgeom import TensorProduct
from sympy import pprint
TensorProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y)
TensorProduct(R2.dx, R2.dy)(R2.e_y, R2.e_x)
TensorProduct(R2.dx, R2.x*R2.dy)(R2.x*R2.e_x, R2.e_y)
#You can nest tensor products.
tp1 = TensorProduct(R2.dx, R2.dy)
TensorProduct(tp1, R2.dx)(R2.e_x, R2.e_y, R2.e_x)
#You can make partial contraction for instance when ‘raising an index’. Putting None in the second argument of rcall means that the respective position in the tensor product is left as it is.
TP = TensorProduct
metric = TP(R2.dx, R2.dx) + 3*TP(R2.dy, R2.dy)
metric.rcall(R2.e_y, None)
# WedgeProduct Examples
from sympy import Function
from sympy.diffgeom.rn import R2
from sympy.diffgeom import WedgeProduct
from sympy import pprint