def test_merge_phases_multi_phase(): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ) sol = ocp.solve() sol_merged = sol.merge_phases() for key in sol.states[0]: expected = np.concatenate([s[key][:, :-1] for s in sol.states], axis=1) expected = np.concatenate( (expected, sol.states[-1][key][:, -1][:, np.newaxis]), axis=1) np.testing.assert_almost_equal(sol_merged.states[key], expected) for key in sol.controls[0]: expected = np.concatenate([s[key][:, :-1] for s in sol.controls], axis=1) expected = np.concatenate( (expected, sol.controls[-1][key][:, -1][:, np.newaxis]), axis=1) np.testing.assert_almost_equal(sol_merged.controls[key], expected)
def test_interpolate_multiphases_merge_phase(): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ) sol = ocp.solve() n_frames = 100 n_shooting = [20, 30, 20] sol_interp = sol.interpolate(n_frames) shapes = (6, 3, 3) for i, key in enumerate(sol.states[0]): expected = np.array( [sol.states[0][key][:, 0], sol.states[-1][key][:, -1]]).T np.testing.assert_almost_equal(sol_interp.states[key][:, [0, -1]], expected) assert sol_interp.states[key].shape == (shapes[i], n_frames) assert sol.states[i][key].shape == (shapes[i], n_shooting[i] + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_interp.controls
def test_phase_transitions(ode_solver): from bioptim.examples.getting_started import custom_phase_transitions as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 109443.6239236211) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (516, 1)) np.testing.assert_almost_equal(g, np.zeros((516, 1))) # Check some of the results states, controls = sol.states, sol.controls # initial and final position np.testing.assert_almost_equal(states[0]["q"][:, 0], np.array((1, 0, 0))) np.testing.assert_almost_equal(states[-1]["q"][:, -1], np.array((1, 0, 0))) # initial and final velocities np.testing.assert_almost_equal(states[0]["qdot"][:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[-1]["qdot"][:, -1], np.array((0, 0, 0))) # cyclic continuity (between phase 3 and phase 0) np.testing.assert_almost_equal(states[-1]["q"][:, -1], states[0]["q"][:, 0]) # Continuity between phase 0 and phase 1 np.testing.assert_almost_equal(states[0]["q"][:, -1], states[1]["q"][:, 0]) # initial and final controls np.testing.assert_almost_equal(controls[0]["tau"][:, 0], np.array((0.73170732, 12.71705188, -0.0928732))) np.testing.assert_almost_equal(controls[-1]["tau"][:, -2], np.array((0.11614402, 8.70686126, 1.05599166))) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate with pytest.raises( RuntimeError, match=re.escape( "Phase transition must have the same number of states (3) " "when integrating with Shooting.SINGLE_CONTINUOUS. If it is not possible, " "please integrate with Shooting.SINGLE" ), ): TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 14769.760808687663) np.testing.assert_almost_equal(sol.detailed_cost[1]["cost_value_weighted"], 38218.35341602849) np.testing.assert_almost_equal(sol.detailed_cost[2]["cost_value_weighted"], 34514.48724963841) np.testing.assert_almost_equal(sol.detailed_cost[3]["cost_value_weighted"], 21941.02244926652)
def test_custom_constraint_track_markers(ode_solver): from bioptim.examples.getting_started import custom_constraint as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver) sol = ocp.solve() # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (186, 1)) np.testing.assert_almost_equal(g, np.zeros((186, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((1, 0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((2, 0, 1.57))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0))) if isinstance(ode_solver, OdeSolver.IRK): # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 19767.53312569523) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((1.4516129, 9.81, 2.27903226))) np.testing.assert_almost_equal( tau[:, -2], np.array((-1.45161291, 9.81, -2.27903226))) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal( sol.detailed_cost[0]["cost_value_weighted"], 19767.533125695227) else: # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 19767.533125695223) np.testing.assert_almost_equal( tau[:, 0], np.array( (1.4516128810214546, 9.81, 2.2790322540381487))) np.testing.assert_almost_equal( tau[:, -2], np.array((-1.4516128810214546, 9.81, -2.2790322540381487))) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal( sol.detailed_cost[0]["cost_value_weighted"], 19767.533125695227)
def test_integrate(integrator, ode_solver): # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) n_shooting = 80 ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=0.9, n_shooting=n_shooting, ode_solver=ode_solver(), ) sol = ocp.solve() opts = { "shooting_type": Shooting.MULTIPLE, "keep_intermediate_points": False, "integrator": integrator } with pytest.raises( ValueError, match="Shooting.MULTIPLE and keep_intermediate_points=False " "cannot be used simultaneously since it would do nothing", ): _ = sol.integrate(**opts) opts["keep_intermediate_points"] = True if ode_solver == OdeSolver.COLLOCATION and integrator == SolutionIntegrator.DEFAULT: with pytest.raises( RuntimeError, match= "Integration with direct collocation must be not continuous"): sol.integrate(**opts) return sol_integrated = sol.integrate(**opts) shapes = (4, 2, 2) decimal = 5 if integrator != SolutionIntegrator.DEFAULT else 8 for i, key in enumerate(sol.states): np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -1]], sol.states[key][:, [0, -1]], decimal=decimal) assert sol_integrated.states[key].shape == (shapes[i], n_shooting * 5 + 1) if ode_solver == OdeSolver.COLLOCATION: assert sol.states[key].shape == (shapes[i], n_shooting * 5 + 1) else: assert sol.states[key].shape == (shapes[i], n_shooting + 1) with pytest.raises( RuntimeError, match="There is no controls in the solution. " "This may happen in previously integrated and interpolated structure", ): _ = sol_integrated.controls
def test_integrate_single_shoot(keep_intermediate_points, ode_solver): # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) n_shooting = 10 ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=0.9, n_shooting=n_shooting, ode_solver=ode_solver(), ) sol = ocp.solve() opts = { "keep_intermediate_points": keep_intermediate_points, "integrator": SolutionIntegrator.DEFAULT } if ode_solver == OdeSolver.COLLOCATION: with pytest.raises( RuntimeError, match= "Integration with direct collocation must be not continuous"): sol.integrate(**opts) return sol_integrated = sol.integrate(**opts) shapes = (4, 2, 2) assert np.shape(sol_integrated.states["all"])[1] == np.shape( sol_integrated.time_vector)[0] decimal = 1 for i, key in enumerate(sol.states): np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -1]], sol.states[key][:, [0, -1]], decimal=decimal) if keep_intermediate_points or ode_solver == OdeSolver.COLLOCATION: assert sol_integrated.states[key].shape == (shapes[i], n_shooting * 5 + 1) else: np.testing.assert_almost_equal(sol_integrated.states[key], sol.states[key], decimal=decimal) assert sol_integrated.states[key].shape == (shapes[i], n_shooting + 1) assert sol.states[key].shape == (shapes[i], n_shooting + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls
def test_contact_forces_inequality_lesser_than_constraint(ode_solver): from bioptim.examples.getting_started import example_inequality_constraint as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) max_bound = 75 ode_solver = ode_solver() ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/2segments_4dof_2contacts.bioMod", phase_time=0.1, n_shooting=10, min_bound=-np.inf, max_bound=max_bound, mu=0.2, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 0.2005516965424669) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (120, 1)) np.testing.assert_almost_equal(g[:80], np.zeros((80, 1))) np.testing.assert_array_less(g[80:100], max_bound) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] np.testing.assert_almost_equal(q[:, 0], np.array((0.0, 0.0, -0.75, 0.75))) np.testing.assert_almost_equal( q[:, -1], np.array((-0.00902682, 0.00820596, -0.72560094, 0.72560094))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0, 0))) np.testing.assert_almost_equal( qdot[:, -1], np.array((-0.18616011, 0.16512913, 0.49768751, -0.49768751))) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((-24.36593641))) np.testing.assert_almost_equal(tau[:, -2], np.array((-24.36125297))) # save and load TestUtils.save_and_load(sol, ocp, False) # simulate TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 0.2005516965424669)
def test_contact_forces_inequality_greater_than_constraint(ode_solver): from bioptim.examples.getting_started import example_inequality_constraint as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) min_bound = 50 ode_solver = ode_solver() ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/2segments_4dof_2contacts.bioMod", phase_time=0.1, n_shooting=10, min_bound=min_bound, max_bound=np.inf, mu=0.2, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 0.19216241950659246) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (120, 1)) np.testing.assert_almost_equal(g[:80], np.zeros((80, 1))) np.testing.assert_array_less(-g[80:100], -min_bound) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0.0, 0.0, -0.75, 0.75))) np.testing.assert_almost_equal( q[:, -1], np.array((-0.027221, 0.02358599, -0.67794882, 0.67794882))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0, 0))) np.testing.assert_almost_equal( qdot[:, -1], np.array((-0.53979971, 0.43468705, 1.38612634, -1.38612634))) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((-33.50557304))) np.testing.assert_almost_equal(tau[:, -2], np.array((-29.43209257))) # save and load TestUtils.save_and_load(sol, ocp, False) # simulate TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 0.19216241950659244)
def test_initial_guesses(interpolation, ode_solver): from bioptim.examples.getting_started import custom_initial_guess as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() np.random.seed(42) ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/cube.bioMod", final_time=1, n_shooting=5, initial_guess=interpolation, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 13954.735) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (36, 1)) np.testing.assert_almost_equal(g, np.zeros((36, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array([1, 0, 0])) np.testing.assert_almost_equal(q[:, -1], np.array([2, 0, 1.57])) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0))) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array([5.0, 9.81, 7.85])) np.testing.assert_almost_equal(tau[:, -2], np.array([-5.0, 9.81, -7.85])) # save and load if interpolation == InterpolationType.CUSTOM: with pytest.raises( AttributeError, match= "'PathCondition' object has no attribute 'custom_function'"): TestUtils.save_and_load(sol, ocp, True) else: TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 13954.735000000004)
def test_cyclic_objective(ode_solver): from bioptim.examples.getting_started import example_cyclic_movement as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() np.random.seed(42) ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/cube.bioMod", final_time=1, n_shooting=10, loop_from_constraint=False, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 56851.88181545) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (67, 1)) np.testing.assert_almost_equal(g, np.zeros((67, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal( q[:, 0], np.array([1.60205103, -0.01069317, 0.62477988])) np.testing.assert_almost_equal(q[:, -1], np.array([1, 0, 1.57])) # initial and final velocities np.testing.assert_almost_equal( qdot[:, 0], np.array((0.12902365, 0.09340155, -0.20256713))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0))) # initial and final controls np.testing.assert_almost_equal( tau[:, 0], np.array([9.89210954, 9.39362112, -15.53061197])) np.testing.assert_almost_equal( tau[:, -2], np.array([17.16370432, 9.78643138, -26.94701577])) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 13224.252515047212)
def test_cyclic_constraint(ode_solver): from bioptim.examples.getting_started import example_cyclic_movement as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() np.random.seed(42) ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/cube.bioMod", final_time=1, n_shooting=10, loop_from_constraint=True, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 78921.61000000016) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (73, 1)) np.testing.assert_almost_equal(g, np.zeros((73, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array([1, 0, 1.57])) np.testing.assert_almost_equal(q[:, -1], np.array([1, 0, 1.57])) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0))) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array([20.0, 9.81, -31.4])) np.testing.assert_almost_equal(tau[:, -2], np.array([20.0, 9.81, -31.4])) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 78921.61000000013)
def test_multinode_constraints(ode_solver): from bioptim.examples.getting_started import example_multinode_constraints as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 106090.89337001556) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (3036, 1)) np.testing.assert_almost_equal(g, np.zeros((3036, 1))) # Check some of the results states, controls = sol.states, sol.controls # initial and final position np.testing.assert_almost_equal(states[0]["q"][:, 0], np.array([1.0, 0.0, 0.0])) np.testing.assert_almost_equal(states[-1]["q"][:, -1], np.array([2.0, 0.0, 1.57])) # initial and final velocities np.testing.assert_almost_equal(states[0]["qdot"][:, 0], np.array([0.0, 0.0, 0.0])) np.testing.assert_almost_equal(states[-1]["qdot"][:, -1], np.array([0.0, 0.0, 0.0])) # equality Node.START phase 0 and 2 np.testing.assert_almost_equal(states[0]["q"][:, 0], states[2]["q"][:, 0]) # initial and final controls np.testing.assert_almost_equal(controls[0]["tau"][:, 0], np.array([1.4968523, 9.81, 0.0236434])) np.testing.assert_almost_equal(controls[-1]["tau"][:, -2], np.array([-0.3839688, 9.81, -0.6037517])) # save and load TestUtils.save_and_load(sol, ocp, True)
def test_merge_phases_one_phase(): # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=2, n_shooting=10, ) sol = ocp.solve() sol_merged = sol.merge_phases() for key in sol.states: np.testing.assert_almost_equal(sol_merged.states[key], sol.states[key]) for key in sol.controls: np.testing.assert_almost_equal(sol_merged.controls[key], sol.controls[key])
def test_interpolate_multiphases(ode_solver): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver()) sol = ocp.solve() n_frames = 100 n_shooting = [20, 30, 20] sol_interp = sol.interpolate([n_frames, n_frames, n_frames]) shapes = (6, 3, 3) decimal = 2 if ode_solver == OdeSolver.COLLOCATION else 8 for i, key in enumerate(sol.states[0]): np.testing.assert_almost_equal(sol_interp.states[i][key][:, [0, -1]], sol.states[i][key][:, [0, -1]], decimal=decimal) assert sol_interp.states[i][key].shape == (shapes[i], n_frames) if ode_solver == OdeSolver.COLLOCATION: assert sol.states[i][key].shape == (shapes[i], n_shooting[i] * 5 + 1) else: assert sol.states[i][key].shape == (shapes[i], n_shooting[i] + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_interp.controls with pytest.raises( ValueError, match="n_frames should either be a int to merge_phases phases or a " "list of int of the number of phases dimension", ): sol.interpolate([n_frames, n_frames])
def test_interpolate(): # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) n_shooting = 10 ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=2, n_shooting=n_shooting, ) sol = ocp.solve() n_frames = 100 sol_interp = sol.interpolate(n_frames) sol_interp_list = sol.interpolate([n_frames]) shapes = (4, 2, 2) for i, key in enumerate(sol.states): np.testing.assert_almost_equal(sol_interp.states[key][:, [0, -1]], sol.states[key][:, [0, -1]]) np.testing.assert_almost_equal(sol_interp_list.states[key][:, [0, -1]], sol.states[key][:, [0, -1]]) assert sol_interp.states[key].shape == (shapes[i], n_frames) assert sol_interp_list.states[key].shape == (shapes[i], n_frames) assert sol.states[key].shape == (shapes[i], n_shooting + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_interp.controls with pytest.raises( ValueError, match="n_frames should either be a int to merge_phases phases or a " "list of int of the number of phases dimension", ): sol.interpolate([n_frames, n_frames])
def test_parameter_optimization(ode_solver): from bioptim.examples.getting_started import custom_parameters as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=1, n_shooting=80, optim_gravity=True, optim_mass=False, min_g=np.array([-1, -1, -10]), max_g=np.array([1, 1, -5]), min_m=10, max_m=30, target_g=np.array([0, 0, -9.81]), target_m=20, ) sol = ocp.solve() # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (320, 1)) np.testing.assert_almost_equal(g, np.zeros((320, 1)), decimal=6) # Check some of the results q, qdot, tau, gravity = sol.states["q"], sol.states["qdot"], sol.controls["tau"], sol.parameters["gravity_xyz"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((0, 3.14))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0))) if isinstance(ode_solver, OdeSolver.IRK): # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 359.892132373683, decimal=6) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((7.73915783, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-10.24782316, 0))) # gravity parameter np.testing.assert_almost_equal(gravity, np.array([[0, 0.05059018, -9.8065527]]).T) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 357.32088196158827) elif isinstance(ode_solver, OdeSolver.RK8): # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 359.892132373683, decimal=6) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((7.73915783, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-10.24782316, 0))) # gravity parameter np.testing.assert_almost_equal(gravity, np.array([[0.0, 0.05059018, -9.8065527]]).T) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 357.32088196158827) else: # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 359.892132373683, decimal=6) # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((7.73915783, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-10.24782316, 0))) # gravity parameter np.testing.assert_almost_equal(gravity, np.array([[0, 0.05059018, -9.8065527]]).T) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 357.32088196158827) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol) # Test warm starting TestUtils.assert_warm_start(ocp, sol, param_decimal=0)
def test_pendulum(ode_solver, use_sx, n_threads): from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() if isinstance(ode_solver, (OdeSolver.IRK, OdeSolver.CVODES)) and use_sx: with pytest.raises( RuntimeError, match=f"use_sx=True and OdeSolver.{ode_solver.rk_integrator.__name__} are not yet compatible" ): ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=2, n_shooting=10, n_threads=n_threads, use_sx=use_sx, ode_solver=ode_solver, ) return ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=1, n_shooting=30, n_threads=n_threads, use_sx=use_sx, ode_solver=ode_solver, ) ocp.print(to_console=True, to_graph=False) # the test is too long with CVODES if isinstance(ode_solver, OdeSolver.CVODES): return sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) if isinstance(ode_solver, OdeSolver.RK8): np.testing.assert_almost_equal(f[0, 0], 41.57063948309302) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 41.57063948309302) elif isinstance(ode_solver, OdeSolver.IRK): np.testing.assert_almost_equal(f[0, 0], 65.8236055171619) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 65.8236055171619) elif isinstance(ode_solver, OdeSolver.COLLOCATION): np.testing.assert_almost_equal(f[0, 0], 46.667345680854794) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 46.667345680854794) elif isinstance(ode_solver, OdeSolver.RK1): np.testing.assert_almost_equal(f[0, 0], 47.360621044913245) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 47.360621044913245) elif isinstance(ode_solver, OdeSolver.RK2): np.testing.assert_almost_equal(f[0, 0], 76.24887695462857) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 76.24887695462857) else: np.testing.assert_almost_equal(f[0, 0], 41.58259426) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 41.58259426) # Check constraints g = np.array(sol.constraints) if ode_solver.is_direct_collocation: np.testing.assert_equal(g.shape, (600, 1)) np.testing.assert_almost_equal(g, np.zeros((600, 1))) else: np.testing.assert_equal(g.shape, (120, 1)) np.testing.assert_almost_equal(g, np.zeros((120, 1))) # Check some of the results states, controls = sol.states, sol.controls q, qdot, tau = states["q"], states["qdot"], controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((0, 3.14))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0))) # initial and final controls if isinstance(ode_solver, OdeSolver.RK8): np.testing.assert_almost_equal(tau[:, 0], np.array((6.03763589, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-13.59527556, 0))) elif isinstance(ode_solver, OdeSolver.IRK): np.testing.assert_almost_equal(tau[:, 0], np.array((5.40765381, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-25.26494109, 0))) elif isinstance(ode_solver, OdeSolver.COLLOCATION): np.testing.assert_almost_equal(tau[:, 0], np.array((5.78386563, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-18.22245512, 0))) elif isinstance(ode_solver, OdeSolver.RK1): np.testing.assert_almost_equal(tau[:, 0], np.array((5.498956, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-17.6888209, 0))) elif isinstance(ode_solver, OdeSolver.RK2): np.testing.assert_almost_equal(tau[:, 0], np.array((5.6934385, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-27.6610711, 0))) else: np.testing.assert_almost_equal(tau[:, 0], np.array((6.01549798, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-13.68877181, 0))) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol)
def test_pendulum_save_and_load(n_threads, use_sx, ode_solver): from bioptim.examples.getting_started import example_save_and_load as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() if isinstance(ode_solver, OdeSolver.IRK): if use_sx: with pytest.raises(RuntimeError, match="use_sx=True and OdeSolver.IRK are not yet compatible"): ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=1, n_shooting=30, n_threads=n_threads, use_sx=use_sx, ode_solver=ode_solver, ) else: ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=1, n_shooting=30, n_threads=n_threads, use_sx=use_sx, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (120, 1)) np.testing.assert_almost_equal(g, np.zeros((120, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((0, 3.14))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0))) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol) else: ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=1, n_shooting=30, n_threads=n_threads, use_sx=use_sx, ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value is_collocation = isinstance(ode_solver, OdeSolver.COLLOCATION) and not isinstance(ode_solver, OdeSolver.IRK) f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) if isinstance(ode_solver, OdeSolver.RK8): np.testing.assert_almost_equal(f[0, 0], 9.821989132327003) elif is_collocation: pass else: np.testing.assert_almost_equal(f[0, 0], 9.834017207589055) # Check constraints g = np.array(sol.constraints) if is_collocation: np.testing.assert_equal(g.shape, (600, 1)) np.testing.assert_almost_equal(g, np.zeros((600, 1))) else: np.testing.assert_equal(g.shape, (120, 1)) np.testing.assert_almost_equal(g, np.zeros((120, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((0, 3.14))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0))) # initial and final controls if isinstance(ode_solver, OdeSolver.RK8): np.testing.assert_almost_equal(tau[:, 0], np.array((5.67291529, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-11.71262836, 0))) elif is_collocation: pass else: np.testing.assert_almost_equal(tau[:, 0], np.array((5.72227268, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((-11.62799294, 0))) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol)
def test_integrate_single_shoot_use_scipy(keep_intermediate_points, ode_solver): if ode_solver == OdeSolver.COLLOCATION and platform == "darwin": # For some reason, the test fails on Mac warnings.warn( "Test test_integrate_single_shoot_use_scipy skiped on Mac") return # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) n_shooting = 10 ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=0.9, n_shooting=n_shooting, ode_solver=ode_solver(), ) sol = ocp.solve() opts = { "keep_intermediate_points": keep_intermediate_points, "integrator": SolutionIntegrator.SCIPY_RK45 } sol_integrated = sol.integrate(**opts) shapes = (4, 2, 2) assert np.shape(sol_integrated.states["all"])[1] == np.shape( sol_integrated.time_vector)[0] decimal = 1 if ode_solver == OdeSolver.RK4: np.testing.assert_almost_equal( sol_integrated.states["q"][:, [0, -1]], np.array([[0.0, -0.40229917], [0.0, 2.66577734]]), decimal=decimal, ) np.testing.assert_almost_equal( sol_integrated.states["qdot"][:, [0, -1]], np.array([[0.0, 4.09704146], [0.0, 4.54449186]]), decimal=decimal, ) else: np.testing.assert_almost_equal( sol_integrated.states["q"][:, [0, -1]], np.array([[0.0, -0.93010486], [0.0, 1.25096783]]), decimal=decimal, ) np.testing.assert_almost_equal( sol_integrated.states["qdot"][:, [0, -1]], np.array([[0.0, -0.78079849], [0.0, 1.89447328]]), decimal=decimal, ) if keep_intermediate_points: assert sol_integrated.states["all"].shape == (shapes[0], n_shooting * 5 + 1) assert sol_integrated.states["q"].shape == (shapes[1], n_shooting * 5 + 1) assert sol_integrated.states["qdot"].shape == (shapes[2], n_shooting * 5 + 1) else: if ode_solver == OdeSolver.RK4: np.testing.assert_almost_equal( sol_integrated.states["all"], np.array([ [ 0.0, 0.3, 0.6, 0.8, 0.9, 0.8, -0.4, -0.8, -1.0, -0.9, -0.4 ], [ 0.0, -0.3, -0.6, -0.7, -0.8, -0.6, 0.6, 1.2, 1.6, 2.1, 2.7 ], [ 0.0, 4.6, 2.0, 1.7, 0.7, -4.2, -9.3, -1.1, -3.7, 6.0, 4.1 ], [ 0.0, -4.5, -1.8, -1.1, 0.3, 4.8, 10.2, 4.9, 4.1, 6.8, 4.5 ], ]), decimal=decimal, ) np.testing.assert_almost_equal( sol_integrated.states["q"], np.array([ [ 0.0, 0.33771737, 0.60745128, 0.77322807, 0.87923355, 0.75783664, -0.39855413, -0.78071335, -0.9923451, -0.92719046, -0.40229917, ], [ 0.0, -0.33826953, -0.59909116, -0.72747641, -0.76068201, -0.56369461, 0.62924769, 1.23356971, 1.64774156, 2.09574642, 2.66577734, ], ]), decimal=decimal, ) np.testing.assert_almost_equal( sol_integrated.states["qdot"], np.array([ [ 0.0, 4.56061105, 2.00396203, 1.71628908, 0.67171827, -4.17420278, -9.3109149, -1.09241789, -3.74378463, 6.01186572, 4.09704146, ], [ 0.0, -4.52749096, -1.8038578, -1.06710062, 0.30405407, 4.80782728, 10.24044964, 4.893414, 4.12673905, 6.83563286, 4.54449186, ], ]), decimal=decimal, ) assert ( sol_integrated.states["all"].shape == (shapes[0], n_shooting + 1) and sol_integrated.states["q"].shape == (shapes[1], n_shooting + 1) and sol_integrated.states["qdot"].shape == (shapes[2], n_shooting + 1)) if ode_solver == OdeSolver.COLLOCATION: b = bool(1) for i, key in enumerate(sol.states): b = b * sol.states[key].shape == (shapes[i], n_shooting * 5 + 1) assert b with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls
def test_integrate_multiphase_merged(shooting, keep_intermediate_points, integrator, ode_solver): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver(), ) sol = ocp.solve() opts = { "shooting_type": shooting, "continuous": False, "keep_intermediate_points": keep_intermediate_points, "integrator": integrator, } if shooting == Shooting.SINGLE_CONTINUOUS: with pytest.raises( ValueError, match= "Shooting.SINGLE_CONTINUOUS and continuous=False cannot be used simultaneously it is a contradiction", ): _ = sol.integrate(**opts) return if ode_solver == OdeSolver.COLLOCATION and integrator == SolutionIntegrator.DEFAULT: if shooting != Shooting.MULTIPLE: with pytest.raises( RuntimeError, match= "Integration with direct collocation must using shooting_type=Shooting.MULTIPLE" ): _ = sol.integrate(**opts) return if shooting == Shooting.MULTIPLE: if not keep_intermediate_points: with pytest.raises( ValueError, match= "Shooting.MULTIPLE and keep_intermediate_points=False cannot be used " "simultaneously since it would do nothing", ): _ = sol.integrate(**opts) return opts["merge_phases"] = True opts["continuous"] = True if ode_solver == OdeSolver.COLLOCATION and integrator == SolutionIntegrator.DEFAULT: with pytest.raises( RuntimeError, match= "Integration with direct collocation must be not continuous", ): sol.integrate(**opts) return n_shooting = [20, 30, 20] sol_integrated = sol.integrate(**opts) shapes = (6, 3, 3) decimal = 0 if integrator != SolutionIntegrator.DEFAULT else 8 for k, key in enumerate(sol.states[0]): expected = np.array( [sol.states[0][key][:, 0], sol.states[-1][key][:, -1]]).T if integrator == SolutionIntegrator.DEFAULT or shooting == Shooting.MULTIPLE: np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -1]], expected, decimal=decimal) if keep_intermediate_points: assert sol_integrated.states[key].shape == (shapes[k], sum(n_shooting) * 5 + 1) else: # The interpolation prevents from comparing all points if integrator == SolutionIntegrator.DEFAULT or shooting == Shooting.MULTIPLE: expected = np.concatenate( (sol.states[0][key][:, 0:1], sol.states[-1][key][:, -1][:, np.newaxis]), axis=1) np.testing.assert_almost_equal( sol_integrated.states[key][:, [0, -1]], expected) assert sol_integrated.states[key].shape == (shapes[k], sum(n_shooting) + 1) for i in range(len(sol_integrated.states)): for k, key in enumerate(sol.states[i]): if ode_solver == OdeSolver.COLLOCATION: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] * 5 + 1) else: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls
def test_integrate_multiphase_merged_non_continuous(shooting, integrator, ode_solver): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver()) sol = ocp.solve() opts = { "shooting_type": shooting, "continuous": False, "keep_intermediate_points": False, "integrator": integrator, } if shooting == Shooting.SINGLE_CONTINUOUS: with pytest.raises( ValueError, match= "Shooting.SINGLE_CONTINUOUS and continuous=False cannot be used simultaneously it is a contradiction", ): _ = sol.integrate(**opts) return elif shooting == Shooting.MULTIPLE: with pytest.raises( ValueError, match= "Shooting.MULTIPLE and keep_intermediate_points=False cannot be used simultaneously since it would do nothing", ): _ = sol.integrate(**opts) elif ode_solver == OdeSolver.COLLOCATION: if integrator == SolutionIntegrator.DEFAULT: with pytest.raises( RuntimeError, match= "Integration with direct collocation must using shooting_type=Shooting.MULTIPLE " "if a scipy integrator is not used", ): _ = sol.integrate(**opts) return opts["merge_phases"] = True opts["keep_intermediate_points"] = True n_shooting = [20, 30, 20] sol_integrated = sol.integrate(**opts) shapes = (6, 3, 3) assert np.shape(sol_integrated.states["all"])[1] == np.shape( sol_integrated.time_vector)[0] decimal = 0 if integrator != SolutionIntegrator.DEFAULT or ode_solver == OdeSolver.COLLOCATION else 8 steps = 4 if integrator == SolutionIntegrator.DEFAULT and ode_solver == OdeSolver.COLLOCATION else 5 for k, key in enumerate(sol.states[0]): expected = np.array( [sol.states[0][key][:, 0], sol.states[-1][key][:, -1]]).T if integrator == SolutionIntegrator.DEFAULT or shooting == Shooting.MULTIPLE: np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -1]], expected, decimal=decimal) np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -2]], expected, decimal=decimal) assert sol_integrated.states[key].shape == (shapes[k], sum(n_shooting) * (steps + 1) + 1 * len(n_shooting)) for i in range(len(sol_integrated.states)): for k, key in enumerate(sol.states[i]): if ode_solver == OdeSolver.COLLOCATION: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] * 5 + 1) else: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls
def test_integrate_multiphase_non_continuous(shooting, integrator, ode_solver): # Load pendulum from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver()) sol = ocp.solve() n_shooting = [20, 30, 20] opts = { "shooting_type": shooting, "continuous": False, "keep_intermediate_points": True, "integrator": integrator, } if shooting == Shooting.SINGLE_CONTINUOUS: with pytest.raises( ValueError, match= "Shooting.SINGLE_CONTINUOUS and continuous=False cannot be used " "simultaneously it is a contradiction", ): _ = sol.integrate(**opts) return if ode_solver == OdeSolver.COLLOCATION and integrator == SolutionIntegrator.DEFAULT: if shooting != Shooting.MULTIPLE: with pytest.raises( RuntimeError, match= "Integration with direct collocation must using shooting_type=Shooting.MULTIPLE" ): _ = sol.integrate(**opts) return sol_integrated = sol.integrate(**opts) shapes = (6, 3, 3) states_shape_sum = 0 for i in range(len(sol_integrated.states)): states_shape_sum += np.shape(sol_integrated.states[i]["all"])[1] assert states_shape_sum == np.shape(sol_integrated.time_vector)[0] decimal = 1 if integrator != SolutionIntegrator.DEFAULT or ode_solver == OdeSolver.COLLOCATION else 8 for i in range(len(sol_integrated.states)): for k, key in enumerate(sol.states[i]): if integrator == SolutionIntegrator.DEFAULT or shooting == Shooting.MULTIPLE: np.testing.assert_almost_equal( sol_integrated.states[i][key][:, [0, -1]], sol.states[i][key][:, [0, -1]], decimal=decimal) np.testing.assert_almost_equal( sol_integrated.states[i][key][:, [0, -2]], sol.states[i][key][:, [0, -1]], decimal=decimal) if ode_solver == OdeSolver.COLLOCATION and integrator == SolutionIntegrator.DEFAULT: assert sol_integrated.states[i][key].shape == (shapes[k], n_shooting[i] * (4 + 1) + 1) else: assert sol_integrated.states[i][key].shape == (shapes[k], n_shooting[i] * (5 + 1) + 1) if ode_solver == OdeSolver.COLLOCATION: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] * 5 + 1) else: assert sol.states[i][key].shape == (shapes[k], n_shooting[i] + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls
def test_example_external_forces(ode_solver): from bioptim.examples.getting_started import example_external_forces as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ode_solver = ode_solver() ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/cube_with_forces.bioMod", ode_solver=ode_solver, ) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 9875.88768746912) # Check constraints g = np.array(sol.constraints) np.testing.assert_equal(g.shape, (246, 1)) np.testing.assert_almost_equal(g, np.zeros((246, 1))) # Check some of the results q, qdot, tau = sol.states["q"], sol.states["qdot"], sol.controls["tau"] # initial and final controls np.testing.assert_almost_equal(tau[:, 0], np.array((0, 9.71322593, 0, 0))) np.testing.assert_almost_equal(tau[:, 10], np.array((0, 7.71100122, 0, 0))) np.testing.assert_almost_equal(tau[:, 20], np.array((0, 5.70877651, 0, 0))) np.testing.assert_almost_equal(tau[:, -2], np.array((0, 3.90677425, 0, 0))) if isinstance(ode_solver, OdeSolver.IRK): # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0, 0, 0)), decimal=5) np.testing.assert_almost_equal(q[:, -1], np.array((0, 2, 0, 0)), decimal=5) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0, 0)), decimal=5) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0, 0)), decimal=5) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 9875.887687469118) else: # initial and final position np.testing.assert_almost_equal(q[:, 0], np.array((0, 0, 0, 0))) np.testing.assert_almost_equal(q[:, -1], np.array((0, 2, 0, 0))) # initial and final velocities np.testing.assert_almost_equal(qdot[:, 0], np.array((0, 0, 0, 0))) np.testing.assert_almost_equal(qdot[:, -1], np.array((0, 0, 0, 0))) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 9875.887687469118) # save and load TestUtils.save_and_load(sol, ocp, True) # simulate TestUtils.simulate(sol)
def test_example_multiphase(ode_solver): from bioptim.examples.getting_started import example_multiphase as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) ocp = ocp_module.prepare_ocp(biorbd_model_path=bioptim_folder + "/models/cube.bioMod", ode_solver=ode_solver()) sol = ocp.solve() # Check objective function value f = np.array(sol.cost) np.testing.assert_equal(f.shape, (1, 1)) np.testing.assert_almost_equal(f[0, 0], 106088.01707867868) # Check constraints g = np.array(sol.constraints) if ode_solver().is_direct_collocation: np.testing.assert_equal(g.shape, (2124, 1)) np.testing.assert_almost_equal(g, np.zeros((2124, 1))) else: np.testing.assert_equal(g.shape, (444, 1)) np.testing.assert_almost_equal(g, np.zeros((444, 1))) # Check some of the results states, controls = sol.states, sol.controls # initial and final position np.testing.assert_almost_equal(states[0]["q"][:, 0], np.array((1, 0, 0))) np.testing.assert_almost_equal(states[0]["q"][:, -1], np.array((2, 0, 0.0078695))) np.testing.assert_almost_equal(states[1]["q"][:, 0], np.array((2, 0, 0.0078695))) np.testing.assert_almost_equal(states[1]["q"][:, -1], np.array((1, 0, 0))) np.testing.assert_almost_equal(states[2]["q"][:, 0], np.array((1, 0, 0))) np.testing.assert_almost_equal(states[2]["q"][:, -1], np.array((2, 0, 1.57))) # initial and final velocities np.testing.assert_almost_equal(states[0]["qdot"][:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[0]["qdot"][:, -1], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[1]["qdot"][:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[1]["qdot"][:, -1], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[2]["qdot"][:, 0], np.array((0, 0, 0))) np.testing.assert_almost_equal(states[2]["qdot"][:, -1], np.array((0, 0, 0))) # initial and final controls np.testing.assert_almost_equal(controls[0]["tau"][:, 0], np.array((1.42857142, 9.81, 0.01124212))) np.testing.assert_almost_equal(controls[0]["tau"][:, -2], np.array((-1.42857144, 9.81, -0.01124212))) np.testing.assert_almost_equal(controls[1]["tau"][:, 0], np.array((-0.22788183, 9.81, 0.01775688))) np.testing.assert_almost_equal(controls[1]["tau"][:, -2], np.array((0.2957136, 9.81, 0.285805))) np.testing.assert_almost_equal(controls[2]["tau"][:, 0], np.array((0.3078264, 9.81, 0.34001243))) np.testing.assert_almost_equal(controls[2]["tau"][:, -2], np.array((-0.36233407, 9.81, -0.58394606))) # save and load TestUtils.save_and_load(sol, ocp, False) # simulate TestUtils.simulate(sol) # Test warm start if ode_solver == OdeSolver.COLLOCATION: TestUtils.assert_warm_start(ocp, sol, state_decimal=0) else: TestUtils.assert_warm_start(ocp, sol) # detailed cost values sol.detailed_cost_values() np.testing.assert_almost_equal(sol.detailed_cost[0]["cost_value_weighted"], 19397.605252449728) np.testing.assert_almost_equal(sol.detailed_cost[1]["cost_value_weighted"], 48129.27750487157) np.testing.assert_almost_equal(sol.detailed_cost[2]["cost_value_weighted"], 0.0) np.testing.assert_almost_equal(sol.detailed_cost[3]["cost_value_weighted"], 38560.82580432337)
def test_integrate_non_continuous(shooting, merge, integrator, ode_solver): # Load pendulum from bioptim.examples.getting_started import pendulum as ocp_module bioptim_folder = os.path.dirname(ocp_module.__file__) n_shooting = 10 ocp = ocp_module.prepare_ocp( biorbd_model_path=bioptim_folder + "/models/pendulum.bioMod", final_time=0.9, n_shooting=n_shooting, ode_solver=ode_solver(), ) sol = ocp.solve() opts = { "shooting_type": shooting, "continuous": False, "keep_intermediate_points": False, "integrator": integrator, } if shooting == Shooting.SINGLE_CONTINUOUS: with pytest.raises( ValueError, match= "Shooting.SINGLE_CONTINUOUS and continuous=False cannot be used simultaneously it is a contradiction", ): _ = sol.integrate(**opts) return elif shooting == Shooting.MULTIPLE: with pytest.raises( ValueError, match= "Shooting.MULTIPLE and keep_intermediate_points=False cannot be used " "simultaneously since it would do nothing", ): _ = sol.integrate(**opts) opts["keep_intermediate_points"] = True opts["merge_phases"] = merge if (ode_solver == OdeSolver.COLLOCATION and shooting != Shooting.MULTIPLE and integrator == SolutionIntegrator.DEFAULT): with pytest.raises( RuntimeError, match= "Integration with direct collocation must using shooting_type=Shooting.MULTIPLE", ): sol.integrate(**opts) return sol_integrated = sol.integrate(**opts) shapes = (4, 2, 2) assert np.shape(sol_integrated.states["all"])[1] == np.shape( sol_integrated.time_vector)[0] decimal = 1 if integrator != SolutionIntegrator.DEFAULT or ode_solver == OdeSolver.COLLOCATION else 8 for i, key in enumerate(sol.states): np.testing.assert_almost_equal(sol_integrated.states[key][:, [0, -1]], sol.states[key][:, [0, -1]], decimal=decimal) if ode_solver == OdeSolver.COLLOCATION: if integrator != SolutionIntegrator.DEFAULT: assert sol_integrated.states[key].shape == (shapes[i], n_shooting * (5 + 1) + 1) else: assert sol_integrated.states[key].shape == (shapes[i], n_shooting * (4 + 1) + 1) assert sol.states[key].shape == (shapes[i], n_shooting * 5 + 1) else: assert sol_integrated.states[key].shape == (shapes[i], n_shooting * (5 + 1) + 1) assert sol.states[key].shape == (shapes[i], n_shooting + 1) with pytest.raises( RuntimeError, match= "There is no controls in the solution. This may happen in previously " "integrated and interpolated structure", ): _ = sol_integrated.controls