Commits (565)
......@@ -3,16 +3,19 @@
# Working files
patch
fix_*.py
fix_*/
test_*.py
test_*/
/fix_*.py
/fix_*/
/test_*.py
/test_*/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.so
# profiling
*.cprof
# setuptools
build/
dist/
......@@ -26,8 +29,6 @@ pip-delete-this-directory.txt
target/
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
image: base/archlinux
# NOTE: python-setuptools is a missing dependency of python-coverage.
# NOTE: gcc, swig, which are build dependencies of swiglpk (via pip).
image: archlinux/base
stages:
- test
- coverage
- deploy
# ------------------------------------------------------------------------------
# Tests necessary for pipeline completion.
# ------------------------------------------------------------------------------
# Run production tests with Python 3.
testbench (py3):
stage: test
before_script:
# Install PICOS dependencies.
- pacman -Sy --noconfirm python-numpy python-cvxopt
# Install additional solvers.
- pacman -S --noconfirm python-pip glpk gcc
- >
pacman -Syu --noconfirm
gcc glpk python-coverage python-cvxopt python-numpy python-pip
python-setuptools swig which
- pip install swiglpk smcp
script:
- python ./test.py -vv -s cvxopt glpk smcp
- >
coverage run -p --source picos
./test.py -p -vv -s cvxopt glpk smcp
artifacts:
expire_in: 1 day
paths:
- .coverage.*
# Run production tests with Python 2.
testbench (py2):
stage: test
before_script:
# Install PICOS dependencies.
- pacman -Sy --noconfirm python2-numpy python2-cvxopt
# Install additional solvers.
- pacman -S --noconfirm python2-pip glpk gcc
- pip2 install swiglpk smcp
- >
pacman -Syu --noconfirm
gcc glpk python2-coverage python2-numpy python2-pip python2-setuptools
swig which
- pip2 install cvxopt swiglpk smcp
script:
- >
coverage2 run -p --source picos
./test.py -p -vv -s cvxopt glpk smcp
artifacts:
expire_in: 1 day
paths:
- .coverage.*
# Run doctests via PICOS' test runner.
doctests (py3):
stage: test
before_script:
- >
pacman -Syu --noconfirm
python-coverage python-cvxopt python-networkx python-numpy
python-setuptools
script:
- python2 ./test.py -vv -s cvxopt glpk smcp
- >
coverage run -p --source picos
./test.py -u -vv
artifacts:
expire_in: 1 day
paths:
- .coverage.*
doctest:
# Test-build the documentations.
# NOTE: "doctest" is built because there are still some leftover
# testcode/testoutput blocks that are not handled by test.py.
# NOTE: There is a bug that would require us to build "doctest" twice to also
# include documentation from the auto-generated API documentation but all
# these additional tests are already handled by "doctests (py3)".
documentation:
stage: test
before_script:
- pacman -Sy --noconfirm python-pip python-numpy python-cvxopt
- pacman -S --noconfirm m2r python-sphinx python-matplotlib python-networkx
- pip install sphinx-automodapi
- >
pacman -Syu --noconfirm
gcc git glpk graphviz make m2r python-cvxopt python-matplotlib python-networkx
python-numpy python-pip python-scipy python-sphinx python-sphinx_rtd_theme
texlive-most swig which
- pip install autoapi swiglpk
script:
- sphinx-build -b doctest doc doctest
- sphinx-build -W -b html doc html
- sphinx-build -W -b latex doc latex
- make -C latex
# Detect do-not-commit-this comments left in the code.
leftovers:
stage: test
before_script:
- pacman -Sy --noconfirm grep
script:
- (! grep -qr XXX picos)
# ------------------------------------------------------------------------------
# Compliance tests that are allowed to fail.
# ------------------------------------------------------------------------------
# Check (limited) PEP 8 and PEP 257 compliance.
style:
stage: test
before_script:
- pacman -Syu --noconfirm pylama
script:
- >
pylama
--linters pep8,pep257
--ignore D105,D203,D213,D401,E122,E128,E221,E271,E272,E501,E702,E741
picos tests
allow_failure: true
# Check line lengths.
linelength:
stage: test
before_script:
- pacman -Sy --noconfirm findutils grep
script:
- (! find picos tests -name '*.py' -print0|xargs -0 grep '^.\{81,\}$')
allow_failure: true
# ------------------------------------------------------------------------------
# Compute test coverage.
# ------------------------------------------------------------------------------
# Merge and report test coverage.
coverage:
stage: coverage
needs: [ # Run job early when all coverage results are available.
"testbench (py3)",
"testbench (py2)",
"doctests (py3)"]
dependencies: [ # Download exactly the coverage results.
"testbench (py3)",
"testbench (py2)",
"doctests (py3)"]
before_script:
- pacman -Syu --noconfirm python-coverage python-setuptools
script:
- coverage combine
- coverage report
artifacts:
expire_in: 1 year
name: coverage
paths:
- .coverage
# ------------------------------------------------------------------------------
# Deploy a release.
# ------------------------------------------------------------------------------
# Upload package to PyPI.
pypi:
stage: deploy
dependencies: [] # Don't download coverage reports.
before_script:
- pacman -Sy --noconfirm git twine
- pacman -Syu --noconfirm git twine
script:
- ./setup.py sdist
- twine upload --skip-existing dist/*
......@@ -46,11 +163,13 @@ pypi:
- master
- pypi
# Upload package to Anaconda.
anaconda:
stage: deploy
dependencies: [] # Don't download coverage reports.
before_script:
# Install Miniconda from the AUR.
- pacman -Sy --noconfirm wget fakeroot audit
- pacman -Syu --noconfirm audit fakeroot grep tar wget
- wget https://aur.archlinux.org/cgit/aur.git/snapshot/miniconda3.tar.gz
- tar xf miniconda3.tar.gz
- cd miniconda3
......@@ -66,16 +185,17 @@ anaconda:
- master
- conda
# Generate and publish the online documentation.
pages:
stage: deploy
dependencies: [] # Don't download coverage reports.
before_script:
# Install PICOS dependencies.
- pacman -Sy --noconfirm python-numpy python-cvxopt
# Install documentation built dependencies.
- pacman -S --noconfirm m2r python-sphinx python-matplotlib python-networkx
- pacman -S --noconfirm texlive-most python-sphinx_rtd_theme python-scipy
- pacman -S --noconfirm git python-pip glpk graphviz
- pip install sphinx-automodapi swiglpk
- >
pacman -Syu --noconfirm
gcc git glpk graphviz m2r python-cvxopt python-matplotlib python-networkx
python-numpy python-pip python-scipy python-sphinx python-sphinx_rtd_theme
texlive-most swig which
- pip install autoapi swiglpk
script:
- sphinx-build -b html doc html
- mkdir public
......@@ -87,4 +207,26 @@ pages:
- master
- doc
# Generate PDF versions of the documentation.
pdfdoc:
stage: deploy
dependencies: [] # Don't download coverage reports.
before_script:
- >
pacman -Syu --noconfirm
gcc git glpk graphviz make m2r python-cvxopt python-matplotlib python-networkx
python-numpy python-pip python-scipy python-sphinx python-sphinx_rtd_theme
texlive-most swig which
- pip install autoapi swiglpk
script:
- make -C doc latexpdf
- mv doc/build/latex/picos*.pdf .
artifacts:
name: picos-doc
paths:
- picos*.pdf
only:
- master
- pdfdoc
# vi:ts=2:et:ai
......@@ -3,6 +3,7 @@
This file documents major changes to PICOS.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[2.0]: https://gitlab.com/picos-api/picos/compare/v1.2.0...v2.0
[1.2.0]: https://gitlab.com/picos-api/picos/compare/v1.1.3...v1.2.0
[1.1.3]: https://gitlab.com/picos-api/picos/compare/v1.1.2...v1.1.3
[1.1.2]: https://gitlab.com/picos-api/picos/compare/v1.1.1...v1.1.2
......@@ -17,6 +18,209 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[0.1.0]: about:blank
## [2.0] - 2020-03-03
### Important
This is a major release featuring vast backend rewrites as well as interface
changes. Programs written for older versions of PICOS are expected to raise
deprecation warnings but should otherwise work as before. The following lists
notable exceptions:
- The solution returned by :meth:`~picos.Problem.solve` is now an instance of
the new :class:`~picos.Solution` class instead of a dictionary.
- If solution search fails to find an optimal primal solution, PICOS will now
raise a :class:`~picos.SolutionFailure` by default. Old behavior of not
raising an exception is achieved by setting ``primals=None`` (see
:ref:`primals <option_primals>` and :ref:`duals <option_duals>` options).
- The definition of the :math:`L_{p,q}`-norm has changed: It no longer refers
to the :math:`p`-norm of the :math:`q`-norms of the matrix rows but to the
:math:`q`-norm of the :math:`p`-norms of the matrix columns. This matches
the definition you would find
[on Wikipedia](https://en.wikipedia.org/wiki/Matrix_norm#L2,1_and_Lp,q_norms)
and should reduce confusion for new users. See :class:`~picos.Norm`.
- The signs in the Lagrange dual problem of a conic problem are now more
consistent for all cones, see :ref:`duals`. In particular the signs of dual
values for (rotated) second order conic constraints have changed and the
problem obtained by :attr:`Problem.dual <picos.Problem.dual>` (new for
:meth:`~picos.Problem.as_dual`) has a different (but equivalent) form.
### Added
- A modular problem reformulation framework. Before selecting a solver, PICOS
now builds a map of problem types that your problem can be reformulated to
and makes a choice based on the expected complexity of the reposed problem.
- An object oriented interface to solution search options. See
:class:`~picos.Options`.
- Support for arbitrary objective functions via an epigraph reformulation.
- Support for MOSEK 9.
- Support for ECOS 2.0.7.
- Support for multiple subsystems with :func:`~picos.partial_trace`.
- Quick-solve functions :func:`picos.minimize` and :func:`picos.maximize`.
- Lower and upper diagonal matrix variable types.
- :class:`~picos.SecondOrderCone` and :class:`~picos.RotatedSecondOrderCone`
sets to explicitly create the associated constraints. *(You now need to use
these if you want to obtain a conic instead of a quadratic dual.)*
- Possibility to use :func:`picos.sum` to sum over the elements of a single
multidimensional expression.
- Possibility to create a :class:`~picos.Ball` or :class:`~picos.Simplex` with a
non-constant radius.
- Many new properties (postfix operations) to work with affine expressions; for
instance ``A.vec`` is a faster and cached way to express the vectorization
``A[:]``. See :class:`~picos.expressions.ComplexAffineExpression`.
- Options :ref:`assume_conic <option_assume_conic>` and
:ref:`verify_prediction <option_verify_prediction>`.
- An option for every solver to manipulate the chances of it being selected
(e.g. :ref:`penalty_cvxopt <option_penalty_cvxopt>`).
- Ability to run doctests via ``test.py``.
### Fixed
The following are issues that were fixed in an effort of their own. If a bug is
not listed here, it might still be fixed as a side effect of some of the large
scale code rewrites that this release ships.
- Upgrading the PyPI package via pip.
- A regression that rendered the Kronecker product unusable.
- Noisy exception handling in a sparse matrix helper function.
- Shape detection for matrices given by string.
- The :ref:`hotstart <option_hotstart>` option when solving with CPLEX.
- Low precision QCP duals from Gurobi.
### Changed
- All algebraic expression code has been rewritten and organized in a new
:mod:`~picos.expressions` package. In particular, real and complex expressions
are distinguished more clearly.
- All algebraic expressions are now immutable.
- The result of any unary operation on algebraic expressions (e.g. negation,
transposition) is cached (only computed once per expression).
- Slicing of affine expressions is more powerful, see :ref:`slicing`.
- Loading of constant numeric data has been unified, see
:func:`~picos.expressions.data.load_data`.
- Variables are now created independently of problems by instanciating one of
the new :mod:`variable types <picos.expressions.variables>`.
*(*:meth:`Problem.add_variable <picos.Problem.add_variable>` *is deprecated.)*
- Constraints are added to problems as they are; any transformation is done
transparently during solution search.
- In particular, :math:`x^2 \leq yz` is now initially a (nonconvex) quadratic
constraint and transformation to a conic constraint is controlled by the new
:ref:`assume_conic <option_assume_conic>` option.
- Expressions constrained to be positive semidefinite are now required to be
symmetric/hermitian by their own definition. *(Use*
:class:`~picos.SymmetricVariable` *or* :class:`~picos.HermitianVariable`
*whenever applicable!)*
- Options passed to :meth:`~picos.Problem.solve` are only used for that
particular search.
- The default value for the :ref:`verbosity <option_verbosity>` option (formerly
``verbose``) is now :math:`0`.
- Available solvers are only imported when they are actually being used, which
speeds up import of PICOS on platforms with many solvers installed.
- The code obeys PEP 8 and PEP 257 more strongly. Exceptions: D105, D203, D213,
D401, E122, E128, E221, E271, E272, E501, E702, E741.
- Production testing code was moved out of the :mod:`picos` package.
### Removed
- The ``NoAppropriateSolverError`` exception that was previously raised by
:meth:`~picos.Problem.solve`. This is replaced by the new
:class:`~picos.SolutionFailure` exception with error code :math:`1`.
- Some public functions in the :mod:`~picos.tools` module that were originally
meant for internal use.
### Deprecated
This section lists deprecated modules, functions and options with their
respective replacement or deprecation reason on the right hand side.
Deprecated entities produce a warning and will be removed in a future release.
- The :mod:`~picos.tools` module as a whole. It previously contained both
algebraic functions for the user as well as functions meant for internal use.
The former group of functions can now be imported directly from the
:mod:`picos` namespace (though some are also individually deprecated). The
other functions were either relocated (but can still be imported from
:mod:`~picos.tools` while it lasts) or removed.
- In the :class:`~picos.Problem` class:
- :meth:`~picos.Problem.add_variable`,
:meth:`~picos.Problem.remove_variable`,
:meth:`~picos.Problem.set_var_value`
→ variables are instanciated directly and added to problems automatically
- :meth:`~picos.Problem.minimize` → :func:`picos.minimize`
- :meth:`~picos.Problem.maximize` → :func:`picos.maximize`
- :meth:`~picos.Problem.set_option`
→ assign to attributes or items of :attr:`Problem.options <picos.Options>`
- :meth:`~picos.Problem.update_options`
→ :meth:`options.update <picos.Options.update>`
- :meth:`~picos.Problem.set_all_options_to_default`
→ :meth:`options.reset <picos.Options.reset>`
- :meth:`~picos.Problem.obj_value` → :attr:`~picos.Problem.value`
- :meth:`~picos.Problem.is_continuous` → :attr:`~picos.Problem.continuous`
- :meth:`~picos.Problem.is_pure_integer` → :attr:`~picos.Problem.pure_integer`
- :meth:`~picos.Problem.verbosity`
→ :ref:`options.verbosity <option_verbosity>`
- :meth:`~picos.Problem.as_dual` → :attr:`~picos.Problem.dual`
- :meth:`~picos.Problem.countVar`,
:meth:`~picos.Problem.countCons`,
:meth:`~picos.Problem.numberOfVars`,
:meth:`~picos.Problem.numberLSEConstraints`,
:meth:`~picos.Problem.numberSDPConstraints`,
:meth:`~picos.Problem.numberQuadConstraints`,
:meth:`~picos.Problem.numberConeConstraints`
→ were meant for internal use
- arguments ``it``, ``indices`` and ``key`` to
:meth:`~picos.Problem.add_list_of_constraints` → are ignored
- All expression types:
- constraint creation via ``<````<=``
- constraint creation via ``>````>=``
- :meth:`~picos.expressions.Expression.is_valued`
→ :attr:`~picos.expressions.Expression.valued`
- :meth:`~picos.expressions.Expression.set_value`
→ assign to :attr:`~picos.expressions.Expression.value`
- Affine expressions:
- :meth:`~picos.expressions.ComplexAffineExpression.fromScalar`
→ :meth:`~picos.expressions.ComplexAffineExpression.from_constant`
or :func:`picos.Constant`
- :meth:`~picos.expressions.ComplexAffineExpression.fromMatrix`
→ :meth:`~picos.expressions.ComplexAffineExpression.from_constant`
or :func:`picos.Constant`
- :meth:`~picos.expressions.ComplexAffineExpression.hadamard```^``
- :meth:`~picos.expressions.ComplexAffineExpression.isconstant`
→ :meth:`~picos.expressions.ComplexAffineExpression.constant`
- :meth:`~picos.expressions.ComplexAffineExpression.same_as`
→ :meth:`~picos.expressions.ComplexAffineExpression.equals`
- :meth:`~picos.expressions.ComplexAffineExpression.transpose`
→ :attr:`~picos.expressions.ComplexAffineExpression.T`
- :attr:`~picos.expressions.ComplexAffineExpression.Tx`
→ :meth:`~picos.expressions.ComplexAffineExpression.partial_transpose`
- :meth:`~picos.expressions.ComplexAffineExpression.conjugate`
→ :attr:`~picos.expressions.ComplexAffineExpression.conj`
- :meth:`~picos.expressions.ComplexAffineExpression.Htranspose`
→ :attr:`~picos.expressions.ComplexAffineExpression.H`
- :meth:`~picos.expressions.ComplexAffineExpression.copy`
→ expressions are immutable
- :meth:`~picos.expressions.ComplexAffineExpression.soft_copy`
→ expressions are immutable
- Algebraic functions and shorthands in the ``picos`` namespace:
- :func:`~picos.tracepow` → :class:`~picos.PowerTrace`
- :func:`~picos.new_param` → :func:`~picos.Constant`
- :func:`~picos.flow_Constraint` → :class:`~picos.FlowConstraint`
- :func:`~picos.diag_vect` → :func:`~picos.maindiag`
- :func:`~picos.simplex` → :class:`~picos.Simplex`
- :func:`~picos.truncated_simplex` → :class:`~picos.Simplex`
- arguments ``it`` and ``indices`` to :func:`~picos.sum` → are ignored
- Solution search options:
- ``allow_license_warnings``
→ :ref:`license_warnings <option_license_warnings>`
- ``verbose`` → :ref:`verbosity <option_verbosity>` (takes an integer)
- ``noprimals`` → :ref:`primals <option_primals>` (the meaning is inverted)
- ``noduals`` → :ref:`duals <option_duals>` (the meaning is inverted)
- ``tol````*_fsb_tol`` and ``*_ipm_opt_tol``
- ``gaplim`` → :ref:`rel_bnb_opt_tol <option_rel_bnb_opt_tol>`
- ``maxit`` → :ref:`max_iterations <option_max_iterations>`
- ``nbsol`` → :ref:`max_fsb_nodes <option_max_fsb_nodes>`
- ``pool_relgap`` → :ref:`pool_rel_gap <option_pool_rel_gap>`
- ``pool_absgap`` → :ref:`pool_abs_gap <option_pool_abs_gap>`
- ``lboundlimit`` → :ref:`cplex_lwr_bnd_limit <option_cplex_lwr_bnd_limit>`
- ``uboundlimit`` → :ref:`cplex_upr_bnd_limit <option_cplex_upr_bnd_limit>`
- ``boundMonitor`` → :ref:`cplex_bnd_monitor <option_cplex_bnd_monitor>`
- ``solve_via_dual`` → :ref:`dualize <option_dualize>` (may not be :obj:`None`
any more)
## [1.2.0] - 2019-01-11
### Important
......@@ -54,8 +258,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
always return the constraints
passed to them.
- :func:`add_list_of_constraints <picos.Problem.add_list_of_constraints>`
and :func:`picos.sum <picos.tools.sum>` find a short string representation
automatically.
and :func:`picos.sum` find a short string representation automatically.
### Removed
- The old production testing script.
......@@ -91,8 +294,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Test bench execution is automated for greater code stability.
- Improved test bench output.
- Improved support for the SDPA solver.
- :func:`partial_trace <picos.tools.partial_trace>` can handle rectangular
subsystems.
- :func:`~picos.partial_trace` can handle rectangular subsystems.
- The documentation was restructured; examples were converted to Python 3.
### Fixed
......@@ -105,8 +307,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [1.1.2] - 2016-07-04
### Added
- Ability to dynamically add and remove constraints, see
:ref:`the documentation on constraint deletion <delcons>`.
- Ability to dynamically add and remove constraints.
- Option ``pass_simple_cons_as_bound``, see below.
### Changed
......@@ -114,8 +315,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Improved support for the SDPA solver.
- :func:`add_constraint <picos.Problem.add_constraint>` returns a handle to the
constraint when the option `return_constraints` is set.
- New signature for the function
:func:`partial_transpose <picos.tools.partial_transpose>`, which can now
- New signature for the function :func:`~picos.partial_transpose`, which can now
transpose arbitrary subsystems from a kronecker product.
- PICOS no longer turns constraints into variable bounds, unless the new option
``pass_simple_cons_as_bound`` is enabled.
......@@ -129,7 +329,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Support for the SDPA solver.
- Partial trace of an affine expression, see
:func:`partial_trace <picos.tools.partial_trace>`.
:func:`~picos.partial_trace`.
### Changed
- Improved PEP 8 compliance.
......@@ -153,35 +353,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Ability to read and write problems in
[conic benchmark format](http://cblib.zib.de/).
- Support for inequalities involving the sum of the :math:`k` largest or
smallest elements of an affine expression, see
:func:`sum_k_largest <picos.tools.sum_k_largest>` and
:func:`sum_k_smallest <picos.tools.sum_k_smallest>`.
smallest elements of an affine expression, see :func:`~picos.sum_k_largest`
and :func:`~picos.sum_k_smallest`.
- Support for inequalities involving the sum of the :math:`k` largest or
smallest eigenvalues of a symmetric matrix, see
:func:`sum_k_largest_lambda <picos.tools.sum_k_largest_lambda>`,
:func:`sum_k_smallest_lambda <picos.tools.sum_k_smallest_lambda>`,
:func:`lambda_max <picos.tools.lambda_max>` and
:func:`lambda_min <picos.tools.lambda_min>`.
:func:`~picos.sum_k_largest_lambda`, :func:`~picos.sum_k_smallest_lambda`,
:func:`~picos.lambda_max` and :func:`~picos.lambda_min`.
- Support for inequalities involving the :math:`L_{p,q}`-norm of an affine
expression, see :func:`norm <picos.tools.norm>`.
expression, see :func:`~picos.norm`.
- Support for equalities involving complex coefficients.
- New :attr:`variable type <picos.expressions.Variable.vtype>` for antisymmetric
matrix variables: ``antisym``.
- Support for antisymmetric matrix variables.
- Set expressions that affine expressions can be constrained to be an element
of, see :func:`ball <picos.tools.ball>`, :func:`simplex <picos.tools.simplex>`
and :func:`truncated_simplex <picos.tools.truncated_simplex>`.
of, see :func:`~picos.ball`, :func:`~picos.simplex` and
:func:`~picos.truncated_simplex`.
- Shorthand functions :func:`maximize <picos.Problem.maximize>` and
:func:`minimize <picos.Problem.minimize>` to specify the objective function of
a problem and solve it.
- Hadamard (elementwise) product of affine expression, as an overload of the
``^`` operator, read :ref:`the tutorial on overloads <overloads>`.
- Partial transposition of an aAffine Expression, see
:func:`partial_transpose <picos.tools.partial_transpose>` and
:attr:`AffinExp.Tx <picos.expressions.AffinExp.Tx>`.
:func:`~picos.partial_transpose`.
### Changed
- Improved efficiency of the sparse SDPA file format writer.
- Improved efficiency of :func:`to_real <picos.Problem.as_real>`.
- Improved efficiency of the complex to real transformation.
### Fixed
- Scalar product of hermitian matrices.
......@@ -195,15 +390,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
:ref:`the documentation on complex problems <complex>`.
- Helper function to input (multicommodity) graph flow problems, see
:ref:`the tutorial on flow constraints <flowcons>`.
- Additional ``coef`` argument to :func:`tracepow <picos.tools.tracepow>`, to
represent constraints of the form
:math:`\operatorname{trace}(M X^p) \geq t`.
- Additional argument to :func:`~picos.tracepow`, to represent constraints
of the form :math:`\operatorname{trace}(M X^p) \geq t`.
### Changed
- Significantly improved slicing performance for
:class:`affine expressions <picos.expressions.AffinExp>`.
- Improved performance of
:func:`retrieve_matrix <picos.tools.retrieve_matrix>`.
- Significantly improved slicing performance for affine expressions.
- Improved performance when loading data.
- Improved performance when retrieving primal solution from CPLEX.
- The documentation received an overhaul.
......@@ -212,17 +404,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Ability to express rational powers of affine expressions with the ``**``
operator, traces of matrix powers with
:func:`picos.tracepow <picos.tools.tracepow>`, (generalized) p-norms with
:func:`picos.norm <picos.tools.norm>` and :math:`n`-th roots of a determinant
with :func:`picos.detrootn <picos.tools.detrootn>`.
operator, traces of matrix powers with :func:`~picos.tracepow`,
(generalized) p-norms with :func:`~picos.norm` and :math:`n`-th roots of a
determinant with :func:`~picos.detrootn`.
- Ability to specify variable bounds directly rather than by adding constraints,
see :func:`add_variable <picos.Problem.add_variable>`,
:func:`set_lower() <picos.expressions.Variable.set_lower>`,
:func:`set_upper() <picos.expressions.Variable.set_upper>`,
:func:`set_sparse_lower() <picos.expressions.Variable.set_sparse_lower>` and
:func:`set_sparse_upper() <picos.expressions.Variable.set_sparse_upper>`.
- Problem dualization, see :func:`dualize <picos.Problem.as_dual>`.
see :func:`add_variable <picos.Problem.add_variable>`.
- Problem dualization.
- Option ``solve_via_dual`` which controls passing the dual problem to the
solver instead of the primal problem. This can result in a significant
speedup for certain problems.
......@@ -242,8 +429,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.1.3] - 2013-04-17
### Added
- A :func:`geomean <picos.tools.geomean>` function to construct geometric mean
inequalities that will be cast as SOCP constraints.
- A :func:`~picos.geomean` function to construct geometric mean inequalities
that will be cast as rotated second order cone constraints.
- Options ``uboundlimit`` and ``lboundlimit`` to tell CPLEX to stop the search
as soon as the given threshold is reached for the upper and lower bound,
respectively.
......
......@@ -44,7 +44,7 @@ with PICOS:
>>> x = P.add_variable("x", 2, vtype="integer")
>>> C = P.add_constraint(x <= 5.5)
>>> P.set_objective("max", 1|x) # 1|x is the sum over x
>>> solution = P.solve(verbose = 0)
>>> solution = P.solve()
>>> print(solution["status"])
'integer optimal solution'
>>> print(P.obj_value())
......@@ -59,9 +59,13 @@ with PICOS:
### Documentation & Source
The full documentation can be found [here](https://picos-api.gitlab.io/picos/).
The source code lives on [GitLab](https://gitlab.com/picos-api/picos).
The page you are reading is featured in both places.
- The full documentation can be browsed
[online](https://picos-api.gitlab.io/picos/)
or downloaded
[in PDF form](https://gitlab.com/picos-api/picos/-/jobs/artifacts/master/raw/picos.pdf?job=pdfdoc).
- The API documentation without the tutorial and examples is also available as a
[separate PDF](https://gitlab.com/picos-api/picos/-/jobs/artifacts/master/raw/picos-api.pdf?job=pdfdoc).
- The source code lives on [GitLab](https://gitlab.com/picos-api/picos).
Installation
------------
......
python:
- 2.7
- 3.6
- 3.7
- 3.8
# vi:ts=2:et:ai
about:
description: "A python interface to conic optimization solvers."
home: https://gitlab.com/picos-api/picos
license: GPL-3.0
package:
name: picos
version: {{ load_setup_py_data().version }}
......@@ -28,4 +23,9 @@ test:
imports:
- picos
about:
description: "A python interface to conic optimization solvers."
home: https://gitlab.com/picos-api/picos
license: GPL-3.0
# vi:ts=2:et:ai
build/
automodapi/
api/
*.xcf
......@@ -6,6 +6,7 @@ SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
AUTOGENDIR = api
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
......@@ -47,7 +48,8 @@ help:
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
rm -rf $(BUILDDIR)
rm -rf $(AUTOGENDIR)
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
......
.wy-table-responsive table td {
white-space: normal !important;
}
{# THEMODULE #}
{{ node.name }}
{{ '=' * node.name|length }}
.. automodule:: {{ node.name }}
:no-special-members:
{# SET CURRENT MODULE #}
.. currentmodule:: {{ node.name }}
{# CONTENT #}
{%- block content -%}
{%- if node.exceptions or node.classes or node.functions or node.variables %}
Outline
-------
{%- if node.classes %}
Classes
^^^^^^^
.. list-table::
:widths: 25 75
{% for item, obj in node.classes.items() %}
* - :py:class:`{{ item }}`
- {{ obj|summary }}
{%- endfor -%}
{%- endif -%}
{%- if node.functions %}
Functions
^^^^^^^^^
.. list-table::
:widths: 25 75
{% for item, obj in node.functions.items() %}
* - :py:func:`{{ item }}`
- {{ obj|summary }}
{%- endfor -%}
{%- endif -%}
{% if node.exceptions %}
Exceptions
^^^^^^^^^^
.. list-table::
:widths: 25 75
{% for item, obj in node.exceptions.items() %}
* - :py:exc:`{{ item }}`
- {{ obj|summary }}
{%- endfor -%}
{%- endif -%}
{%- if node.variables %}
Data
^^^^
.. hlist::
:columns: 4
{% for item, obj in node.variables.items() %}
- :py:data:`{{ item }}`
{%- endfor -%}
{%- endif -%}
{%- endif %}
{%- if subnodes %}
Submodules
^^^^^^^^^^
.. list-table::
:widths: 25 75
{% for subnode in subnodes %}
* - :py:mod:`{{ subnode.name }}`
- {{ subnode.module|summary }}
{%- endfor %}
{%- endif -%}
{%- endblock -%}
{# CLASSES #}
{%- block classes -%}
{%- if node.classes %}
Classes
-------
{% for item in node.classes %}
{{ item }}
{{ '^' * item|length }}
.. autoclass:: {{ item }}
:members:
:undoc-members:
{% endfor -%}
{%- endif -%}
{%- endblock -%}
{# FUNCTIONS #}
{%- block functions -%}
{%- if node.functions %}
Functions
---------
{% for item in node.functions %}
{{ item }}
{{ '^' * item|length }}
.. autofunction:: {{ item }}
{% endfor -%}
{%- endif -%}
{%- endblock -%}
{# EXCEPTIONS #}
{%- block exceptions -%}
{%- if node.exceptions %}
Exceptions
----------
{% for item in node.exceptions %}
{{ item }}
{{ '^' * item|length }}
.. autoexception:: {{ item }}
{% endfor -%}
{%- endif -%}
{%- endblock -%}
{# DATA #}
{%- block variables -%}
{%- if node.variables %}
Data
----
{% for item, obj in node.variables.items() %}
.. autodata:: {{ item }}
:annotation:
{% endfor -%}
{%- endif -%}
{%- endblock -%}
......@@ -3,45 +3,38 @@
API Reference
=============
.. rubric:: Basic interface
To use PICOS to its full extend you just need to know about the two components
below.
.. toctree::
:maxdepth: 3
api/problem.rst
api/tools.rst
.. rubric:: Generated expressions and constraints
When you use the basic interface above, PICOS creates mathematical expressions
and constraints involving your variables and data. The following sections
describe these objects.
.. toctree::
:maxdepth: 3
api/expressions.rst
api/constraints.rst
.. rubric:: Customizing PICOS
The following components allow you to fine-tune the behavior of PICOS.
PICOS is organized in a number of submodules and subpackages, most of which you
do not need to access directly when solving optimization problems. It is usually
sufficient to ``import picos`` and use the functions and classes provided in the
:mod:`picos` namespace.
.. toctree::
:maxdepth: 3
api/glyphs.rst
.. rubric:: Internal Gears
You don't usually come in direct contact with the classes and functions below,
but if you like to poke around or :ref:`contribute to PICOS <contributing>` we
got you covered!
:maxdepth: 1
api/picos
api/picos.apidoc
api/picos.caching
api/picos.compat
api/picos.constraints
api/picos.containers
api/picos.expressions
api/picos.formatting
api/picos.glyphs
api/picos.legacy
api/picos.modeling
api/picos.reforms
api/picos.solvers
api/picos.tools
More
----
Modules below the second level are not listed here but can be found in the
sidebar to your left. Often these modules define a single class which is also
mirrored in one of the namespaces above.
.. toctree::
:maxdepth: 3
:hidden:
:glob:
api/solvers.rst
api/picos.*.*
.. _constraints:
The Constraints package
=======================
.. automodapi:: picos.constraints
:no-heading:
:headings: =-
.. _expression:
The Expressions module
======================
.. automodule:: picos.expressions
.. _glyphs:
The Glyphs module
=================
.. automodule:: picos.glyphs
.. _problem:
The Problem class
=================
The :class:`Problem <picos.Problem>` class represents your optimization problem
and is your main way of interfacing PICOS. After you create a problem instance,
you can add variables to it via :meth:`add_variable
<picos.Problem.add_variable>` and use standard Python algebraic operators
(:ref:`cheatsheet`) and algebraic functions (:ref:`tools`) to create expressions
and constraints involving these variables.
.. autoclass:: picos.Problem
.. _solvers:
The Solvers package
===================
.. automodapi:: picos.solvers
:no-heading:
:headings: =-
.. _tools:
The Tools module
================
Many of the tools, in particular the algebraic functions, are also available
in the ``picos`` namespace. For example, you can write :func:`picos.sum
<picos.tools.sum>` instead of :func:`picos.tools.sum <picos.tools.sum>`.
In the future, we are looking to split the toolbox into mutltiple modules, so
that it is clear which of the functions are imported into the ``picos``
namespace.
.. automodule:: picos.tools
.. warning::
This part of the documentation has not been touched for a while. It might
be incomplete, reference deprecated functions or make a claim that does not
apply to the latest version of PICOS any more. On the bright side, code
listings are validated and still work. Watch your step!
.. _cheatsheet:
Cheat Sheet
......@@ -19,6 +27,8 @@ Manipulate expressions
+--------------+--------------------------------+
| ``^`` | Hadamard (elementwise) product |
+--------------+--------------------------------+
| ``@`` | Kronecker product (Python 3) |
+--------------+--------------------------------+
| ``|`` | scalar product |
+--------------+--------------------------------+
| ``/`` | division |
......@@ -68,91 +78,72 @@ Create constraints
Create affine expressions
-------------------------
+--------------------------------------------------------------+-------------------------------------------+
| **function** | **short doc** |
+==============================================================+===========================================+
|:func:`sum() <picos.tools.sum>` | sums a list of affine expressions |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`diag() <picos.tools.diag>` | diagonal matrix defined by its diagonal |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`diag_vect() <picos.tools.diag_vect>` | vector of diagonal elements of a matrix |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`new_param() <picos.tools.new_param>` | constant affine expression |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`trace() <picos.tools.trace>` | trace of a square affine expression |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`lowtri() <picos.tools.lowtri>` | vector of lower triangular elements |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`partial_transpose() <picos.tools.partial_transpose>` | partial transposition |
+--------------------------------------------------------------+-------------------------------------------+
|:func:`partial_trace() <picos.tools.partial_trace>` | partial trace |
+--------------------------------------------------------------+-------------------------------------------+
+---------------------------------+-------------------------------------------+
| **function** | **short doc** |
+=================================+===========================================+
|:func:`~picos.sum` | sums a list of affine expressions |
+---------------------------------+-------------------------------------------+
|:func:`~picos.diag` | diagonal matrix defined by its diagonal |
+---------------------------------+-------------------------------------------+
|:func:`~picos.diag_vect` | vector of diagonal elements of a matrix |
+---------------------------------+-------------------------------------------+
|:func:`~picos.new_param` | constant affine expression |
+---------------------------------+-------------------------------------------+
|:func:`~picos.trace` | trace of a square affine expression |
+---------------------------------+-------------------------------------------+
|:func:`~picos.partial_transpose` | partial transposition |
+---------------------------------+-------------------------------------------+
|:func:`~picos.partial_trace` | partial trace |
+---------------------------------+-------------------------------------------+
Create convex expressions
-------------------------
+-------------------------------------------------------------------+-----------------------------------------+
| **function** | **short doc** |
+===================================================================+=========================================+
|:func:`geomean() <picos.tools.geomean>` | geometric mean |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`norm() <picos.tools.norm>` | (generalized) :math:`L_p-` norm |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`tracepow() <picos.tools.tracepow>` | trace of a *p*-th matrix power |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`detrootn() <picos.tools.detrootn>` | *n*-th root of determinant |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`sum_k_largest() <picos.tools.sum_k_largest>` | sum of k largest elements |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`sum_k_smallest() <picos.tools.sum_k_smallest>` | sum of k smallest elements |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`sum_k_largest_lambda() <picos.tools.sum_k_largest_lambda>` | sum of k largest eigenvalues |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`sum_k_smallest_lambda() <picos.tools.sum_k_smallest_lambda>`| sum of k smallest eigenvalues |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`lambda_max() <picos.tools.lambda_max>` | largest eigenvalue |
+-------------------------------------------------------------------+-----------------------------------------+
|:func:`lambda_min() <picos.tools.lambda_min>` | smallest eigenvalue |
+-------------------------------------------------------------------+-----------------------------------------+
+-------------------------------------+-----------------------------------------+
| **function** | **short doc** |
+=====================================+=========================================+
|:func:`~picos.geomean` | geometric mean |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.norm` | (generalized) :math:`L_p-` norm |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.tracepow` | trace of a *p*-th matrix power |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.detrootn` | *n*-th root of determinant |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.sum_k_largest` | sum of k largest elements |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.sum_k_smallest` | sum of k smallest elements |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.sum_k_largest_lambda` | sum of k largest eigenvalues |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.sum_k_smallest_lambda` | sum of k smallest eigenvalues |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.lambda_max` | largest eigenvalue |
+-------------------------------------+-----------------------------------------+
|:func:`~picos.lambda_min` | smallest eigenvalue |
+-------------------------------------+-----------------------------------------+
Create sets
-----------
+-------------------------------------------------------------+--------------------------------------------------------------------+
| **function** | **short doc** |
+=============================================================+====================================================================+
|:func:`ball(r,p) <picos.tools.ball>` | a :math:`L_p`- ball of radius ``r`` |
+-------------------------------------------------------------+--------------------------------------------------------------------+
|:func:`simplex(a) <picos.tools.simplex>` | a standard simplex |
| | :math:`\{x\geq 0: \Vert x \Vert_1 \leq a \}` |
+-------------------------------------------------------------+--------------------------------------------------------------------+
|:func:`truncated_simplex(a) <picos.tools.truncated_simplex>` | a set of the form |
| | :math:`\{ 0\leq x\leq 1: \Vert x \Vert_1 \leq a\}`, or |
| | :math:`\{x: \Vert x \Vert_\infty \leq 1; \Vert x \Vert_1 \leq a\}` |
+-------------------------------------------------------------+--------------------------------------------------------------------+
Other useful functions
----------------------
Transform a problem
~~~~~~~~~~~~~~~~~~~
+-------------------------------------------------------------------+------------------------------------------------------+
| **function** | **short doc** |
+===================================================================+======================================================+
|:func:`convert_quad_to_socp() <picos.Problem.convert_quad_to_socp>`| replaces quadratic constraints by |
| | equivalent second order cone constraints |
+-------------------------------------------------------------------+------------------------------------------------------+
|:func:`as_real() <picos.Problem.as_real>` | transform complex SDP to equivalent real-valued SDP |
+-------------------------------------------------------------------+------------------------------------------------------+
|:func:`as_dual() <picos.Problem.as_dual>` | returns Lagrangian dual of a problem |
+-------------------------------------------------------------------+------------------------------------------------------+
+-------------------------------------------------------+--------------------------------------------------------------------+
| **function** | **short doc** |
+=======================================================+====================================================================+
|:func:`ball(r,p) <picos.ball>` | a :math:`L_p`- ball of radius ``r`` |
+-------------------------------------------------------+--------------------------------------------------------------------+
|:func:`simplex(a) <picos.simplex>` | a standard simplex |
| | :math:`\{x\geq 0: \Vert x \Vert_1 \leq a \}` |
+-------------------------------------------------------+--------------------------------------------------------------------+
|:func:`truncated_simplex(a) <picos.truncated_simplex>` | a set of the form |
| | :math:`\{ 0\leq x\leq 1: \Vert x \Vert_1 \leq a\}`, or |
| | :math:`\{x: \Vert x \Vert_\infty \leq 1; \Vert x \Vert_1 \leq a\}` |
+-------------------------------------------------------+--------------------------------------------------------------------+
Get information on a problem
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------------------------------------------------------------+-------------------------------------------+
| **function** | **short doc** |
| **function** | **short doc** |
+=========================================================================================+===========================================+
|:func:`get_variable(name) <picos.Problem.get_variable>` | gets the variable object ``name`` |
+-----------------------------------------------------------------------------------------+-------------------------------------------+
......@@ -168,15 +159,12 @@ Get information on a problem
Miscellaneous
~~~~~~~~~~~~~
+-------------------------------------------------------------+-------------------------------------------+
| **function** | **short doc** |
+=============================================================+===========================================+
|:func:`available_solvers() <picos.solvers.available_solvers>`| lists installed solvers |
+-------------------------------------------------------------+-------------------------------------------+
|:func:`import_cbf() <picos.tools.import_cbf>` | imports data from a .cbf file |
+-------------------------------------------------------------+-------------------------------------------+
|:func:`eval_dict() <picos.tools.eval_dict>` | evaluates a dictionary of picos variables |
| | (after a problem has been solved) |
+-------------------------------------------------------------+-------------------------------------------+
| :func:`write_to_file() <picos.Problem.write_to_file>` | writes problem to a file |
+-------------------------------------------------------------+-------------------------------------------+
+-------------------------------------------------------+-------------------------------------------+
| **function** | **short doc** |
+=======================================================+===========================================+
|:func:`available_solvers() <picos.available_solvers>` | lists installed solvers |
+-------------------------------------------------------+-------------------------------------------+
|:func:`import_cbf() <picos.import_cbf>` | imports data from a .cbf file |
+-------------------------------------------------------+-------------------------------------------+
| :func:`write_to_file() <picos.Problem.write_to_file>` | writes problem to a file |
+-------------------------------------------------------+-------------------------------------------+
.. TODO: Replace all testcode/testoutput blocks with interactive listings so
.. that test.py can validate the examples.
.. _complex:
Complex Semidefinite Programming
================================
Since the version 1.0.1, it is possible to
do complex semidefinite programming with Picos.
This extension of semidefinite programming to
the complex domain was introduced by Goemans and Williamson :ref:`[1] <complex_refs>`
as relaxtions of combinatorial optimization problems, and
has applications
e.g. in Quantum Information Theory :ref:`[2] <complex_refs>`, or
for the phase recovery problem in signal processing :ref:`[3] <complex_refs>`.
To handle complex SDPs in Picos, we have introduced two new variable types: ``'complex'``
and ``'hermitian'``. A complex variable can be created as follows:
>>> import picos as pic
>>> import cvxopt as cvx
>>> P = pic.Problem()
>>> Z = P.add_variable('Z',(3,2),'complex')
it automatically creates two variables called ``Z_RE`` and ``Z_IM`` which contains the
real and imaginary part of ``Z``, and that be accessed by using the ``real`` and ``imag`` properties:
>>> Z.real
<3×2 Continuous Variable: Z_RE>
>>> Z.imag
<3×2 Continuous Variable: Z_IM>
>>> Z.vtype
'complex'
The python variable ``Z`` contains an affine expression equal to ``Z_RE + 1j * Z_IM``,
and that can be used to easily define a complex SDP.
The variable type ``'hermitian'`` can be used to create a complex variable that is forced to be Hermitian.
The following properties can now be used with every affine expression: ``conj`` (complex conjugate),
``real`` (real part, i.e. ``exp.real`` returns ``0.5 * (exp+exp.conj)`` ),
``imag`` (imaginary part, i.e. ``exp.imag`` returns ``-0.5 * 1j * (exp-exp.conj)`` ),
anf ``H`` (Hermitian transposition, i.e. ``exp.H`` returns ``exp.conj.T`` ).
>>> X = P.add_variable('X',(3,3),'hermitian')
>>> X >> 0
<3×3 LMI Constraint: X ≽ 0>
PICOS supports complex semidefinite programming as of version 1.0.1. It was
overhauled in version 2.0 to provide some of the features showcased below.
This extension of semidefinite programming to the complex domain was introduced
by Goemans and Williamson :ref:`[1] <complex_refs>` in order to pose relaxations
of combinatorial optimization problems.
Applications include quantum information theory :ref:`[2] <complex_refs>` and
the phase recovery problem in signal processing :ref:`[3] <complex_refs>`.
Complex problems can be defined in PICOS using the complex-valued variable types
:class:`~picos.ComplexVariable` and :class:`~picos.HermitianVariable`:
>>> from picos import ComplexVariable, HermitianVariable
>>> z = ComplexVariable("z", 4)
>>> H = HermitianVariable("H", 4)
>>> z
<4×1 Complex Variable: z>
>>> H
<4×4 Hermitian Variable: H>
>>> z.real
<4×1 Real Linear Expression: Re(z)>
>>> z.imag
<4×1 Real Linear Expression: Im(z)>
Their value can be set and retrieved as in the real case but may contain an
imaginary part:
>>> z.value = [1, 2+2j, 3+3j, 4j]
>>> z.value # Note the CVXOPT typecode of 'z'.
<4x1 matrix, tc='z'>
>>> print(z)
[ 1.00e+00-j0.00e+00]
[ 2.00e+00+j2.00e+00]
[ 3.00e+00+j3.00e+00]
[ 0.00e+00+j4.00e+00]
>>> z.real.value
<4x1 matrix, tc='d'>
>>> print(z.real)
[ 1.00e+00]
[ 2.00e+00]
[ 3.00e+00]
[ 0.00e+00]
>>> print(z.imag)
[ 0.00e+00]
[ 2.00e+00]
[ 3.00e+00]
[ 4.00e+00]
Just like real variables are the simplest form of an
:class:`~picos.expressions.AffineExpression`, complex variables are represented
to you as instances of :class:`~picos.expressions.ComplexAffineExpression`.
Most notably this gives access to complex conjugation and hermitian
transposition:
>>> z.conj
<4×1 Complex Linear Expression: conj(z)>
>>> z.H
<1×4 Complex Linear Expression: zᴴ>
Internally complex variables are represented as real variable vectors:
>>> z.dim # Twice its dimension on the complex field.
8
>>> H.dim # The same dimension as an arbitrary real matrix of same shape.
16
Note that in the hermitian case, we get away with just :math:`4 \cdot 4 = 16`
*real* scalar variables due to the vectorization used. This leads to a smaller
footprint when the problem is passed to a solver.
Unlike real-valued variables, :class:`~picos.ComplexVariable` and
:class:`~picos.HermitianVariable` do not accept variable bounds at creation, and
any properly complex expression formed from them cannot appear on either side of
an affine inequality constraint or as an objective function. However, PICOS
detects when you supply a real-valued expression in any of these places even if
it was created from complex expressions:
>>> A = ~z*~z.H # Use the current value of z to create a constant 4×4 matrix.
>>> A
<4×4 Complex Constant: value(z)·value(zᴴ)>
>>> A.hermitian # By construction this matrix is hermitian.
True
>>> (H|A) # Create a complex expression involving H.
<1×1 Complex Linear Expression: ⟨H, value(z)·value(zᴴ)⟩>
>>> (H|A).isreal # On closer inspection, it is always real-valued.
True
>>> (H|A).refined # This means it can be "refined" to a real expression.
<1×1 Real Linear Expression: ⟨H, value(z)·value(zᴴ)⟩>
>>> (H|A) >= 0 # Refinement happens automatically wherever necessary.
<1×1 Affine Constraint: ⟨H, value(z)·value(zᴴ)⟩ ≥ 0>
>>> H == A # Equalities involving complex expressions can be posed as normal.
<4×4 Complex Equality Constraint: H = value(z)·value(zᴴ)>
Complex linear matrix inequalities are created just as in the real case with the
overloaded ``<<`` and ``>>`` operators representing the Loewner order:
>>> H >> 0
<4×4 Complex LMI Constraint: H ≽ 0>
Since solvers at this time generally do not support complex optimization, PICOS
transforms such a constraint to an equivalent real LMI during solution search.
Only to demonstrate this behavior, we do it manually:
>>> from picos import Options
>>> from picos.constraints import ComplexLMIConstraint
>>> P = ComplexLMIConstraint.RealConversion.convert(H >> 0, Options())
>>> P.get_constraint(0)
<8×8 LMI Constraint: [Re(H), -Im(H); Im(H), Re(H)] ≽ 0>
Fidelity in Quantum Information Theory
--------------------------------------
The material of this section is inspired from a lecture of John Watrous :ref:`[4] <complex_refs>`.
The material of this section is inspired by a lecture of John Watrous
:ref:`[4] <complex_refs>`.
The Fidelity between two (Hermitian) positive semidefinite operators :math:`P` and :math:`Q`
is defined as:
The fidelity between two (hermitian) positive semidefinite operators :math:`P`
and :math:`Q` is defined as
.. math::
F(P,Q) = \Vert P^{1/2} Q^{1/2} \Vert_{tr} = \max_U \left|\operatorname{trace} \big(P^{1/2} U Q^{1/2}\big) \right|,
where the trace norm :math:`\Vert \cdot \Vert_{tr}` is the sum of the singular values,
and the maximization goes over the set of all unitary matrices :math:`U`.
This quantity can be expressed as the optimal value of the following complex-valued SDP:
F(P,Q)
= \left\Vert P^{\frac{1}{2}} Q^{\frac{1}{2}} \right\Vert_{\text{tr}}
= \max_U \left|
\operatorname{trace}\left(P^{\frac{1}{2}} U Q^{\frac{1}{2}}\right)
\right|,
where the trace norm :math:`\Vert \cdot \Vert_{\text{tr}}` is the sum of the
singular values, and the maximization goes over the set of all unitary matrices
:math:`U`.
This quantity can be expressed as the optimal value of the following
complex-valued SDP:
.. math::
:nowrap:
\begin{center}
\begin{eqnarray*}
&\underset{Z \in \mathbb{C}^{n \times n}}
{\mbox{maximize}}
& \frac{1}{2}\operatorname{trace}(Z + Z^*)\\
&\mbox{subject to} &
\left(\begin{array}{cc}
P & Z \\
Z^* & Q
:nowrap:
\begin{eqnarray*}
&\underset{Z \in \mathbb{C}^{n \times n}}{\mbox{maximize}}
&\frac{1}{2}\operatorname{trace}(Z + Z^*)
\\
&\mbox{subject to}
&\left(\begin{array}{cc}
P & Z \\
Z^* & Q
\end{array}\right) \succeq 0
\end{eqnarray*}
\end{center}
\end{eqnarray*}
This Problem can be solved as follows in PICOS
This model can be implemented in PICOS as follows:
.. testcode::
#generate two (arbitrary) positive hermitian operators
P = cvx.matrix([ [1-1j , 2+2j , 1 ],
[3j , -2j , -1-1j],
[1+2j, -0.5+1j, 1.5 ]
])
P = P * P.H
Q = cvx.matrix([ [-1-2j , 2j , 1.5 ],
[1+2j ,-2j , 2.-3j ],
[1+2j ,-1+1j , 1+4j ]
])
Q = Q * Q.H
n=P.size[0]
P = pic.new_param('P',P)
Q = pic.new_param('Q',Q)
#create the problem in picos
F = pic.Problem()
Z = F.add_variable('Z',(n,n),'complex')
#!/usr/bin/python
F.set_objective('max','I'|0.5*(Z+Z.H)) #('I' | Z.real) works as well
F.add_constraint(((P & Z) // (Z.H & Q))>>0 )
import numpy
import picos
print(F)
# Create a positive semidefinite constant P.
_P = picos.Constant([
[ 1 -1j, 2 +2j, 1 ],
[ 3j, -2j, -1 -1j],
[ 1 +2j, -0.5+1j, 1.5 ]])
P = (_P*_P.H).renamed("P")
F.solve(verbose = 0, solver = 'cvxopt')
# Create a positive semidefinite constant Q.
_Q = picos.Constant([
[-1 -2j, 2j, 1.5 ],
[ 1 +2j, -2j, 2.0-3j],
[ 1 +2j, -1 +1j, 1 +4j]])
Q = (_Q*_Q.H).renamed("Q")
print('fidelity: F(P,Q) = {0:.4f}'.format(F.obj_value()))
# Define the problem.
F = picos.Problem()
Z = picos.ComplexVariable("Z", P.shape)
F.set_objective("max", 0.5*picos.trace(Z + Z.H))
F.add_constraint(((P & Z) // (Z.H & Q)) >> 0)
print('optimal matrix Z:')
print(Z)
print(F)
#verify that we get the same value with numpy
import numpy as np
PP = np.matrix(P.value)
QQ = np.matrix(Q.value)
# Solve the problem.
F.solve(solver = "cvxopt")
S,U = np.linalg.eig(PP)
sqP = U * np.diag([s**0.5 for s in S]) * U.H #square root of P
S,U = np.linalg.eig(QQ)
sqQ = U * np.diag([s**0.5 for s in S]) * U.H #square root of P
print("\nOptimal value:", round(F, 4))
print("Optimal Z:", Z.value, sep="\n")
fidelity = sum(np.linalg.svd(sqP * sqQ)[1]) #trace-norm of P**0.5 * Q**0.5
# Also compute the fidelity via NumPy for comparison.
PP = numpy.matrix(P.value)
QQ = numpy.matrix(Q.value)
S,U = numpy.linalg.eig(PP)
sqP = U * numpy.diag([s**0.5 for s in S]) * U.H # Square root of P.
S,U = numpy.linalg.eig(QQ)
sqQ = U * numpy.diag([s**0.5 for s in S]) * U.H # Square root of Q.
Fnp = sum(numpy.linalg.svd(sqP * sqQ)[1]) # Trace-norm of sqrt(P)·sqrt(Q).
print('fidelity computed by trace-norm: F(P,Q) = {0:.4f}'.format(fidelity))
print("Fidelity F(P,Q) computed by NumPy:", round(Fnp, 4))
.. testoutput::
:options: +NORMALIZE_WHITESPACE
---------------------
optimization problem (Complex SDP):
18 variables, 0 affine constraints, 21 vars in 1 SD cones
Z_IM : (3, 3), continuous
Z_RE : (3, 3), continuous
maximize trace(0.5·(Z + Zᴴ))
such that
----------------------------
Complex Semidefinite Program
maximize 0.5·tr(Z + Zᴴ)
over
3×3 complex variable Z
subject to
[P, Z; Zᴴ, Q] ≽ 0
---------------------
fidelity: F(P,Q) = 37.4742
optimal matrix Z:
[ 1.51e+01+j2.21e+00 -7.17e+00-j1.22e+00 2.52e+00+j6.87e-01]
[-4.88e+00+j4.06e+00 1.00e+01-j1.57e-01 8.33e+00+j1.13e+01]
[-4.33e-01+j2.98e-01 3.84e+00-j3.28e+00 1.24e+01-j2.05e+00]
----------------------------
fidelity computed by trace-norm: F(P,Q) = 37.4742
Optimal value: 39.8938
Optimal Z:
[ 1.06e+01+j2.04e+00 -7.21e+00+j5.77e+00 3.58e+00-j8.10e+00]
[-8.26e+00-j2.13e+00 1.65e+01+j3.61e-01 8.59e-02-j2.29e+00]
[-1.38e+00+j6.42e+00 -5.65e-01+j1.55e+00 1.28e+01-j2.40e+00]
Fidelity F(P,Q) computed by NumPy: 39.8938
Phase Recovery in Signal Processing
-----------------------------------
The material from this section is inspired from :ref:`[3] <complex_refs>`.
This section is inspired by :ref:`[3] <complex_refs>`.
The goal of the phase recovery problem is to reconstruct the complex phase of a vector,
when we are only given the magnitude of some linear measurements.
This problem can be formulated as a nonconvex optimization problem,
and the authors of :ref:`[3] <complex_refs>` have proposed a complex SDP relaxation
similar to the well known *Max-Cut* SDP:
The goal of the phase recovery problem is to reconstruct the complex phase of a
vector given only the magnitudes of some linear measurements.
This problem can be formulated as a non-convex optimization problem, and the
authors of :ref:`[3] <complex_refs>` have proposed a complex semidefinite
relaxation similar to the well known relaxation of the **Max-Cut Problem**:
Given a linear operator :math