From 502c61089a537d897447774637d6e5a030767e06 Mon Sep 17 00:00:00 2001 From: Pantelis Sopasakis Date: Wed, 27 Mar 2024 17:00:34 +0000 Subject: [PATCH 1/6] Code generation for AffineSpace About: - Support for AffineSpace in opengen (issue #333) - Print support for SolverStatus - Add .jinja extension to some jinja files (issue #343) - Change hard coding of file names in builder - Fix typo in icasadi_lib.rs Issues: - Addresses #333 #343 --- .../opengen/builder/optimizer_builder.py | 11 +++-- open-codegen/opengen/constraints/__init__.py | 1 + .../opengen/constraints/affine_space.py | 40 +++++++++++++++++++ open-codegen/opengen/tcp/solver_status.py | 12 ++++++ ...rface.rs => optimizer_cinterface.rs.jinja} | 0 .../opengen/templates/icasadi/icasadi_lib.rs | 2 +- .../{optimizer.rs => optimizer.rs.jinja} | 19 ++++++--- ...izer_build.rs => optimizer_build.rs.jinja} | 0 ..._cargo.toml => optimizer_cargo.toml.jinja} | 0 9 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 open-codegen/opengen/constraints/affine_space.py rename open-codegen/opengen/templates/c/{optimizer_cinterface.rs => optimizer_cinterface.rs.jinja} (100%) rename open-codegen/opengen/templates/{optimizer.rs => optimizer.rs.jinja} (96%) rename open-codegen/opengen/templates/{optimizer_build.rs => optimizer_build.rs.jinja} (100%) rename open-codegen/opengen/templates/{optimizer_cargo.toml => optimizer_cargo.toml.jinja} (100%) diff --git a/open-codegen/opengen/builder/optimizer_builder.py b/open-codegen/opengen/builder/optimizer_builder.py index b628193c..55c96f64 100644 --- a/open-codegen/opengen/builder/optimizer_builder.py +++ b/open-codegen/opengen/builder/optimizer_builder.py @@ -26,6 +26,11 @@ _ICASADI_PREFIX = 'icasadi_' _ROS_PREFIX = 'ros_node_' +# Template files +_OPTIMIZER_RS = "optimizer.rs.jinja" +_OPTIMIZER_CARGO_TOML = "optimizer_cargo.toml.jinja" +_OPTIMIZER_BUILD_RS = "optimizer_build.rs.jinja" + def make_dir_if_not_exists(directory): if not os.path.exists(directory): @@ -243,7 +248,7 @@ def __generate_cargo_toml(self): self.__logger.info("Generating Cargo.toml for target optimizer") target_dir = self.__target_dir() cargo_template = OpEnOptimizerBuilder.__get_template( - 'optimizer_cargo.toml') + _OPTIMIZER_CARGO_TOML) cargo_output_template = cargo_template.render( meta=self.__meta, build_config=self.__build_config, @@ -540,7 +545,7 @@ def __generate_main_project_code(self): "Generating main code for target optimizer (lib.rs)") target_dir = self.__target_dir() optimizer_rs_template = OpEnOptimizerBuilder.__get_template( - 'optimizer.rs') + _OPTIMIZER_RS) optimizer_rs_output_template = optimizer_rs_template.render( solver_config=self.__solver_config, meta=self.__meta, @@ -557,7 +562,7 @@ def __generate_build_rs(self): self.__logger.info("Generating build.rs for target optimizer") target_dir = self.__target_dir() build_rs_template = OpEnOptimizerBuilder.__get_template( - 'optimizer_build.rs') + _OPTIMIZER_BUILD_RS) build_rs_output_template = build_rs_template.render( meta=self.__meta, activate_clib_generation=self.__build_config.build_c_bindings) diff --git a/open-codegen/opengen/constraints/__init__.py b/open-codegen/opengen/constraints/__init__.py index 4fbf168b..e361c496 100644 --- a/open-codegen/opengen/constraints/__init__.py +++ b/open-codegen/opengen/constraints/__init__.py @@ -11,3 +11,4 @@ from .finite_set import * from .halfspace import * from .simplex import * +from .affine_space import * diff --git a/open-codegen/opengen/constraints/affine_space.py b/open-codegen/opengen/constraints/affine_space.py new file mode 100644 index 00000000..28879e23 --- /dev/null +++ b/open-codegen/opengen/constraints/affine_space.py @@ -0,0 +1,40 @@ +import casadi.casadi as cs +import numpy as np +from .constraint import Constraint +import opengen.functions as fn + + +class AffineSpace(Constraint): + """An affine constraint + + A constraint of the form :math:`Ax = b`, where :math:`A` and :math:`b` are + a matrix and a vector of appropriate dimensions + """ + + def __init__(self, A, b): + """Constructor for an affine space + + :return: new instance of AffineSpace + """ + self.__A = A.flatten('C') + self.__b = b + + @property + def matrix_a(self): + return self.__A + + @property + def vector_b(self): + return self.__b + + def distance_squared(self, u): + raise NotImplementedError() + + def project(self, u): + raise NotImplementedError() + + def is_convex(self): + return True + + def is_compact(self): + return False diff --git a/open-codegen/opengen/tcp/solver_status.py b/open-codegen/opengen/tcp/solver_status.py index 59dffa39..7267dabc 100644 --- a/open-codegen/opengen/tcp/solver_status.py +++ b/open-codegen/opengen/tcp/solver_status.py @@ -115,3 +115,15 @@ def cost(self): :return: Value of cost function at the solution """ return self.__dict__["__cost"] + + def __repr__(self): + return "Solver Status Report:\n" + \ + f"Exit status....... {self.exit_status}\n" + \ + f"Num Outer Iters... {self.num_outer_iterations}\n" + \ + f"Num Inner Iters... {self.num_inner_iterations}\n" + \ + f"FPR............... {self.last_problem_norm_fpr}\n" + \ + "Infeasibility\n" + \ + f" L F1............ {self.f1_infeasibility}\n" + \ + f" L Fw............ {self.f2_norm}\n" + \ + f"Penalty............ {self.penalty}\n" + \ + f"Time............... {self.solve_time_ms} ms\n" diff --git a/open-codegen/opengen/templates/c/optimizer_cinterface.rs b/open-codegen/opengen/templates/c/optimizer_cinterface.rs.jinja similarity index 100% rename from open-codegen/opengen/templates/c/optimizer_cinterface.rs rename to open-codegen/opengen/templates/c/optimizer_cinterface.rs.jinja diff --git a/open-codegen/opengen/templates/icasadi/icasadi_lib.rs b/open-codegen/opengen/templates/icasadi/icasadi_lib.rs index 3de21def..efd30433 100644 --- a/open-codegen/opengen/templates/icasadi/icasadi_lib.rs +++ b/open-codegen/opengen/templates/icasadi/icasadi_lib.rs @@ -268,7 +268,7 @@ pub fn precondition( /// Computes the initial penalty /// -/// Make sure that you have called init_ +/// Make sure that you have called init_{{ meta.optimizer_name }} pub fn initial_penalty( u: &[f64], static_params: &[f64], diff --git a/open-codegen/opengen/templates/optimizer.rs b/open-codegen/opengen/templates/optimizer.rs.jinja similarity index 96% rename from open-codegen/opengen/templates/optimizer.rs rename to open-codegen/opengen/templates/optimizer.rs.jinja index 912784db..3624bbe6 100644 --- a/open-codegen/opengen/templates/optimizer.rs +++ b/open-codegen/opengen/templates/optimizer.rs.jinja @@ -61,17 +61,18 @@ pub const {{meta.optimizer_name|upper}}_N1: usize = {{problem.dim_constraints_au /// Number of penalty constraints pub const {{meta.optimizer_name|upper}}_N2: usize = {{problem.dim_constraints_penalty() or 0}}; -{% include "c/optimizer_cinterface.rs" %} +{% include "c/optimizer_cinterface.rs.jinja" %} // ---Parameters of the constraints---------------------------------------------------------------------- - +{# CASE I: Ball* or Sphere #} {% if 'Ball1' == problem.constraints.__class__.__name__ or 'Ball2' == problem.constraints.__class__.__name__ or 'BallInf' == problem.constraints.__class__.__name__ or 'Sphere2' == problem.constraints.__class__.__name__ -%} /// Constraints: Centre of Ball const CONSTRAINTS_BALL_XC: Option<&[f64]> = {% if problem.constraints.center is not none %}Some(&[{{problem.constraints.center | join(', ')}}]){% else %}None{% endif %}; - /// Constraints: Radius of Ball const CONSTRAINTS_BALL_RADIUS : f64 = {{problem.constraints.radius}}; -{% elif 'Rectangle' == problem.constraints.__class__.__name__ -%} +{% endif %} +{# CASE II: Rectangle #} +{% if 'Rectangle' == problem.constraints.__class__.__name__ -%} const CONSTRAINTS_XMIN :Option<&[f64]> = {% if problem.constraints.xmin is not none %}Some(&[ {%- for xmini in problem.constraints.xmin -%} {%- if float('-inf') == xmini -%}std::f64::NEG_INFINITY{%- else -%}{{xmini}}{%- endif -%}, @@ -85,7 +86,6 @@ const CONSTRAINTS_XMAX :Option<&[f64]> = {% if problem.constraints.xmax is not n {% endif %} - {% if problem.alm_set_c is not none %} // ---Parameters of ALM-type constraints (Set C)--------------------------------------------------------- {% if 'Ball2' == problem.alm_set_c.__class__.__name__ or 'BallInf' == problem.alm_set_c.__class__.__name__ -%} @@ -150,6 +150,10 @@ fn make_constraints() -> impl Constraint { {% elif 'Rectangle' == problem.constraints.__class__.__name__ -%} // - Rectangle: Rectangle::new(CONSTRAINTS_XMIN, CONSTRAINTS_XMAX) + {% elif 'AffineSpace' == problem.constraints.__class__.__name__ -%} + let constraints_affine_a = vec![{{problem.constraints.matrix_a | join(', ')}}]; + let constraints_affine_b = vec![{{problem.constraints.vector_b | join(', ')}}]; + AffineSpace::new(constraints_affine_a, constraints_affine_b) {% elif 'FiniteSet' == problem.constraints.__class__.__name__ -%} // - Finite Set: let data: &[&[f64]] = &[ @@ -192,6 +196,11 @@ fn make_constraints() -> impl Constraint { let center_{{loop.index}}: Option<&[f64]> = {% if set_i.center is not none %}Some(&[{{set_i.center | join(', ')}}]){% else %}None{% endif %}; let set_{{loop.index}} = Sphere2::new(center_{{loop.index}}, radius_{{loop.index}}); let bounds = bounds.add_constraint(idx_{{loop.index}}, set_{{loop.index}}); + {% elif 'AffineSpace' == set_i.__class__.__name__ -%} + let constraints_affine_a = vec![{{problem.constraints.matrix_a | join(', ')}}]; + let constraints_affine_b = vec![{{problem.constraints.vector_b | join(', ')}}]; + let set_{{loop.index}} = AffineSpace::new(constraints_affine_a, constraints_affine_b) + let bounds = bounds.add_constraint(idx_{{loop.index}}, set_{{loop.index}}); {% elif 'Simplex' == set_i.__class__.__name__ -%} let alpha_{{loop.index}} = {{set_i.alpha}}; let set_{{loop.index}} = Simplex::new(alpha_{{loop.index}}); diff --git a/open-codegen/opengen/templates/optimizer_build.rs b/open-codegen/opengen/templates/optimizer_build.rs.jinja similarity index 100% rename from open-codegen/opengen/templates/optimizer_build.rs rename to open-codegen/opengen/templates/optimizer_build.rs.jinja diff --git a/open-codegen/opengen/templates/optimizer_cargo.toml b/open-codegen/opengen/templates/optimizer_cargo.toml.jinja similarity index 100% rename from open-codegen/opengen/templates/optimizer_cargo.toml rename to open-codegen/opengen/templates/optimizer_cargo.toml.jinja From fe6f7bd97855bb4560b581389edbe1116ce40bb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:06:03 +0000 Subject: [PATCH 2/6] Update ndarray requirement from 0.15 to 0.16 Updates the requirements on [ndarray](https://github.com/rust-ndarray/ndarray) to permit the latest version. - [Release notes](https://github.com/rust-ndarray/ndarray/releases) - [Changelog](https://github.com/rust-ndarray/ndarray/blob/master/RELEASES.md) - [Commits](https://github.com/rust-ndarray/ndarray/compare/ndarray-rand-0.15.0...0.16.0) --- updated-dependencies: - dependency-name: ndarray dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f1f645a4..706d9f50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,7 @@ rpmalloc = { version = "0.2", features = [ roots = "0.0.8" # Least squares solver -ndarray = { version = "0.15", features = ["approx"] } +ndarray = { version = "0.16", features = ["approx"] } modcholesky = "0.1" # jemallocator is an optional feature; it will only be loaded if the feature From 23836b025d635a5b5fc40c26e6e8fdfa605fec80 Mon Sep 17 00:00:00 2001 From: Pantelis Sopasakis Date: Thu, 15 Aug 2024 14:13:42 +0100 Subject: [PATCH 3/6] [docit] affine space: python docstrings --- Cargo.toml | 5 +++-- open-codegen/opengen/constraints/affine_space.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 706d9f50..7369a45d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,8 +98,9 @@ rpmalloc = { version = "0.2", features = [ # epigraph of the squared Euclidean norm roots = "0.0.8" -# Least squares solver -ndarray = { version = "0.16", features = ["approx"] } +# Least squares solver (NOTE: ndarray must be version 0.15 - not 0.16) +# Bug report: https://github.com/argmin-rs/modcholesky/issues/34 +ndarray = { version = "0.15", features = ["approx"] } modcholesky = "0.1" # jemallocator is an optional feature; it will only be loaded if the feature diff --git a/open-codegen/opengen/constraints/affine_space.py b/open-codegen/opengen/constraints/affine_space.py index 28879e23..1eb054c6 100644 --- a/open-codegen/opengen/constraints/affine_space.py +++ b/open-codegen/opengen/constraints/affine_space.py @@ -21,20 +21,36 @@ def __init__(self, A, b): @property def matrix_a(self): + """Matrix A + """ return self.__A @property def vector_b(self): + """Vector b + """ return self.__b def distance_squared(self, u): + """Squared distance to affine space + + Not implemented yet + """ raise NotImplementedError() def project(self, u): + """Projection on affine space + + Not implemented yet + """ raise NotImplementedError() def is_convex(self): + """Affine spaces are convex sets + """ return True def is_compact(self): + """Affine spaces are not compact sets + """ return False From 9ed7dd5219034d792e5b8f5577048943f1891568 Mon Sep 17 00:00:00 2001 From: Pantelis Sopasakis Date: Thu, 15 Aug 2024 16:32:36 +0100 Subject: [PATCH 4/6] [ci skip] changelog: bump version to 0.9.0 --- docs/python-interface.md | 29 ++++++++++++++++------------- open-codegen/CHANGELOG.md | 9 +++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/docs/python-interface.md b/docs/python-interface.md index 77983d8a..e14b800c 100644 --- a/docs/python-interface.md +++ b/docs/python-interface.md @@ -77,18 +77,21 @@ following types of constraints: | Constraint | Explanation | |--------------------|------------------------------------------------| -| `Ball2` | Euclidean ball: `Ball2(None, r)` creates a Euclidean ball of radius `r` centered at the origin, and `Ball2(xc, r)` is a ball centered at point `xc` (list/np.array) | -| `BallInf` | Ball of infinity norm:`BallInf(None, r)` creates an infinity-norm ball of radius `r` centered at the origin, and `BallInf(xc, r)` is an infinity ball centered at point `xc` (list/np.array) | -| `Ball1` | L1 ball: `Ball(None, r)` creates an ell1-ball of radius `r` centered at the origin, and `BallInf(xc, r)` is an ell1-ball centered at point `xc` (list/np.array)| -| `Sphere2` | Euclidean sphere: `Sphere2(None, r)` creates a Euclidean sphere of radius `r` centered at the origin, and `Sphere2(xc, r)` is a sphere centered at point `xc` (list/np.array) | -| `Simplex` | A simplex of size $\alpha$ is a set of the form $\Delta_\alpha = \\{x \in \mathbb{R}^n {}:{} x_i \geq 0, \sum_i x_i = \alpha\\}$. Create one with `Simplex(alpha)`. Projections are computed using Condat's [fast projection method](https://link.springer.com/article/10.1007/s10107-015-0946-6). | -| `Halfspace` | A halfspace is a set of the form $\\{u \in \mathbb{R}^{n_u} {}:{} \langle c, u\rangle \leq b \\}$, for a vector $c$ and a scalar $b$. The syntax is straightforwarrd: `Halfspace(c, b)`. | -| `FiniteSet` | Finite set, $\\{u^{(1)},\ldots,u^{(m)}\\}$; the set of point is provided as a list of lists, for example, `FiniteSet([[1,2],[2,3],[4,5]])`. The commonly used set of binary numbers, $\\{0, 1\\}$, is created with `FiniteSet([[0], [1]])`. | -| `NoConstraints` | No constraints - the whole $\mathbb{R}^{n}$| -| `Rectangle` | Rectangle, $$R = \\{u \in \mathbb{R}^{n_u} {}:{} f_{\min} \leq u \leq f_{\max}\\},$$ for example, `Rectangle(fmin, fmax)` | -| `SecondOrderCone` | Second-order aka "ice cream" aka "Lorenz" cone | -| `EpigraphSquaredNorm`| The epigraph of the squared Eucliden norm is a set of the form $X = \\{(z, t) \in \mathbb{R}^{n+1}: \Vert z \Vert \leq t\\}$. | -| `CartesianProduct` | Cartesian product of any of the above. See more information below. | +| `AffineSpace` | An affine space is a set of the form $\\{x\in\mathbb{R}^n {}:{} Ax = b\\}$ for a matrix $A\in \mathbb{R}^p$ and vector $b$. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.AffineSpace.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.affine_space)) | +| `Ball2` | Euclidean ball: `Ball2(None, r)` creates a Euclidean ball of radius `r` centered at the origin, and `Ball2(xc, r)` is a ball centered at point `xc` (list/np.array) Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Ball2.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.ball2)) | +| `BallInf` | Ball of infinity norm:`BallInf(None, r)` creates an infinity-norm ball of radius `r` centered at the origin, and `BallInf(xc, r)` is an infinity ball centered at point `xc` (list/np.array) Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.BallInf.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.ball_inf)) | +| `Ball1` | L1 ball: `Ball(None, r)` creates an ell1-ball of radius `r` centered at the origin, and `BallInf(xc, r)` is an ell1-ball centered at point `xc` (list/np.array) Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Ball1.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.ball1)) | +| `Sphere2` | Euclidean sphere: `Sphere2(None, r)` creates a Euclidean sphere of radius `r` centered at the origin, and `Sphere2(xc, r)` is a sphere centered at point `xc` (list/np.array) Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Sphere2.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.sphere2)) | +| `Simplex` | A simplex of size $\alpha$ is a set of the form $\Delta_\alpha = \\{x \in \mathbb{R}^n {}:{} x_i \geq 0, \sum_i x_i = \alpha\\}$. Create one with `Simplex(alpha)`. Projections are computed using Condat's [fast projection method](https://link.springer.com/article/10.1007/s10107-015-0946-6). Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Simplex.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.simplex)) | +| `Halfspace` | A halfspace is a set of the form $\\{u \in \mathbb{R}^{n_u} {}:{} \langle c, u\rangle \leq b \\}$, for a vector $c$ and a scalar $b$. The syntax is straightforward: `Halfspace(c, b)`. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Halfspace.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.halfspace)) | +| `Hyperplane` | A hyperplane is a set given by $H=\\{x \in \mathbb{R}^n {}:{} c^\intercal x =b \\}$. Docs: [Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Hyperplane.html) | +| `FiniteSet` | Finite set, $\\{u^{(1)},\ldots,u^{(m)}\\}$; the set of point is provided as a list of lists, for example, `FiniteSet([[1,2],[2,3],[4,5]])`. The commonly used set of binary numbers, $\\{0, 1\\}$, is created with `FiniteSet([[0], [1]])`. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.FiniteSet.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.finite_set)) | +| `NoConstraints` | No constraints - the whole $\mathbb{R}^{n}$ Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.NoConstraints.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.no_constraints)) | +| `Rectangle` | Rectangle, $$R = \\{u \in \mathbb{R}^{n_u} {}:{} f_{\min} \leq u \leq f_{\max}\\},$$ for example, `Rectangle(fmin, fmax)` Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Rectangle.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.rectangle)) | +| `SecondOrderCone` | Second-order aka "ice cream" aka "Lorenz" cone. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.SecondOrderCone.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.soc)) | +| `EpigraphSquaredNorm`| The epigraph of the squared Euclidean norm is a set of the form $X = \\{(z, t) \in \mathbb{R}^{n+1}: \Vert z \Vert \leq t\\}$. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.EpigraphSquaredNorm.html), Python: to be implemented) | +| `CartesianProduct` | Cartesian product of any of the above. See more information below. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.CartesianProduct.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.cartesian)) | +| `Zero` | The set $\\{0\\}$. Docs: ([Rust](https://docs.rs/optimization_engine/latest/optimization_engine/constraints/struct.Zero.html), [Python](https://alphaville.github.io/optimization-engine/api-dox/html/opengen.constraints.html#module-opengen.constraints.zero)) | @@ -424,7 +427,7 @@ Note here that the solver performed 6 outer [penalty-type iterations](https://en.wikipedia.org/wiki/Penalty_method) and 35 inner iterations overall. The infinity norm of the constraint violations is approximately $7.66\cdot 10^{-5}$ (which is below the -default tolerance of $10^{-4}$. This means that the solution $u^\star$ +default tolerance of $10^{-4}$.) This means that the solution $u^\star$ satisfies
diff --git a/open-codegen/CHANGELOG.md b/open-codegen/CHANGELOG.md index 1fb805ea..d2dcd3fe 100644 --- a/open-codegen/CHANGELOG.md +++ b/open-codegen/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Note: This is the Changelog file of `opengen` - the Python interface of OpEn +## [0.9.0] - 2024-08-15 + +### Added + +* Support for affine spaces in code generation + + ## [0.8.1] - 2024-07-17 ### Added @@ -193,6 +200,8 @@ Note: This is the Changelog file of `opengen` - the Python interface of OpEn * Project-specific `tcp_iface` TCP interface * Fixed `lbfgs` typo +[0.9.0]: https://github.com/alphaville/optimization-engine/compare/opengen-0.8.1...opengen-0.9.0 +[0.8.1]: https://github.com/alphaville/optimization-engine/compare/v0.9.0...opengen-0.8.1 [0.8.1]: https://github.com/alphaville/optimization-engine/compare/v0.9.0...opengen-0.8.1 [0.8.0]: https://github.com/alphaville/optimization-engine/compare/opengen-0.7.1...opengen-0.8.0 [0.7.1]: https://github.com/alphaville/optimization-engine/compare/opengen-0.7.0...opengen-0.7.1 From 218b2a37366edcf99b6162c28a1797eacae0958f Mon Sep 17 00:00:00 2001 From: Pantelis Sopasakis Date: Thu, 15 Aug 2024 16:33:44 +0100 Subject: [PATCH 5/6] [ci skip] VERSION: update version to 0.9.0 --- open-codegen/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open-codegen/VERSION b/open-codegen/VERSION index c18d72be..899f24fc 100644 --- a/open-codegen/VERSION +++ b/open-codegen/VERSION @@ -1 +1 @@ -0.8.1 \ No newline at end of file +0.9.0 \ No newline at end of file From 847fbf33c13bb61f832f951ad3745f8f1b749643 Mon Sep 17 00:00:00 2001 From: Pantelis Sopasakis Date: Thu, 15 Aug 2024 16:48:19 +0100 Subject: [PATCH 6/6] CHANGELOG: minor --- open-codegen/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/open-codegen/CHANGELOG.md b/open-codegen/CHANGELOG.md index d2dcd3fe..e637481f 100644 --- a/open-codegen/CHANGELOG.md +++ b/open-codegen/CHANGELOG.md @@ -11,7 +11,9 @@ Note: This is the Changelog file of `opengen` - the Python interface of OpEn ### Added -* Support for affine spaces in code generation +* Support for affine spaces in code generation (see `opengen.constraints.AffineSpace`) +* TCP solver status can be printed + ## [0.8.1] - 2024-07-17