def map(self,
            sol: Solution,
            control_costate: Union[float, np.ndarray] = 0.) -> Solution:
        idx_u_list = []

        for idx_u, (idx_y,
                    u) in enumerate(sorted(zip(self.control_idxs, sol.u.T))):
            sol.y = np.insert(sol.y, idx_y, u, axis=1)

            if isinstance(control_costate, Iterable):
                if not isinstance(control_costate, np.ndarray):
                    control_costate = np.array(control_costate)
                costate_insert = control_costate[idx_u] * np.ones_like(sol.t)
            else:
                costate_insert = control_costate * np.ones_like(sol.t)

            sol.dual = np.insert(sol.dual, -1, costate_insert, axis=1)
            if len(sol.dual_u) == 0:
                sol.dual_u = np.array([costate_insert])
            else:
                sol.dual_u = np.insert(sol.dual_u, -1, costate_insert, axis=1)

            idx_u_list.append(idx_u)

        sol.u = np.delete(sol.u, idx_u_list, axis=1)
        return sol
 def map(self, sol: Solution) -> Solution:
     idx_u_list = []
     for idx_u, (idx_y,
                 u) in enumerate(sorted(zip(self.control_idxs, sol.u.T))):
         sol.y = np.insert(sol.y, idx_y, u, axis=1)
         idx_u_list.append(idx_u)
     sol.u = np.delete(sol.u, idx_u_list, axis=1)
     return sol
        def scale_sol(sol: Trajectory, scale_factors, inv=False):

            sol = copy.deepcopy(sol)

            if inv:
                op = np.multiply
            else:
                op = np.divide

            sol.t = op(sol.t, scale_factors[0])
            sol.y = op(sol.y, scale_factors[1])
            sol.q = op(sol.q, scale_factors[2])
            if sol.u.size > 0:
                sol.u = op(sol.u, scale_factors[3])
            sol.dynamical_parameters = op(sol.dynamical_parameters,
                                          scale_factors[4])
            sol.nondynamical_parameters = op(sol.nondynamical_parameters,
                                             scale_factors[5])
            sol.const = op(sol.const, scale_factors[6])

            return sol
 def inv_map(self, sol: Solution) -> Solution:
     sol.u = sol.y[:, self.control_idxs]
     sol.y = np.delete(sol.y, self.control_idxs, axis=1)
     sol.dual = np.delete(sol.dual, self.control_idxs, axis=1)
     return sol
 def inv_map(self, sol: Solution) -> Solution:
     sol.u = np.array([
         self.compute_u(_t, _y, _lam, sol.dynamical_parameters, sol.const)
         for _t, _y, _lam, in zip(sol.t, sol.y, sol.dual)
     ])
     return sol
Ejemplo n.º 6
0
def solve(autoscale=True,
          bvp=None,
          bvp_algorithm=None,
          guess_generator=None,
          initial_helper=False,
          method='traditional',
          n_cpus=1,
          ocp=None,
          ocp_map=None,
          ocp_map_inverse=None,
          optim_options=None,
          steps=None,
          save_sols=True):
    """
    Solves the OCP using specified method

    +------------------------+-----------------+---------------------------------------+
    | Valid kwargs           | Default Value   | Valid Values                          |
    +========================+=================+=======================================+
    | autoscale              | True            | bool                                  |
    +------------------------+-----------------+---------------------------------------+
    | prob                   | None            | codegen'd BVPs                        |
    +------------------------+-----------------+---------------------------------------+
    | bvp_algorithm          | None            | prob algorithm                        |
    +------------------------+-----------------+---------------------------------------+
    | guess_generator        | None            | guess generator                       |
    +------------------------+-----------------+---------------------------------------+
    | initial_helper         | False           | bool                                  |
    +------------------------+-----------------+---------------------------------------+
    | method                 | 'traditional'   | string                                |
    +------------------------+-----------------+---------------------------------------+
    | n_cpus                 | 1               | integer                               |
    +------------------------+-----------------+---------------------------------------+
    | ocp                    | None            | :math:`\\Sigma`                       |
    +------------------------+-----------------+---------------------------------------+
    | ocp_map                | None            | :math:`\\gamma \rightarrow \\gamma`   |
    +------------------------+-----------------+---------------------------------------+
    | ocp_map_inverse        | None            | :math:`\\gamma \rightarrow \\gamma`   |
    +------------------------+-----------------+---------------------------------------+
    | optim_options          | None            | dict()                                |
    +------------------------+-----------------+---------------------------------------+
    | steps                  | None            | continuation_strategy                 |
    +------------------------+-----------------+---------------------------------------+
    | save                   | False           | bool, str                             |
    +------------------------+-----------------+---------------------------------------+

    """

    if optim_options is None:
        optim_options = {}

    # Display useful info about the environment to debug logger.
    logger.debug('\n' + __splash__ + '\n')
    from beluga import __version__ as beluga_version
    from llvmlite import __version__ as llvmlite_version
    from numba import __version__ as numba_version
    from numpy import __version__ as numpy_version
    from scipy import __version__ as scipy_version
    from sympy.release import __version__ as sympy_version

    logger.debug('beluga:\t\t' + str(beluga_version))
    logger.debug('llvmlite:\t' + str(llvmlite_version))
    logger.debug('numba:\t\t' + str(numba_version))
    logger.debug('numpy:\t\t' + str(numpy_version))
    logger.debug('python:\t\t' + str(sys.version_info[0]) + '.' +
                 str(sys.version_info[1]) + '.' + str(sys.version_info[2]))
    logger.debug('scipy:\t\t' + str(scipy_version))
    logger.debug('sympy:\t\t' + str(sympy_version) + '\n\n')
    """
    Error checking
    """
    if n_cpus < 1:
        raise ValueError('Number of cpus must be greater than 1.')
    if n_cpus > 1:
        pool = pathos.multiprocessing.Pool(processes=n_cpus)
    else:
        pool = None

    if ocp is None:
        raise NotImplementedError('\"ocp\" must be defined.')
    """
    Main code
    """

    # f_ocp = compile_direct(ocp)

    logger.debug('Using ' + str(n_cpus) + '/' +
                 str(pathos.multiprocessing.cpu_count()) + ' CPUs. ')

    if bvp is None:
        preprocessor = make_preprocessor()
        processed_ocp = preprocessor(copy.deepcopy(ocp))

        if method.lower() in ['indirect', 'traditional', 'brysonho']:
            method = 'traditional'

        if method.lower() in ['traditional', 'diffyg']:
            RFfunctor = make_indirect_method(copy.deepcopy(processed_ocp),
                                             method=method,
                                             **optim_options)
            prob = RFfunctor(copy.deepcopy(processed_ocp))
        elif method == 'direct':
            functor = make_direct_method(copy.deepcopy(processed_ocp),
                                         **optim_options)
            prob = functor(copy.deepcopy(processed_ocp))
        else:
            raise NotImplementedError

        postprocessor = make_postprocessor()
        bvp = postprocessor(copy.deepcopy(prob))

        logger.debug('Resulting BVP problem:')
        logger.debug(bvp.__repr__())

        ocp_map = bvp.map_sol
        ocp_map_inverse = bvp.inv_map_sol

    else:
        if ocp_map is None or ocp_map_inverse is None:
            raise ValueError(
                'BVP problem must have an associated \'ocp_map\' and \'ocp_map_inverse\''
            )

    solinit = Trajectory()
    solinit.const = np.array(getattr_from_list(bvp.constants, 'default_val'))
    solinit = guess_generator.generate(bvp.functional_problem, solinit,
                                       ocp_map, ocp_map_inverse)

    if initial_helper:
        sol_ocp = copy.deepcopy(solinit)
        sol_ocp = match_constants_to_states(ocp, ocp_map_inverse(sol_ocp))
        solinit.const = sol_ocp.const

    if bvp.functional_problem.compute_u is not None:
        u = np.array([
            bvp.functional_problem.compute_u(solinit.y[0],
                                             solinit.dynamical_parameters,
                                             solinit.const)
        ])
        for ii in range(len(solinit.t) - 1):
            u = np.vstack(
                (u,
                 bvp.functional_problem.compute_u(solinit.y[ii + 1],
                                                  solinit.dynamical_parameters,
                                                  solinit.const)))
        solinit.u = u
    """
    Main continuation process
    """
    time0 = time.time()
    continuation_set = run_continuation_set(bvp_algorithm, steps, solinit, bvp,
                                            pool, autoscale)
    total_time = time.time() - time0
    logger.info('Continuation process completed in %0.4f seconds.\n' %
                total_time)
    bvp_algorithm.close()
    """
    Post processing and output
    """
    out = postprocess_continuations(continuation_set, ocp_map_inverse)

    if pool is not None:
        pool.close()

    if save_sols or (isinstance(save_sols, str)):
        if isinstance(save_sols, str):
            filename = save_sols
        else:
            filename = 'data.beluga'

        save(out, ocp, bvp, filename=filename)

    return out