Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RTR/RTM] Algebraic states are states #907

Open
wants to merge 56 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e597291
feat: alternative partition recommendation
Ipuch Jan 23, 2025
9b8fef0
refactor: making partionned_forward_dynamics more flexible for colloc…
Ipuch Jan 24, 2025
2187a56
lint: holonomic model
Ipuch Jan 26, 2025
4da2bba
feat: making sure algebraic states are states. Rolling.
Ipuch Jan 26, 2025
3fbf174
fix test: restoring tf dependant dynamics tests
Ipuch Jan 27, 2025
cc50213
docs : stochastic
Ipuch Jan 27, 2025
2bdf6de
refactor: splitting ode_solver script
Ipuch Jan 30, 2025
bb2cedc
feat/ fix: I found all the places with inconsistent n_cols for algebr…
Ipuch Jan 30, 2025
6883210
feat: handling 2d dim with partitionned states
Ipuch Jan 30, 2025
42fe411
feat: algebraic states as proper entry of OCP
Ipuch Jan 30, 2025
c7f956e
Merge remote-tracking branch 'pyomeca/master' into algebraic
Ipuch Jan 31, 2025
52e57de
example: holonomic refactor plot
Ipuch Jan 31, 2025
cfa1ced
example: holonomic algebraic
Ipuch Jan 31, 2025
c2b8774
fix: integrator algebraic states offset idx
Ipuch Jan 31, 2025
2090518
refactor: standardizing the way variable size is written
Ipuch Jan 31, 2025
b146b05
refactor: giving the right size to OptimizationVariableList even if n…
Ipuch Jan 31, 2025
437c72c
fix: for tests to pass
Ipuch Jan 31, 2025
000d740
tests: fixed
Ipuch Jan 31, 2025
5aef666
fix: IRK case
Ipuch Jan 31, 2025
6f86c93
some comment to help me debug
Ipuch Jan 31, 2025
e9f4901
tests: fix the numerical time series utils to fit the one in the OCP …
Ipuch Jan 31, 2025
1dc116c
fix: integrated values
Ipuch Jan 31, 2025
7b19efb
todos
Ipuch Feb 3, 2025
a200e03
fix: on algebraic states
Ipuch Feb 4, 2025
5c87647
feat: allow for multiple ODE Solvers for multiphases problems.
Ipuch Feb 4, 2025
21e6030
hacky: disgusting solution, need to make sure i can skip any intermed…
Ipuch Feb 4, 2025
cf04062
cherry pick ode solver test
Ipuch Feb 7, 2025
f312c24
very poor success @restoring stochastic...
Ipuch Feb 7, 2025
fa080a2
refactor feat delete: astates stuff no longer neeeded
Ipuch Feb 7, 2025
f1665c9
Merge branch 'master' into algebraic
Ipuch Feb 19, 2025
d89ebf3
make sure n_cx = 3 is used
Ipuch Feb 19, 2025
3d92b82
tests: restore example
Ipuch Feb 19, 2025
21f3516
tests: algebraic holonomic pb
Ipuch Feb 19, 2025
015f042
Merge remote-tracking branch 'pyomeca/master' into algebraic
Ipuch Feb 27, 2025
6f92347
fix: obstacle avoidance
EveCharbie Feb 28, 2025
b286aed
fix: test arm_reaching_collocation
EveCharbie Feb 28, 2025
5c7fb05
removed comments
EveCharbie Feb 28, 2025
b8fb0eb
blacked
EveCharbie Feb 28, 2025
127c468
refactor: moving the intermediate cx created in the optimizationVaria…
Ipuch Mar 4, 2025
f462739
changes requested by pariterre
EveCharbie Mar 4, 2025
88e24fa
refactor: n_algebraic_states_decision_steps calls n_states_decision_s…
Ipuch Mar 4, 2025
90f20a1
refactor: deindenting, nlp method declare_shooting_points
Ipuch Mar 4, 2025
f8196e1
final refactor: set node index is a method of nlp
Ipuch Mar 4, 2025
9a97a10
blacking
Ipuch Mar 4, 2025
2e86673
sorted variables for non collocation SOCP
EveCharbie Feb 28, 2025
21c443a
tried to fix collocation
EveCharbie Feb 28, 2025
f5c3d12
EOD: m and cov init do not work
EveCharbie Feb 28, 2025
d71262e
I think I fixed the auto initialization !!!!
EveCharbie Mar 1, 2025
f7c2a3c
blacked
EveCharbie Mar 1, 2025
82d1196
Values of the implicit test were changed... --'
EveCharbie Mar 1, 2025
aba8993
blacked
EveCharbie Mar 1, 2025
1dbd1a9
decimal
EveCharbie Mar 1, 2025
8440498
doc: declare shooting was missing
Ipuch Mar 4, 2025
d506f21
test: push to delete
Ipuch Mar 4, 2025
ceff148
Merge branch 'master' into algebraic
Ipuch Mar 4, 2025
745c62f
test restored grrr
Ipuch Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions bioptim/dynamics/configure_new_variable.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from casadi import MX, SX, vertcat
import numpy as np
from casadi import MX, SX, vertcat

from .fatigue.fatigue_dynamics import FatigueList, MultiFatigueInterface
from ..gui.plot import CustomPlot
Expand Down Expand Up @@ -291,7 +291,8 @@ def _declare_cx_and_plot(self):
for node_index in range(
self.nlp.n_controls_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
cx_scaled = self.define_cx_scaled(n_col=3, node_index=node_index)
n_cx = 3
cx_scaled = self.define_cx_scaled(n_col=n_cx, node_index=node_index)
cx = self.define_cx_unscaled(cx_scaled, self.nlp.u_scaling[self.name].scaling)
self.nlp.controls.append(
self.name,
Expand Down Expand Up @@ -338,10 +339,9 @@ def _declare_cx_and_plot(self):
for node_index in range(
self.nlp.n_states_nodes if self.nlp.phase_dynamics == PhaseDynamics.ONE_PER_NODE else 1
):
n_cx = 2
n_cx = self.nlp.ode_solver.n_required_cx + 2
cx_scaled = self.define_cx_scaled(n_col=n_cx, node_index=node_index)
cx = self.define_cx_unscaled(cx_scaled, self.nlp.a_scaling[self.name].scaling)

self.nlp.algebraic_states.append(
self.name,
cx,
Expand All @@ -350,18 +350,16 @@ def _declare_cx_and_plot(self):
node_index,
)
if not self.skip_plot:
all_variables_in_one_subplot = True if self.name in ["m", "cov", "k"] else False
self.nlp.plot[f"{self.name}_algebraic"] = CustomPlot(
lambda t0, phases_dt, node_idx, x, u, p, a, d: (
a[self.nlp.algebraic_states.key_index(self.name), :]
if a.any()
else np.ndarray((cx[0].shape[0], 1)) * np.nan
),
plot_type=PlotType.STEP,
plot_type=PlotType.INTEGRATED,
axes_idx=self.axes_idx,
legend=self.legend,
combine_to=self.combine_name,
all_variables_in_one_subplot=all_variables_in_one_subplot,
)


Expand Down
46 changes: 18 additions & 28 deletions bioptim/dynamics/configure_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,12 +401,7 @@
ocp, nlp, n_noised_controls=n_noised_tau, n_references=nlp.model.n_references
)
ConfigureProblem.configure_stochastic_ref(ocp, nlp, n_references=nlp.model.n_references)
n_collocation_points = 1
if isinstance(problem_type, SocpType.COLLOCATION):
n_collocation_points += problem_type.polynomial_degree
ConfigureProblem.configure_stochastic_m(
ocp, nlp, n_noised_states=n_noised_states, n_collocation_points=n_collocation_points
)
ConfigureProblem.configure_stochastic_m(ocp, nlp, n_noised_states=n_noised_states)

if isinstance(problem_type, SocpType.TRAPEZOIDAL_EXPLICIT):
if initial_matrix is None:
Expand Down Expand Up @@ -479,12 +474,7 @@
ocp, nlp, n_noised_controls=n_noised_tau, n_references=nlp.model.n_references
)
ConfigureProblem.configure_stochastic_ref(ocp, nlp, n_references=nlp.model.n_references)
n_collocation_points = 1
if isinstance(problem_type, SocpType.COLLOCATION):
n_collocation_points += problem_type.polynomial_degree
ConfigureProblem.configure_stochastic_m(
ocp, nlp, n_noised_states=n_noised_states, n_collocation_points=n_collocation_points
)
ConfigureProblem.configure_stochastic_m(ocp, nlp, n_noised_states=n_noised_states)

Check warning on line 477 in bioptim/dynamics/configure_problem.py

View check run for this annotation

Codecov / codecov/patch

bioptim/dynamics/configure_problem.py#L477

Added line #L477 was not covered by tests

if isinstance(problem_type, SocpType.TRAPEZOIDAL_EXPLICIT):
if initial_matrix is None:
Expand Down Expand Up @@ -1515,9 +1505,9 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
)

@staticmethod
Expand Down Expand Up @@ -1548,9 +1538,9 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
skip_plot=True,
)

Expand Down Expand Up @@ -1580,9 +1570,9 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
skip_plot=True,
)

Expand Down Expand Up @@ -1638,9 +1628,9 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
)

@staticmethod
Expand Down Expand Up @@ -1669,9 +1659,9 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
)

@staticmethod
Expand All @@ -1697,13 +1687,13 @@
ocp,
nlp,
as_states=False,
as_controls=False,
as_controls=True,
as_states_dot=False,
as_algebraic_states=True,
as_algebraic_states=False,
)

@staticmethod
def configure_stochastic_m(ocp, nlp, n_noised_states: int, n_collocation_points: int = 1):
def configure_stochastic_m(ocp, nlp, n_noised_states: int):
"""
Configure the helper matrix M (from Gillis 2013 : https://doi.org/10.1109/CDC.2013.6761121).

Expand All @@ -1719,11 +1709,11 @@

name_m = []
for name_1 in [f"X_{i}" for i in range(n_noised_states)]:
for name_2 in [f"X_{i}" for i in range(n_noised_states * n_collocation_points)]:
for name_2 in [f"X_{i}" for i in range(n_noised_states)]:
name_m += [name_1 + "_&_" + name_2]
nlp.variable_mappings[name] = BiMapping(
list(range(n_noised_states * n_noised_states * n_collocation_points)),
list(range(n_noised_states * n_noised_states * n_collocation_points)),
list(range(n_noised_states * n_noised_states)),
list(range(n_noised_states * n_noised_states)),
)
ConfigureProblem.configure_new_variable(
name,
Expand Down
17 changes: 14 additions & 3 deletions bioptim/dynamics/integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__(self, ode: dict, ode_opt: dict):
self._x_sym_modified,
self.u_sym,
self.param_sym,
self.a_sym,
self._a_sym_modified,
self.numerical_timeseries_sym,
],
self.dxdt(
Expand Down Expand Up @@ -130,6 +130,10 @@ def _time_xall_from_dt_func(self) -> Function:
def _x_sym_modified(self):
return self.x_sym

@property
def _a_sym_modified(self):
return self.a_sym

@property
def _input_names(self):
return ["t_span", "x0", "u", "p", "a", "d"]
Expand Down Expand Up @@ -585,6 +589,10 @@ def _initialize(self, ode: dict, ode_opt: dict):
def _x_sym_modified(self):
return horzcat(*self.x_sym) if self.duplicate_starting_point else horzcat(*self.x_sym[1:])

@property
def _a_sym_modified(self):
return horzcat(*self.a_sym) if self.duplicate_starting_point else horzcat(*self.a_sym[1:])

@property
def _output_names(self):
return ["xf", "xall", "defects"]
Expand Down Expand Up @@ -664,7 +672,7 @@ def dxdt(
states[j + 1],
self.get_u(controls, self._integration_time[j]),
params,
algebraic_states,
algebraic_states[j + 1],
numerical_timeseries,
)[:, self.ode_idx]
defects.append(xp_j - f_j * self.h)
Expand All @@ -676,7 +684,7 @@ def dxdt(
states[j + 1],
self.get_u(controls, self._integration_time[j]),
params,
algebraic_states,
algebraic_states[j + 1],
numerical_timeseries,
xp_j / self.h,
)
Expand Down Expand Up @@ -741,6 +749,9 @@ def dxdt(

# Root-finding function, implicitly defines x_collocation_points as a function of x0 and p
collocation_states = vertcat(*states[1:]) if self.duplicate_starting_point else vertcat(*states[2:])
algebraic_states = (
vertcat(*algebraic_states[1:]) if self.duplicate_starting_point else vertcat(*algebraic_states[2:])
)
vfcn = Function(
"vfcn",
[collocation_states, self.t_span_sym, states[0], controls, params, algebraic_states, numerical_timeseries],
Expand Down
6 changes: 5 additions & 1 deletion bioptim/dynamics/ode_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ def p_ode(self, nlp):
return nlp.controls.scaled.cx_start

def a_ode(self, nlp):
return nlp.algebraic_states.scaled.cx_start
out = [nlp.algebraic_states.scaled.cx_start]
if not self.duplicate_starting_point:
out += [nlp.algebraic_states.scaled.cx_start]
out += nlp.algebraic_states.scaled.cx_intermediates_list
return out

def d_ode(self, nlp):
return nlp.numerical_timeseries.cx_start
Expand Down
Loading
Loading