@@ -12,6 +12,12 @@ def __init__(self, solution):
1212 self .cost = 1.23
1313 self .exit_status = "Converged"
1414 self .solve_time_ms = 0.7
15+ self .penalty = 12.5
16+ self .num_outer_iterations = 3
17+ self .num_inner_iterations = 27
18+ self .last_problem_norm_fpr = 1e-6
19+ self .f1_infeasibility = 2e-5
20+ self .f2_norm = 3e-5
1521 self .lagrange_multipliers = []
1622
1723
@@ -71,7 +77,6 @@ def setUpOCP1(cls):
7177 .with_max_inner_iterations (500 )
7278 .with_max_outer_iterations (10 ),
7379 ).build ()
74- cls .ocp1_optimizer .save ()
7580 cls .ocp1_manifest_path = os .path .join (cls .ocp1_optimizer .target_dir , "optimizer_manifest.json" )
7681 cls .ocp1_rollout_path = os .path .join (cls .ocp1_optimizer .target_dir , "rollout.casadi" )
7782
@@ -132,8 +137,6 @@ def make_problem(shooting):
132137 solver_configuration = solver_config ,
133138 ).build ()
134139
135- cls .ocp2_single_optimizer .save ()
136- cls .ocp2_multiple_optimizer .save ()
137140 cls .ocp2_single_manifest_path = os .path .join (
138141 cls .ocp2_single_optimizer .target_dir , "optimizer_manifest.json" )
139142 cls .ocp2_multiple_manifest_path = os .path .join (
@@ -325,10 +328,46 @@ def test_multistep_rk4_codegen(self):
325328 initial_guess = [0.0 ] * 5 ,
326329 )
327330
331+ # Check the result has all necessary attributes
332+ self .assertTrue (hasattr (result , "raw" ))
333+ self .assertTrue (hasattr (result , "solution" ))
334+ self .assertTrue (hasattr (result , "inputs" ))
335+ self .assertTrue (hasattr (result , "states" ))
336+ self .assertTrue (hasattr (result , "cost" ))
337+ self .assertTrue (hasattr (result , "exit_status" ))
338+ self .assertTrue (hasattr (result , "solve_time_ms" ))
339+ self .assertTrue (hasattr (result , "penalty" ))
340+ self .assertTrue (hasattr (result , "num_outer_iterations" ))
341+ self .assertTrue (hasattr (result , "num_inner_iterations" ))
342+ self .assertTrue (hasattr (result , "last_problem_norm_fpr" ))
343+ self .assertTrue (hasattr (result , "f1_infeasibility" ))
344+ self .assertTrue (hasattr (result , "f2_norm" ))
345+ self .assertTrue (hasattr (result , "lagrange_multipliers" ))
346+
347+ # Check all attributes of `result`
328348 self .assertEqual ("Converged" , result .exit_status )
349+ self .assertIsInstance (result .solution , list )
350+ self .assertIsInstance (result .inputs , list )
351+ self .assertIsInstance (result .states , list )
329352 self .assertEqual (5 , len (result .solution ))
330353 self .assertEqual (5 , len (result .inputs ))
331354 self .assertEqual (6 , len (result .states ))
355+ self .assertIsInstance (result .cost , float )
356+ self .assertGreaterEqual (result .cost , 0.0 )
357+ self .assertIsInstance (result .solve_time_ms , float )
358+ self .assertGreater (result .solve_time_ms , 0.0 )
359+ self .assertIsInstance (result .penalty , float )
360+ self .assertIsInstance (result .num_outer_iterations , int )
361+ self .assertGreaterEqual (result .num_outer_iterations , 1 )
362+ self .assertIsInstance (result .num_inner_iterations , int )
363+ self .assertGreaterEqual (result .num_inner_iterations , 1 )
364+ self .assertIsInstance (result .last_problem_norm_fpr , float )
365+ self .assertGreaterEqual (result .last_problem_norm_fpr , 0.0 )
366+ self .assertIsInstance (result .f1_infeasibility , float )
367+ self .assertGreaterEqual (result .f1_infeasibility , 0.0 )
368+ self .assertIsInstance (result .f2_norm , float )
369+ self .assertGreaterEqual (result .f2_norm , 0.0 )
370+ self .assertIsInstance (result .lagrange_multipliers , list )
332371 self .assertAlmostEqual (result .states [0 ][0 ], 1.0 )
333372 self .assertAlmostEqual (result .states [0 ][1 ], 0.0 )
334373
@@ -421,6 +460,12 @@ def test_generated_optimizer_defaults(self):
421460 self .assertEqual (result .states [0 ], [0.0 , 0.0 ])
422461 self .assertAlmostEqual (result .states [- 1 ][0 ], 0.6 )
423462 self .assertAlmostEqual (result .states [- 1 ][1 ], - 0.6 )
463+ self .assertEqual (result .penalty , 12.5 )
464+ self .assertEqual (result .num_outer_iterations , 3 )
465+ self .assertEqual (result .num_inner_iterations , 27 )
466+ self .assertEqual (result .last_problem_norm_fpr , 1e-6 )
467+ self .assertEqual (result .f1_infeasibility , 2e-5 )
468+ self .assertEqual (result .f2_norm , 3e-5 )
424469
425470 def test_optimizer_manifest_roundtrip (self ):
426471 manifest_path = self .ocp1_manifest_path
@@ -521,6 +566,58 @@ def test_multiple_shooting_state_extraction(self):
521566 self .assertEqual (result .inputs , [[0.1 ], [0.2 ], [0.4 ]])
522567 self .assertEqual (result .states , [[0.0 , 0.0 ], [0.1 , - 0.1 ], [0.3 , - 0.3 ], [0.7 , - 0.7 ]])
523568
569+ def test_tcp_optimizer_result (self ):
570+ optimizer = og .ocp .GeneratedOptimizer .load (self .ocp2_single_manifest_path )
571+
572+ try :
573+ result = optimizer .solve (
574+ x0 = [1.0 , - 1.0 ],
575+ xref = [0.0 , 0.0 ],
576+ )
577+
578+ self .assertTrue (hasattr (result , "raw" ))
579+ self .assertTrue (hasattr (result , "solution" ))
580+ self .assertTrue (hasattr (result , "inputs" ))
581+ self .assertTrue (hasattr (result , "states" ))
582+ self .assertTrue (hasattr (result , "cost" ))
583+ self .assertTrue (hasattr (result , "exit_status" ))
584+ self .assertTrue (hasattr (result , "solve_time_ms" ))
585+ self .assertTrue (hasattr (result , "penalty" ))
586+ self .assertTrue (hasattr (result , "num_outer_iterations" ))
587+ self .assertTrue (hasattr (result , "num_inner_iterations" ))
588+ self .assertTrue (hasattr (result , "last_problem_norm_fpr" ))
589+ self .assertTrue (hasattr (result , "f1_infeasibility" ))
590+ self .assertTrue (hasattr (result , "f2_norm" ))
591+ self .assertTrue (hasattr (result , "lagrange_multipliers" ))
592+
593+ self .assertEqual ("Converged" , result .exit_status )
594+ self .assertIsInstance (result .solution , list )
595+ self .assertIsInstance (result .inputs , list )
596+ self .assertIsInstance (result .states , list )
597+ self .assertEqual (5 , len (result .inputs ))
598+ self .assertEqual (6 , len (result .states ))
599+ self .assertIsInstance (result .cost , float )
600+ self .assertGreaterEqual (result .cost , 0.0 )
601+ self .assertIsInstance (result .solve_time_ms , float )
602+ self .assertGreater (result .solve_time_ms , 0.0 )
603+ self .assertIsInstance (result .penalty , float )
604+ self .assertGreater (result .penalty , 0.0 )
605+ self .assertIsInstance (result .num_outer_iterations , int )
606+ self .assertGreaterEqual (result .num_outer_iterations , 1 )
607+ self .assertIsInstance (result .num_inner_iterations , int )
608+ self .assertGreaterEqual (result .num_inner_iterations , 1 )
609+ self .assertIsInstance (result .last_problem_norm_fpr , float )
610+ self .assertGreaterEqual (result .last_problem_norm_fpr , 0.0 )
611+ self .assertIsInstance (result .f1_infeasibility , float )
612+ self .assertGreaterEqual (result .f1_infeasibility , 0.0 )
613+ self .assertIsInstance (result .f2_norm , float )
614+ self .assertGreaterEqual (result .f2_norm , 0.0 )
615+ self .assertIsInstance (result .lagrange_multipliers , list )
616+ self .assertAlmostEqual (result .states [0 ][0 ], 1.0 )
617+ self .assertAlmostEqual (result .states [0 ][1 ], - 1.0 )
618+ finally :
619+ optimizer .kill ()
620+
524621 def test_single_vs_multiple (self ):
525622 single_optimizer = og .ocp .GeneratedOptimizer .load (self .ocp2_single_manifest_path )
526623 multiple_optimizer = og .ocp .GeneratedOptimizer .load (self .ocp2_multiple_manifest_path )
0 commit comments