def inv_map(self, sol: Solution) -> Solution: qinv = np.ones_like(sol.t) pinv = np.ones_like(sol.t) for ii, t in enumerate(sol.t): qinv[ii] = self.fn_q_inv(sol.y[ii], sol.dual[ii], sol.q[ii], sol.dynamical_parameters, sol.const) pinv[ii] = self.fn_p_inv(sol.y[ii], sol.dual[ii], sol.dynamical_parameters, sol.const) state = pinv qval = qinv if self.remove_parameter_dict['location'] == 'states': sol.y = np.column_stack( (sol.y[:, :self.remove_parameter_dict['index']], state, sol.y[:, self.remove_parameter_dict['index']:])) elif self.remove_parameter_dict['location'] == 'costates': sol.dual = np.column_stack( (sol.dual[:, :self.remove_parameter_dict['index']], state, sol.dual[:, self.remove_parameter_dict['index']:])) if self.remove_symmetry_dict['location'] == 'states': sol.y = np.column_stack( (sol.y[:, :self.remove_symmetry_dict['index']], qval, sol.y[:, self.remove_symmetry_dict['index']:])) elif self.remove_symmetry_dict['location'] == 'costates': sol.dual = np.column_stack( (sol.dual[:, :self.remove_symmetry_dict['index']], qval, sol.dual[:, self.remove_symmetry_dict['index']:])) sol.q = np.delete(sol.q, np.s_[-1], axis=1) sol.dynamical_parameters = sol.dynamical_parameters[:-1] return sol
def map(self, sol: Solution) -> Solution: cval = self.fn_p(sol.y[0], sol.dual[0], sol.dynamical_parameters, sol.const) qval = np.ones_like(sol.t) sol.dynamical_parameters = np.hstack((sol.dynamical_parameters, cval)) for ii, t in enumerate(sol.t): qval[ii] = self.fn_q(sol.y[ii], sol.dual[ii], sol.dynamical_parameters, sol.const) if self.remove_parameter_dict['location'] == 'states': sol.y = np.delete(sol.y, np.s_[self.remove_parameter_dict['index']], axis=1) elif self.remove_parameter_dict['location'] == 'costates': sol.dual = np.delete(sol.dual, np.s_[self.remove_parameter_dict['index']], axis=1) if self.remove_symmetry_dict['location'] == 'states': sol.y = np.delete(sol.y, np.s_[self.remove_symmetry_dict['index']], axis=1) elif self.remove_symmetry_dict['location'] == 'costates': sol.dual = np.delete(sol.dual, np.s_[self.remove_symmetry_dict['index']], axis=1) sol.q = np.column_stack((sol.q, qval)) return sol
def inv_map(self, sol: Solution) -> Solution: sol.dual = sol.y[:, self.costate_idxs] sol.y = np.delete(sol.y, self.costate_idxs, axis=1) sol.nondynamical_parameters = np.delete(sol.nondynamical_parameters, self.constraint_adjoints_idxs) return sol
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 inv_map(self, sol: Solution) -> Solution: if self.ind_state_idx is None: self.ind_state_idx = np.shape(sol.y)[1] - 1 sol.t = sol.y[:, self.ind_state_idx] sol.y = np.delete(sol.y, self.ind_state_idx, axis=1) sol.dual_t = sol.dual[:, self.ind_state_idx] sol.dual = np.delete(sol.dual, self.ind_state_idx, axis=1) return sol
def map(self, sol: Solution) -> Solution: if self.ind_state_idx is None: self.ind_state_idx = np.shape(sol.y)[1] if len(sol.dual_t) == 0: sol.dual_t = np.zeros_like(sol.t) sol.y = np.insert(sol.y, self.ind_state_idx, sol.t, axis=1) sol.dual = np.insert(sol.dual, self.ind_state_idx, sol.dual_t, axis=1) return sol
def inv_map(self, sol: Solution, retain_dual=True) -> Solution: if not retain_dual: sol.dual = empty_array sol.nondynamical_parameters = empty_array sol.cost = self.compute_cost(sol.t, sol.y, sol.q, sol.u, sol.dynamical_parameters, sol.const) 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 solve(self, solinit, **kwargs): solinit = copy.deepcopy(solinit) nstates = solinit.y.shape[1] nquads = 0 def return_nil(*_, **__): return np.array([]) if solinit.q.size > 0: nquads = solinit.q.shape[1] else: nquads = 0 self.quadrature_function = return_nil ndyn = solinit.dynamical_parameters.size nnondyn = solinit.nondynamical_parameters.size empty_array = np.array([]) if nquads == 0: # TODO: Try to vectorize def _fun(t, y, params=empty_array, const=solinit.const): return np.vstack([self.derivative_function(yi[:nstates], params[:ndyn], const) for yi in y.T]).T def _bc(ya, yb, params=empty_array, const=solinit.const): return self.boundarycondition_function(ya, yb, params[:ndyn], params[ndyn:ndyn + nnondyn], const) else: def _fun(t, y, params=empty_array, const=solinit.const): y = y.T o1 = np.vstack([self.derivative_function(yi[:nstates], params[:ndyn], const) for yi in y]) o2 = np.vstack([self.quadrature_function(yi[:nstates], params[:ndyn], const) for yi in y]) return np.hstack((o1, o2)).T def _bc(ya, yb, params=np.array([]), const=solinit.const): return self.boundarycondition_function(ya[:nstates], ya[nstates:nstates+nquads], yb[:nstates], yb[nstates:nstates+nquads], params[:ndyn], params[ndyn:ndyn+nnondyn], const) if self.derivative_function_jac is not None: def _fun_jac(t, y, params=np.array([]), const=solinit.const): y = y.T df_dy = np.zeros((y[0].size, y[0].size, t.size)) df_dp = np.zeros((y[0].size, ndyn+nnondyn, t.size)) for ii, yi in enumerate(y): df_dy[:, :, ii], _df_dp = self.derivative_function_jac(yi, params[:ndyn], const) if nstates > 1 and len(_df_dp.shape) == 1: _df_dp = np.array([_df_dp]).T df_dp[:, :, ii] = np.hstack((_df_dp, np.zeros((nstates, nnondyn)))) if ndyn + nnondyn == 0: return df_dy else: return df_dy, df_dp else: _fun_jac = None if self.boundarycondition_function_jac is not None: if nquads > 0: def _bc_jac(ya, yb, params=np.array([]), const=solinit.const): dbc_dya, dbc_dyb, dbc_dp = \ self.boundarycondition_function_jac(ya[:nstates], ya[nstates:nstates+nquads], yb[:nstates], yb[nstates:nstates+nquads], params[:ndyn], params[ndyn:ndyn+nnondyn], const) return dbc_dya, dbc_dyb, dbc_dp else: def _bc_jac(ya, yb, params=np.array([]), const=solinit.const): dbc_dya, dbc_dyb, dbc_dp = \ self.boundarycondition_function_jac(ya, yb, params[:ndyn], params[ndyn:ndyn+nnondyn], const) return dbc_dya, dbc_dyb, dbc_dp else: _bc_jac = None if nquads > 0: opt = solve_bvp(_fun, _bc, solinit.t, np.hstack((solinit.y, solinit.q)).T, np.hstack((solinit.dynamical_parameters, solinit.nondynamical_parameters)), max_nodes=self.max_nodes, fun_jac=_fun_jac, bc_jac=_bc_jac) else: opt = solve_bvp(_fun, _bc, solinit.t, solinit.y.T, np.hstack((solinit.dynamical_parameters, solinit.nondynamical_parameters)), max_nodes=self.max_nodes, fun_jac=_fun_jac, bc_jac=_bc_jac) sol = Trajectory(solinit) sol.t = opt['x'] sol.y = opt['y'].T[:, :nstates] sol.q = opt['y'].T[:, nstates:nstates+nquads] sol.dual = np.zeros_like(sol.y) if opt['p'] is not None: sol.dynamical_parameters = opt['p'][:ndyn] sol.nondynamical_parameters = opt['p'][ndyn:ndyn+nnondyn] else: sol.dynamical_parameters = np.array([]) sol.nondynamical_parameters = np.array([]) sol.converged = opt['success'] out = BVPResult(sol=sol, success=opt['success'], message=opt['message'], rms_residuals=opt['rms_residuals'], niter=opt['niter']) return out