From 4272c015e1d2711af039672c062c4524032671f0 Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Sun, 5 Jan 2025 14:01:40 +0100 Subject: [PATCH 01/17] Make setuptools a required dependency, fixes #295. --- README.rst | 5 +++-- opty-dev-env.yml | 1 + setup.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 54ad8c1e..235221c2 100644 --- a/README.rst +++ b/README.rst @@ -79,6 +79,7 @@ The required dependencies are as follows: - numpy >= 1.19.0 - python 3.9-3.13 - scipy >= 1.5.0 +- setuptools - sympy >= 1.6.0 The optional dependencies are as follows: @@ -136,7 +137,7 @@ set the ``LD_LIBRARY_PATH`` so that you can link to Ipopt when installing Once Ipopt is installed and accessible, install conda then create an environment:: - $ conda create -n opty-custom -c conda-forge cython numpy pip scipy sympy + $ conda create -n opty-custom -c conda-forge cython numpy pip scipy setuptools sympy $ source activate opty-custom (opty-custom)$ pip install cyipopt # this will compile cyipopt against the available ipopt (opty-custom)$ pip install opty @@ -145,7 +146,7 @@ If you want to develop opty, create a conda environment with all of the dependencies installed:: $ conda config --add channels conda-forge - $ conda create -n opty-dev python sympy numpy scipy cython ipopt cyipopt matplotlib pytables pydy pandas pytest sphinx sphinx-gallery numpydoc + $ conda create -n opty-dev python sympy numpy scipy cython ipopt cyipopt matplotlib pytables pydy pandas pytest setuptools sphinx sphinx-gallery numpydoc $ source activate opty-dev Next download the opty source files and install with:: diff --git a/opty-dev-env.yml b/opty-dev-env.yml index e2e073a0..e995ba18 100644 --- a/opty-dev-env.yml +++ b/opty-dev-env.yml @@ -13,6 +13,7 @@ dependencies: - pytest-cov - python - scipy >=1.5.0 + - setuptools - sphinx - sphinx-gallery - sympy >=1.13 # version required for the docs diff --git a/setup.py b/setup.py index 34f7b404..33d3eefc 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ 'cython>=0.29.19', 'numpy>=1.19.0', 'scipy>=1.5.0', + 'setuptools', # provides distutils for Python >=3.13 'sympy>=1.6.0', ], extras_require={ From 4ee3cb80223e971248d67d4c11bc03c39377cc63 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Sat, 18 Jan 2025 16:27:51 +0100 Subject: [PATCH 02/17] changed a typo in line 434 --- opty/direct_collocation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index c598695e..4c084b23 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -340,7 +340,7 @@ def jacobian(self, free): Returns ======= - jac_vals : ndarray, shape((2*n + q + r + s)*(n*(N - 1) + o), ) + jac_vals : ndarray, shape((2*n + q + r + s)*(n*(N - 1)) + o, ) Non-zero Jacobian values in triplet format. """ From 10c0feb02e6b92fa33069836294f41c093e3117f Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Tue, 21 Jan 2025 14:28:10 +0100 Subject: [PATCH 03/17] add parse_free method to Problem class, add test fubction --- opty/direct_collocation.py | 56 ++++++++++++ opty/tests/test_direct_collocation.py | 124 +++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 4c084b23..3f60ffd0 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -597,6 +597,62 @@ def plot_objective_value(self): return ax + def parse_free(self, free): + """Parses the free parameters vector and returns it's components. + + Parameters + ---------- + free : ndarray, shape(n*N + q*N + r + s) + The free parameters of the system. + + where: + + - N : number of collocation nodes + - n : number of unknown state trajectories + - q : number of unknown input trajectories + - r : number of unknown parameters + - s : number of unknown time intervals (s=1 if variable duration, else s=0) + + + Returns + ------- + states : ndarray, shape(n, N) + The array of n states through N time steps. + specified_values : ndarray, shape(q, N) or shape(N,), or None + The array of q specified inputs through N time steps. + constant_values : ndarray, shape(r,) + The array of r constants. + time_interval : float + The time between collocation nodes. Only returned if + ``variable_duration`` is ``True``. + + """ + + n = self.collocator.num_states + N = self.collocator.num_collocation_nodes + q = self.collocator.num_unknown_input_trajectories + variable_duration = self.collocator._variable_duration + + len_states = n * N + len_specified = q * N + + free_states = free[:len_states].reshape((n, N)) + + if q == 0: + free_specified = None + else: + free_specified = free[len_states:len_states + len_specified] + if q > 1: + free_specified = free_specified.reshape((q, N)) + + if variable_duration: + free_time_interval = free[-1] + free_constants = free[len_states + len_specified:-1] + return free_states, free_specified, free_constants, free_time_interval + else: + free_constants = free[len_states + len_specified:] + return free_states, free_specified, free_constants + class ConstraintCollocator(object): """This class is responsible for generating the constraint function and the diff --git a/opty/tests/test_direct_collocation.py b/opty/tests/test_direct_collocation.py index adc2f3f8..ec4e37f9 100644 --- a/opty/tests/test_direct_collocation.py +++ b/opty/tests/test_direct_collocation.py @@ -10,7 +10,7 @@ from pytest import raises from ..direct_collocation import Problem, ConstraintCollocator -from ..utils import create_objective_function, sort_sympy +from ..utils import create_objective_function, sort_sympy, parse_free def test_pendulum(): @@ -1566,3 +1566,125 @@ def test_for_algebraic_eoms(): ) assert excinfo.type is ValueError + + +def test_prob_parse_free(): + """ + Test for parse_free method of Problem class. + =========================================== + + This test whether the parse_free method of the Problem class works as + the parse_free in utils. + + **States** + + - :math:`x_1, x_2, ux_1, ux_2` : state variables + + **Control** + + - :math:`u_1, u_2` : control variable + + """ + + t = mech.dynamicsymbols._t + + x1, x2, ux1, ux2 = mech.dynamicsymbols('x1 x2 ux1 ux2') + u1, u2 = mech.dynamicsymbols('u1 u2') + h = sym.symbols('h') + a, b = sym.symbols('a b') + + # equations of motion. + # (No meaning, just for testing) + eom = sym.Matrix([ + -x1.diff(t) + ux1, + -x2.diff(t) + ux2, + -ux1.diff(t) + a*u1, + -ux2.diff(t) + b*u2, + ]) + + # Set up and Solve the Optimization Problem + num_nodes = 11 + t0, tf = 0.0, 0.9 + state_symbols = (x1, x2, ux1, ux2) + control_symbols = (u1, u2) + + interval_value = (tf - t0)/(num_nodes - 1) + times = np.linspace(t0, tf, num_nodes) + + # Specify the symbolic instance constraints, as per the example. + instance_constraints = ( + x1.func(t0) - 1.0, + x2.func(t0) + 1.0, + ) + + # Specify the objective function and form the gradient. + + def obj(free): + return sum([free[i]**2 for i in range(2*num_nodes)]) + + def obj_grad(free): + grad = np.zeros_like(free) + grad[:2*num_nodes] = 2*free[:2*num_nodes] + return grad + + # Create the optimization problem and set any options. + prob = Problem( + obj, + obj_grad, + eom, + state_symbols, + num_nodes, + interval_value, + instance_constraints=instance_constraints, +) + + # Give some estimates for the trajectory. + initial_guess = np.random.rand(prob.num_free) + initial_guess1 = initial_guess + + # check whether same results. + statesu, controlsu, constantsu = parse_free(initial_guess1, + len(state_symbols), len(control_symbols), num_nodes) + + states, controls, constants = prob.parse_free(initial_guess) + assert(np.all(states == statesu)) + assert(np.all(controls == controlsu)) + assert(np.all(constants == constantsu)) + + + # test with variable interval_value + interval_value = h + t0, tf = 0.0, (num_nodes - 1)*interval_value + def obj(free): + return sum([free[i]**2 for i in range(2*num_nodes)]) + + def obj_grad(free): + grad = np.zeros_like(free) + grad[:2*num_nodes] = 2*free[:2*num_nodes] + return grad + + # Create the optimization problem and set any options. + prob = Problem( + obj, + obj_grad, + eom, + state_symbols, + num_nodes, + interval_value, + instance_constraints=instance_constraints, +) + + # Give some estimates for the trajectory. + initial_guess = np.random.rand(prob.num_free) + initial_guess1 = initial_guess + + # check whether same results. + statesu, controlsu, constantsu, timeu = parse_free(initial_guess1, + len(state_symbols), len(control_symbols), + num_nodes, variable_duration=True) + + states, controls, constants, times = prob.parse_free(initial_guess) + assert(np.all(states == statesu)) + assert(np.all(controls == controlsu)) + assert(np.all(constants == constantsu)) + assert(np.all(timeu == times)) From e7a22b2aa0ca61aa0a0ca23ac777f6d2cb999d50 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Tue, 21 Jan 2025 15:15:53 +0100 Subject: [PATCH 04/17] changed as per Timo's idea --- opty/direct_collocation.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 3f60ffd0..50ef2be3 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -633,26 +633,7 @@ def parse_free(self, free): q = self.collocator.num_unknown_input_trajectories variable_duration = self.collocator._variable_duration - len_states = n * N - len_specified = q * N - - free_states = free[:len_states].reshape((n, N)) - - if q == 0: - free_specified = None - else: - free_specified = free[len_states:len_states + len_specified] - if q > 1: - free_specified = free_specified.reshape((q, N)) - - if variable_duration: - free_time_interval = free[-1] - free_constants = free[len_states + len_specified:-1] - return free_states, free_specified, free_constants, free_time_interval - else: - free_constants = free[len_states + len_specified:] - return free_states, free_specified, free_constants - + return parse_free(free, n, q, N, variable_duration) class ConstraintCollocator(object): """This class is responsible for generating the constraint function and the From 29eaa2ca94fbf45333b7030e64b318b03f396059 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Tue, 21 Jan 2025 17:34:14 +0100 Subject: [PATCH 05/17] changed test function to np.allclose as per suggerstion --- opty/tests/test_direct_collocation.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/opty/tests/test_direct_collocation.py b/opty/tests/test_direct_collocation.py index ec4e37f9..1a074144 100644 --- a/opty/tests/test_direct_collocation.py +++ b/opty/tests/test_direct_collocation.py @@ -1647,10 +1647,9 @@ def obj_grad(free): len(state_symbols), len(control_symbols), num_nodes) states, controls, constants = prob.parse_free(initial_guess) - assert(np.all(states == statesu)) - assert(np.all(controls == controlsu)) - assert(np.all(constants == constantsu)) - + assert(np.allclose(states, statesu)) + assert(np.allclose(controls, controlsu)) + assert(np.allclose(constants, constantsu)) # test with variable interval_value interval_value = h @@ -1684,7 +1683,7 @@ def obj_grad(free): num_nodes, variable_duration=True) states, controls, constants, times = prob.parse_free(initial_guess) - assert(np.all(states == statesu)) - assert(np.all(controls == controlsu)) - assert(np.all(constants == constantsu)) - assert(np.all(timeu == times)) + assert(np.allclose(states, statesu)) + assert(np.allclose(controls, controlsu)) + assert(np.allclose(constants, constantsu)) + assert(np.allclose(timeu, times)) From 1516536c269e89c4eb944f141dc7731351e06b22 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Tue, 21 Jan 2025 18:10:33 +0100 Subject: [PATCH 06/17] changed to np.testing.assert_allclose(a, b) --- opty/tests/test_direct_collocation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/opty/tests/test_direct_collocation.py b/opty/tests/test_direct_collocation.py index 1a074144..ee598876 100644 --- a/opty/tests/test_direct_collocation.py +++ b/opty/tests/test_direct_collocation.py @@ -1647,9 +1647,9 @@ def obj_grad(free): len(state_symbols), len(control_symbols), num_nodes) states, controls, constants = prob.parse_free(initial_guess) - assert(np.allclose(states, statesu)) - assert(np.allclose(controls, controlsu)) - assert(np.allclose(constants, constantsu)) + np.testing.assert_allclose(states, statesu) + np.testing.assert_allclose(controls, controlsu) + np.testing.assert_allclose(constants, constantsu) # test with variable interval_value interval_value = h @@ -1683,7 +1683,7 @@ def obj_grad(free): num_nodes, variable_duration=True) states, controls, constants, times = prob.parse_free(initial_guess) - assert(np.allclose(states, statesu)) - assert(np.allclose(controls, controlsu)) - assert(np.allclose(constants, constantsu)) - assert(np.allclose(timeu, times)) + np.testing.assert_allclose(states, statesu) + np.testing.assert_allclose(controls, controlsu) + np.testing.assert_allclose(constants, constantsu) + np.testing.assert_allclose(timeu, times) From 12966847b1b9a930065cec236ef5c69e12ba7119 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Wed, 22 Jan 2025 16:48:04 +0100 Subject: [PATCH 07/17] improved HTML rendering --- opty/direct_collocation.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 50ef2be3..e0feced2 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -601,21 +601,12 @@ def parse_free(self, free): """Parses the free parameters vector and returns it's components. Parameters - ---------- + ========== free : ndarray, shape(n*N + q*N + r + s) The free parameters of the system. - where: - - - N : number of collocation nodes - - n : number of unknown state trajectories - - q : number of unknown input trajectories - - r : number of unknown parameters - - s : number of unknown time intervals (s=1 if variable duration, else s=0) - - Returns - ------- + ======= states : ndarray, shape(n, N) The array of n states through N time steps. specified_values : ndarray, shape(q, N) or shape(N,), or None @@ -626,6 +617,15 @@ def parse_free(self, free): The time between collocation nodes. Only returned if ``variable_duration`` is ``True``. + Notes + ===== + + - N : number of collocation nodes + - n : number of unknown state trajectories + - q : number of unknown input trajectories + - r : number of unknown parameters + - s : number of unknown time intervals (s=1 if ``variable duration`` is ``True`` else s=0) + """ n = self.collocator.num_states From 2f6ccd0ba651348d4a7adcd24be76460001dd55c Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Sat, 25 Jan 2025 09:00:47 +0100 Subject: [PATCH 08/17] trial push whether layout is o.k. --- opty/direct_collocation.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index e0feced2..1610c60e 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -727,6 +727,13 @@ def __init__(self, equations_of_motion, state_symbols, If True, STDOUT and STDERR of the Cython compilation call will be shown. + Attributes + ---------- + eom : sympy.Matrix + The equations of motion used. + state_symbols : tuple + The state symbols used. Functions of time. + """ self.eom = equations_of_motion From bd360fb77fe72f9c73901bd7b7cb3dff430a9146 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Sat, 25 Jan 2025 12:05:13 +0100 Subject: [PATCH 09/17] included all public attributes of ConstraintCollocator --- opty/direct_collocation.py | 70 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 1610c60e..b4431569 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -128,6 +128,8 @@ class Problem(cyipopt.Problem): eomn2, ... eomnN, c1, ..., co] + The attributes may be accessed as follows: Problem_instance.collocator.name_of_attribute + """ INF = 10e19 @@ -729,10 +731,74 @@ def __init__(self, equations_of_motion, state_symbols, Attributes ---------- - eom : sympy.Matrix + Some of the attributes are explained in more detail under Parameters above. + + eom: sympy.Matrix The equations of motion used. state_symbols : tuple - The state symbols used. Functions of time. + The state symbols used. Functrion of time. + state_derivative_symbols : tuple + symbols for the time derivatives of the states. + num_states : int + The number of states = len(state_symbols). + num_collocation_nodes : int + Number of times spaced evenly between the initial and final time of the optimization. + node_time_interval : float or sympy.Symbol + The time interval between the collocation nodes. float if the time is fixed, sympy.Symbol if the time is a variable. + time_interval_symbol : sympy.Symbol + The symbol used to represent the time interval if it is variable, else the internal symbol. + known_parameter_map : dict + A mapping of known parameters to their values. + unknown_parameters : tuple + The unknown parameters in the problem, in the sequence in which they appear in the solution of the optimization. + num_unknown_parameters : int + The number of unknown parameters. + parameters : tuple + known_parameters + unknown_parameters + num_parameters : int + The number of parameters = len(parameters). + known_trajectory_map : dict + A mapping of known trajectories to their values, see also above in Parameters + known_trajectory_symbols : tuple + The known trajectory symbols. + num_known_trajectories : int + The number of known trajectories = len(known_trajectory_symbols). + unknown_input_trajectories : tuple + The unknown input trajectories symbols. + num_unknown_input_trajectories : int + The number of unknown input trajectories = len(unknown_input_trajectories). + input_trajectories : tuple + known_input_trajectories + unknown_input_trajectories + instance_constraints : tuple + The instance constraints used in the optimization. + num_constraints : int + The number of constraints = (num_collection_nodes-1)*num_states + len(instance_constraints). + num_instance_constraints : int + The number of instance constraints = len(instance_constraints). + previous_discrete_state_symbols : tuple + The symbols for the previous discrete states. + current_discrete_state_symbols : tuple + The symbols for the current discrete states. + next_discrete_state_symbols : tuple + The symbols for the next discrete states. + current_discrete_specified_symbols : tuple + The symbols for the current discrete specified inputs. + next_discrete_specified_symbols : tuple + The symbols for the next discrete specified inputs. + integration_method : str + The integration method used. + discrete_eom : sympy.Matrix + Discretized equations of motion. Depending on the integration method used. + num_free : int + Number of variables to be optimized + time_symbol : sympy.Symbol + The symbol used to represent time, usually `t` + tmp_dir + The temporary directory used to store files generated + parallel : bool + Whether to use parallel processing or not. + show_compile_output : bool + Whether to show the compile output or not. """ self.eom = equations_of_motion From 222505b241ed306cdc881c364802b75923e75ce9 Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Sun, 26 Jan 2025 11:40:04 +0100 Subject: [PATCH 10/17] tried to address the suggestions given --- opty/direct_collocation.py | 150 +++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 72 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index b4431569..c03063a4 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -656,9 +656,86 @@ class ConstraintCollocator(object): - o : number of instance constraints - nN + qN + r + s : number of free variables - n(N - 1) + o : number of constraints + - Some of the attributes are explained in more detail under Parameters below. + + Attributes + ---------- + ========== + + current_discrete_state_symbols : n-tuple + The symbols for the current discrete states. + current_discrete_specified_symbols : q-tuple + The symbols for the current discrete specified inputs. + discrete_eom : sympy.Matrix, shape(n, 1) + Discretized equations of motion. Depending on the integration method + used. + eom: sympy.Matrix, shape(n, 1) + The equations of motion used. + input_trajectories : tuple + known_input_trajectories + unknown_input_trajectories. + instance_constraints : o-tuple + The instance constraints used in the optimization. + integration_method : str + The integration method used. + known_parameters : tuple + The symbols of the known parameters in the problem. + known_parameter_map : dict + A mapping of known parameters to their values. + known_trajectory_map : dict + A mapping of known trajectories to their values. + known_trajectory_symbols : (m-q)-tuple + The known trajectory symbols. + next_discrete_specified_symbols : q-tuple + The symbols for the next discrete specified inputs. + next_discrete_state_symbols : n-tuple + The symbols for the next discrete states. + node_time_interval : float or sympy.Symbol + The time interval between the collocation nodes. float if the interval + is fixed, sympy.Symbol if the interval is variable. + num_collocation_nodes : int + Number of times spaced evenly between the initial and final time of + the optimization = N. + num_constraints : int + The number of constraints = (num_collection_nodes-1)*num_states + + len(instance_constraints). + num_free : int + Number of variables to be optimized = n*N + q*N + r + s. + num_input_trajectories : int + The number of input trajectories = len(input_trajectories). + num_instance_constraints : int + The number of instance constraints = len(instance_constraints). + num_known_trajectories : int + The number of known trajectories = len(known_trajectory_symbols). + num_parameters : int + The number of parameters = len(parameters). + num_states : int + The number of states = len(state_symbols) = n. + num_unknown_input_trajectories : int + The number of unknown input trajectories = + len(unknown_input_trajectories). + num_unknown_parameters : int + The number of unknown parameters = r. + parameters : tuple + known_parameters + unknown_parameters. + parallel : bool + Whether to use parallel processing or not. + previous_discrete_state_symbols : n-tuple + The symbols for the previous discrete states. + show_compile_output : bool + Whether to show the compile output or not. + state_derivative_symbols : n-tuple + symbols for the time derivatives of the states. + time_symbol : sympy.Symbol + The symbol used to represent time, usually `t`. + tmp_dir + The temporary directory used to store files generated. + unknown_input_trajectories : q-tuple + The unknown input trajectories symbols. + unknown_parameters : r-tuple + The unknown parameters in the problem, in the sequence in which they + appear in the solution of the optimization. """ - def __init__(self, equations_of_motion, state_symbols, num_collocation_nodes, node_time_interval, known_parameter_map={}, known_trajectory_map={}, @@ -729,77 +806,6 @@ def __init__(self, equations_of_motion, state_symbols, If True, STDOUT and STDERR of the Cython compilation call will be shown. - Attributes - ---------- - Some of the attributes are explained in more detail under Parameters above. - - eom: sympy.Matrix - The equations of motion used. - state_symbols : tuple - The state symbols used. Functrion of time. - state_derivative_symbols : tuple - symbols for the time derivatives of the states. - num_states : int - The number of states = len(state_symbols). - num_collocation_nodes : int - Number of times spaced evenly between the initial and final time of the optimization. - node_time_interval : float or sympy.Symbol - The time interval between the collocation nodes. float if the time is fixed, sympy.Symbol if the time is a variable. - time_interval_symbol : sympy.Symbol - The symbol used to represent the time interval if it is variable, else the internal symbol. - known_parameter_map : dict - A mapping of known parameters to their values. - unknown_parameters : tuple - The unknown parameters in the problem, in the sequence in which they appear in the solution of the optimization. - num_unknown_parameters : int - The number of unknown parameters. - parameters : tuple - known_parameters + unknown_parameters - num_parameters : int - The number of parameters = len(parameters). - known_trajectory_map : dict - A mapping of known trajectories to their values, see also above in Parameters - known_trajectory_symbols : tuple - The known trajectory symbols. - num_known_trajectories : int - The number of known trajectories = len(known_trajectory_symbols). - unknown_input_trajectories : tuple - The unknown input trajectories symbols. - num_unknown_input_trajectories : int - The number of unknown input trajectories = len(unknown_input_trajectories). - input_trajectories : tuple - known_input_trajectories + unknown_input_trajectories - instance_constraints : tuple - The instance constraints used in the optimization. - num_constraints : int - The number of constraints = (num_collection_nodes-1)*num_states + len(instance_constraints). - num_instance_constraints : int - The number of instance constraints = len(instance_constraints). - previous_discrete_state_symbols : tuple - The symbols for the previous discrete states. - current_discrete_state_symbols : tuple - The symbols for the current discrete states. - next_discrete_state_symbols : tuple - The symbols for the next discrete states. - current_discrete_specified_symbols : tuple - The symbols for the current discrete specified inputs. - next_discrete_specified_symbols : tuple - The symbols for the next discrete specified inputs. - integration_method : str - The integration method used. - discrete_eom : sympy.Matrix - Discretized equations of motion. Depending on the integration method used. - num_free : int - Number of variables to be optimized - time_symbol : sympy.Symbol - The symbol used to represent time, usually `t` - tmp_dir - The temporary directory used to store files generated - parallel : bool - Whether to use parallel processing or not. - show_compile_output : bool - Whether to show the compile output or not. - """ self.eom = equations_of_motion From 26681cafb98b7d22d31aebb06b523fda43e9136d Mon Sep 17 00:00:00 2001 From: Peter Stahlecker Date: Sun, 26 Jan 2025 13:22:39 +0100 Subject: [PATCH 11/17] put attributes above notes, changed that sentence --- opty/direct_collocation.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index c03063a4..45937c77 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -643,25 +643,9 @@ class ConstraintCollocator(object): for a non-linear programming problem where the essential constraints are defined from the equations of motion of the system. - Notes - ===== - - - N : number of collocation nodes - - n : number of states - - m : number of input trajectories - - q : number of unknown input trajectories - - r : number of unknown parameters - - s : number of unknown time intervals (0 or 1 if fixed duration or - variable duration) - - o : number of instance constraints - - nN + qN + r + s : number of free variables - - n(N - 1) + o : number of constraints - - Some of the attributes are explained in more detail under Parameters below. Attributes - ---------- ========== - current_discrete_state_symbols : n-tuple The symbols for the current discrete states. current_discrete_specified_symbols : q-tuple @@ -735,6 +719,23 @@ class ConstraintCollocator(object): The unknown parameters in the problem, in the sequence in which they appear in the solution of the optimization. + Notes + ===== + + - N : number of collocation nodes + - n : number of states + - m : number of input trajectories + - q : number of unknown input trajectories + - r : number of unknown parameters + - s : number of unknown time intervals (0 or 1 if fixed duration or + variable duration) + - o : number of instance constraints + - nN + qN + r + s : number of free variables + - n(N - 1) + o : number of constraints + + Some of the attributes are explained in more detail under Parameters below. + + """ def __init__(self, equations_of_motion, state_symbols, num_collocation_nodes, node_time_interval, From 2f3ba013dee279beb4b7df2e2a5fce293d02660f Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Sun, 26 Jan 2025 14:28:26 +0100 Subject: [PATCH 12/17] Update opty/direct_collocation.py --- opty/direct_collocation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 45937c77..da4bb6aa 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -128,7 +128,7 @@ class Problem(cyipopt.Problem): eomn2, ... eomnN, c1, ..., co] - The attributes may be accessed as follows: Problem_instance.collocator.name_of_attribute + The attributes may be accessed as follows: ``Problem_instance.collocator.name_of_attribute`` """ From 7bed059c6390939d1409c8c51085931c5dcb21e9 Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Sun, 26 Jan 2025 14:29:18 +0100 Subject: [PATCH 13/17] Update opty/direct_collocation.py --- opty/direct_collocation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index da4bb6aa..a2db8848 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -675,7 +675,7 @@ class ConstraintCollocator(object): The symbols for the next discrete states. node_time_interval : float or sympy.Symbol The time interval between the collocation nodes. float if the interval - is fixed, sympy.Symbol if the interval is variable. + is fixed, ``sympy.Symbol`` if the interval is variable. num_collocation_nodes : int Number of times spaced evenly between the initial and final time of the optimization = N. From da1214035fd4eb1d33fb021bcb0ef10a6a72bd4f Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Mon, 27 Jan 2025 07:53:42 +0100 Subject: [PATCH 14/17] Update readthedocs config. --- .readthedocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index f9514ee9..d514e60c 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,8 +1,8 @@ version: 2 build: - os: "ubuntu-22.04" + os: "ubuntu-24.04" tools: - python: "mambaforge-22.9" + python: "miniconda-latest" sphinx: configuration: docs/conf.py formats: all From bffff7a1eeb5d17a7ec4a2957fa471999cdab127 Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Mon, 27 Jan 2025 07:59:36 +0100 Subject: [PATCH 15/17] Testing the RTD preview builds. --- docs/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 4721e1b2..bfbc5e29 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,6 +6,8 @@ Welcome to opty's documentation! ================================ +Trying out a preview build. + Contents -------- From f88480f8c792582edc5c0989ab8637395899d458 Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Mon, 27 Jan 2025 08:18:48 +0100 Subject: [PATCH 16/17] Docstring shuffling. --- docs/index.rst | 2 -- opty/direct_collocation.py | 12 +++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index bfbc5e29..4721e1b2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,8 +6,6 @@ Welcome to opty's documentation! ================================ -Trying out a preview build. - Contents -------- diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index a2db8848..8f5d9f24 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -626,7 +626,8 @@ def parse_free(self, free): - n : number of unknown state trajectories - q : number of unknown input trajectories - r : number of unknown parameters - - s : number of unknown time intervals (s=1 if ``variable duration`` is ``True`` else s=0) + - s : number of unknown time intervals (s=1 if ``variable duration`` is + ``True`` else s=0) """ @@ -643,7 +644,6 @@ class ConstraintCollocator(object): for a non-linear programming problem where the essential constraints are defined from the equations of motion of the system. - Attributes ========== current_discrete_state_symbols : n-tuple @@ -719,6 +719,11 @@ class ConstraintCollocator(object): The unknown parameters in the problem, in the sequence in which they appear in the solution of the optimization. + Some of the attributes are explained in more detail under Parameters below. + + It is best to treat ``ConstraintCollocator`` as immutable, changing + attributes after initialization will inevitably fail. + Notes ===== @@ -733,9 +738,6 @@ class ConstraintCollocator(object): - nN + qN + r + s : number of free variables - n(N - 1) + o : number of constraints - Some of the attributes are explained in more detail under Parameters below. - - """ def __init__(self, equations_of_motion, state_symbols, num_collocation_nodes, node_time_interval, From a77fedb1515ddd9db5bea92c76c0bb4dafd7f148 Mon Sep 17 00:00:00 2001 From: "Jason K. Moore" Date: Mon, 27 Jan 2025 08:41:05 +0100 Subject: [PATCH 17/17] Move paragraph text back into notes. --- opty/direct_collocation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/opty/direct_collocation.py b/opty/direct_collocation.py index 8f5d9f24..47059a0f 100644 --- a/opty/direct_collocation.py +++ b/opty/direct_collocation.py @@ -719,11 +719,6 @@ class ConstraintCollocator(object): The unknown parameters in the problem, in the sequence in which they appear in the solution of the optimization. - Some of the attributes are explained in more detail under Parameters below. - - It is best to treat ``ConstraintCollocator`` as immutable, changing - attributes after initialization will inevitably fail. - Notes ===== @@ -738,6 +733,11 @@ class ConstraintCollocator(object): - nN + qN + r + s : number of free variables - n(N - 1) + o : number of constraints + Some of the attributes are explained in more detail under Parameters below. + + It is best to treat ``ConstraintCollocator`` as immutable, changing + attributes after initialization will inevitably fail. + """ def __init__(self, equations_of_motion, state_symbols, num_collocation_nodes, node_time_interval,