├── AUTHORS ├── docs ├── sphinx │ ├── source │ │ ├── matlab-source │ │ │ └── mips │ │ │ │ ├── mips.m │ │ │ │ ├── mipsver.m │ │ │ │ ├── qps_mips.m │ │ │ │ ├── t_mips.m │ │ │ │ ├── mplinsolve.m │ │ │ │ ├── t_qps_mips.m │ │ │ │ ├── test_mips.m │ │ │ │ ├── t_mplinsolve.m │ │ │ │ ├── mips_example1.m │ │ │ │ ├── mips_example2.m │ │ │ │ ├── t_mips_pardiso.m │ │ │ │ ├── have_feature_mips.m │ │ │ │ ├── have_feature_lu_vec.m │ │ │ │ ├── have_feature_pardiso.m │ │ │ │ ├── have_feature_pardiso_legacy.m │ │ │ │ └── have_feature_pardiso_object.m │ │ ├── _static │ │ │ └── css │ │ │ │ └── matpower.css │ │ ├── index.rst │ │ ├── functions │ │ │ ├── mips.rst │ │ │ ├── t_mips.rst │ │ │ ├── mipsver.rst │ │ │ ├── qps_mips.rst │ │ │ ├── test_mips.rst │ │ │ ├── mplinsolve.rst │ │ │ ├── t_qps_mips.rst │ │ │ ├── t_mplinsolve.rst │ │ │ ├── mips_example1.rst │ │ │ ├── mips_example2.rst │ │ │ ├── t_mips_pardiso.rst │ │ │ ├── have_feature_mips.rst │ │ │ ├── have_feature_lu_vec.rst │ │ │ ├── have_feature_pardiso.rst │ │ │ ├── have_feature_pardiso_legacy.rst │ │ │ └── have_feature_pardiso_object.rst │ │ ├── reference.rst │ │ └── conf.py │ ├── Makefile │ ├── make.bat │ └── Building-Docs.md ├── MIPS-manual.pdf ├── relnotes │ ├── MIPS-Release-Notes-1.5.2.md │ ├── MIPS-Release-Notes-1.3.1.md │ ├── MIPS-Release-Notes-1.5.1.md │ ├── MIPS-Release-Notes-1.5.md │ ├── MIPS-Release-Notes-1.3.md │ └── MIPS-Release-Notes-1.4.md └── other │ └── MIPS-Release-Checklist.md ├── examples ├── mips_example1.m └── mips_example2.m ├── .gitignore ├── lib ├── have_feature_mips.m ├── have_feature_lu_vec.m ├── Contents.m ├── have_feature_pardiso.m ├── have_feature_pardiso_object.m ├── mipsver.m ├── t │ ├── test_mips.m │ ├── generate_mips_autodoc.m │ ├── t_qps_mips.m │ ├── t_mips_pardiso.m │ ├── t_mips.m │ └── t_mplinsolve.m ├── have_feature_pardiso_legacy.m ├── qps_mips.m ├── mplinsolve.m └── mips.m ├── CITATION ├── LICENSE ├── .github └── workflows │ └── continuous-integration.yml ├── README.md ├── CHANGES.md └── CONTRIBUTING.md /AUTHORS: -------------------------------------------------------------------------------- 1 | Hongye Wang 2 | Ray Zimmerman 3 | -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/mipsver.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/mipsver.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/qps_mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/qps_mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/t_mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/t/t_mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/_static/css/matpower.css: -------------------------------------------------------------------------------- 1 | ../../mp-docs-shared/css/matpower.css -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/mplinsolve.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/mplinsolve.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/t_qps_mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/t/t_qps_mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/test_mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/t/test_mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/t_mplinsolve.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/t/t_mplinsolve.m -------------------------------------------------------------------------------- /docs/MIPS-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MATPOWER/mips/HEAD/docs/MIPS-manual.pdf -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/mips_example1.m: -------------------------------------------------------------------------------- 1 | ../../../../../examples/mips_example1.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/mips_example2.m: -------------------------------------------------------------------------------- 1 | ../../../../../examples/mips_example2.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/t_mips_pardiso.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/t/t_mips_pardiso.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/have_feature_mips.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/have_feature_mips.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/have_feature_lu_vec.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/have_feature_lu_vec.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/have_feature_pardiso.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/have_feature_pardiso.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/have_feature_pardiso_legacy.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/have_feature_pardiso_legacy.m -------------------------------------------------------------------------------- /docs/sphinx/source/matlab-source/mips/have_feature_pardiso_object.m: -------------------------------------------------------------------------------- 1 | ../../../../../lib/have_feature_pardiso_object.m -------------------------------------------------------------------------------- /examples/mips_example1.m: -------------------------------------------------------------------------------- 1 | function mips_example1 2 | % mips_example1 - Example of unconstrained nonlinear optimization. 3 | % 4 | % Minimizes MATLAB's :func:`banana` function. 5 | f_fcn = @(x)banana(x, 100); 6 | x0 = [-1.9; 2]; 7 | [x, f] = mips(f_fcn, x0) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | untracked 2 | docs/src/MIPS-manual/MIPS-manual.aux 3 | docs/src/MIPS-manual/MIPS-manual.brf 4 | docs/src/MIPS-manual/MIPS-manual.lof 5 | docs/src/MIPS-manual/MIPS-manual.log 6 | docs/src/MIPS-manual/MIPS-manual.lot 7 | docs/src/MIPS-manual/MIPS-manual.out 8 | docs/src/MIPS-manual/MIPS-manual.pdf 9 | docs/src/MIPS-manual/MIPS-manual.synctex.gz 10 | docs/src/MIPS-manual/MIPS-manual.synctex.gz (busy) 11 | docs/src/MIPS-manual/MIPS-manual.toc 12 | docs/sphinx/build 13 | docs/sphinx/source/mp-docs-shared 14 | .vs 15 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.5.2.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.5.2 2 | ------------------------ 3 | 4 | #### Released July 12, 2025 5 | 6 | Below is a summary of the changes since version 1.5.1 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### New Features: 11 | - New feature detection function `have_feature_mips()`, providing 12 | implementation of the `'mips'` tag for `have_feature()`. 13 | 14 | 15 | [1]: ../../CHANGES.md 16 | [2]: ../MIPS-manual.pdf 17 | [3]: https://matpower.org/doc/mips/ 18 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.3.1.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.3.1 2 | ------------------------ 3 | 4 | #### Released Jun 20, 2019 5 | 6 | Below is a summary of the changes since version 1.3 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### Changes: 11 | - Add `CITATION` file. 12 | - Other miscellaneous documentation updates, e.g. MATPOWER website 13 | links updated to https://matpower.org. 14 | 15 | 16 | [1]: https://github.com/MATPOWER/mips/blob/master/CHANGES.md 17 | [2]: https://github.com/MATPOWER/mips/blob/master/docs/MIPS-manual.pdf 18 | -------------------------------------------------------------------------------- /docs/sphinx/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.5.1.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.5.1 2 | ------------------------ 3 | 4 | #### Released May 10, 2024 5 | 6 | Below is a summary of the changes since version 1.5 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### New Features: 11 | - Add Sphinx-based [Reference documentation][3]. 12 | - Add `full_hist` option to enable saving in `output.hist` 13 | trajectories of `x`, `z`, `g`, `h`, `lam`, and `mu` 14 | ([issue #4][4]). 15 | 16 | 17 | [1]: ../../CHANGES.md 18 | [2]: ../MIPS-manual.pdf 19 | [3]: https://matpower.org/doc/mips/ 20 | [4]: https://github.com/MATPOWER/mips/issues/4 21 | -------------------------------------------------------------------------------- /docs/sphinx/source/index.rst: -------------------------------------------------------------------------------- 1 | .. _mips_users_manual: 2 | 3 | ################## 4 | MIPS User's Manual 5 | ################## 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | :numbered: 3 10 | 11 | .. note:: 12 | 13 | The new web-based version of the MIPS User's Manual is not yet available. Please, continue to use the PDF version of the |MIPSman| for now, along with the new reference documentation below. 14 | 15 | 16 | Reference 17 | ========= 18 | 19 | The primary sources of documentation for MIPS, aside from the legacy PDF |MIPSman|, are this :ref:`sec_mips_reference` documentation and the built-in ``help`` command. As with the built-in functions and toolbox routines in |MATLAB>| and |Octave>|, you can type ``help`` followed by the name of a command or M-file to get help on that particular function. 20 | 21 | .. toctree:: 22 | 23 | reference 24 | -------------------------------------------------------------------------------- /lib/have_feature_mips.m: -------------------------------------------------------------------------------- 1 | function [TorF, vstr, rdate] = have_feature_mips() 2 | % have_feature_mips - Detect availability/version info for MIPS. 3 | % 4 | % Private feature detection function implementing ``mips`` tag for 5 | % have_feature to detect support for ``mips()`` function. 6 | % 7 | % See also have_feature. 8 | 9 | % MIPS 10 | % Copyright (c) 2004-2025, Power Systems Engineering Research Center (PSERC) 11 | % by Ray Zimmerman, PSERC Cornell 12 | % 13 | % This file is part of MIPS. 14 | % Covered by the 3-clause BSD License (see LICENSE file for details). 15 | % See https://github.com/MATPOWER/mips for more info. 16 | 17 | if exist('mipsver', 'file') == 2 18 | v = mipsver('all'); 19 | vstr = v.Version; 20 | rdate = v.Date; 21 | TorF = 1; 22 | else 23 | vstr = ''; 24 | rdate = ''; 25 | TorF = 0; 26 | end 27 | -------------------------------------------------------------------------------- /lib/have_feature_lu_vec.m: -------------------------------------------------------------------------------- 1 | function [TorF, vstr, rdate] = have_feature_lu_vec() 2 | % have_feature_lu_vec - Detect availability/version info for LU vector support. 3 | % 4 | % Private feature detection function implementing ``'lu_vec'`` tag for 5 | % have_feature to detect support for ``lu(..., 'vector')`` syntax. 6 | % 7 | % See also have_feature, lu. 8 | 9 | % MIPS 10 | % Copyright (c) 2004-2024, Power Systems Engineering Research Center (PSERC) 11 | % by Ray Zimmerman, PSERC Cornell 12 | % 13 | % This file is part of MIPS. 14 | % Covered by the 3-clause BSD License (see LICENSE file for details). 15 | % See https://github.com/MATPOWER/mips for more info. 16 | 17 | vstr = ''; 18 | rdate = ''; 19 | if have_feature('matlab') && have_feature('matlab', 'vnum') < 7.003 20 | TorF = 0; %% lu(..., 'vector') syntax not supported 21 | else 22 | TorF = 1; 23 | end 24 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.5.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.5 2 | ---------------------- 3 | 4 | #### Released Dec 12, 2022 5 | 6 | Below is a summary of the changes since version 1.4 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### New Features: 11 | - Add to `mplinsolve()` the ability to return a struct containing the 12 | matrix LU factorization, and to reuse this pre-factored matrix to solve 13 | additional systems with different right-hand-sides by passing the 14 | struct in place of the A matrix to subsequent calls. 15 | - Add option to `mplinsolve()` to solve transposed systems by setting 16 | `opt.tr` to 1, including when providing the pre-factored matrix for 17 | the original, non-transposed system. 18 | 19 | 20 | [1]: ../../CHANGES.md 21 | [2]: ../MIPS-manual.pdf 22 | -------------------------------------------------------------------------------- /docs/sphinx/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | mips 6 | ---- 7 | 8 | .. autofunction:: mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/t_mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | t_mips 6 | ------ 7 | 8 | .. autofunction:: t_mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/mipsver.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | mipsver 6 | ------- 7 | 8 | .. autofunction:: mipsver 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/qps_mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | qps_mips 6 | -------- 7 | 8 | .. autofunction:: qps_mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/test_mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | test_mips 6 | --------- 7 | 8 | .. autofunction:: test_mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/mplinsolve.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | mplinsolve 6 | ---------- 7 | 8 | .. autofunction:: mplinsolve 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/t_qps_mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | t_qps_mips 6 | ---------- 7 | 8 | .. autofunction:: t_qps_mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/t_mplinsolve.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | t_mplinsolve 6 | ------------ 7 | 8 | .. autofunction:: t_mplinsolve 9 | -------------------------------------------------------------------------------- /lib/Contents.m: -------------------------------------------------------------------------------- 1 | % MIPS 2 | % Version 1.5.2 12-Jul-2025 3 | % 4 | % The MATPOWER Interior Point Solver (MIPS) is a package of MATLAB/Octave 5 | % M-files for solving non-linear programming problems (NLPs) using a 6 | % primal dual interior point method. MIPS is based on code written in C 7 | % language by Hongye Wang as a graduate student at Cornell University 8 | % for optimal power flow applications. It was later ported to the 9 | % MATLAB/Octave language by Ray D. Zimmerman for use in MATPOWER. 10 | % 11 | % The latest version of MIPS can be found on GitHub at: 12 | % 13 | % https://github.com/MATPOWER/mips 14 | % 15 | % MIPS is covered by the 3-clause BSD License (see LICENSE for details). 16 | 17 | % MIPS 18 | % Copyright (c) 2010-2025, Power Systems Engineering Research Center (PSERC) 19 | % by Ray Zimmerman, PSERC Cornell 20 | % 21 | % This file is part of MIPS. 22 | % Covered by the 3-clause BSD License (see LICENSE file for details). 23 | % See https://github.com/MATPOWER/mips for more info. 24 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/mips_example1.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | mips_example1 6 | ------------- 7 | 8 | .. autofunction:: mips_example1 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/mips_example2.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | mips_example2 6 | ------------- 7 | 8 | .. autofunction:: mips_example2 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/t_mips_pardiso.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | t_mips_pardiso 6 | -------------- 7 | 8 | .. autofunction:: t_mips_pardiso 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/have_feature_mips.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | have_feature_mips 6 | ----------------- 7 | 8 | .. autofunction:: have_feature_mips 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/have_feature_lu_vec.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | have_feature_lu_vec 6 | ------------------- 7 | 8 | .. autofunction:: have_feature_lu_vec 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/have_feature_pardiso.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | have_feature_pardiso 6 | -------------------- 7 | 8 | .. autofunction:: have_feature_pardiso 9 | -------------------------------------------------------------------------------- /lib/have_feature_pardiso.m: -------------------------------------------------------------------------------- 1 | function [TorF, vstr, rdate] = have_feature_pardiso() 2 | % have_feature_pardiso - Detect availability/version info for PARDISO. 3 | % 4 | % Private feature detection function implementing ``'pardiso'`` tag for 5 | % have_feature to detect availability/version of PARDISO, Parallel Sparse 6 | % Direct & Iterative Linear Solver (https://pardiso-project.org). 7 | % 8 | % See also have_feature, have_feature_pardiso_legacy, 9 | % have_feature_pardiso_object. 10 | 11 | % MIPS 12 | % Copyright (c) 2004-2024, Power Systems Engineering Research Center (PSERC) 13 | % by Ray Zimmerman, PSERC Cornell 14 | % 15 | % This file is part of MIPS. 16 | % Covered by the 3-clause BSD License (see LICENSE file for details). 17 | % See https://github.com/MATPOWER/mips for more info. 18 | 19 | if have_feature('pardiso_object') 20 | TorF = 1; 21 | vstr = have_feature('pardiso_object', 'vstr'); 22 | elseif have_feature('pardiso_legacy') 23 | TorF = 1; 24 | vstr = have_feature('pardiso_legacy', 'vstr'); 25 | else 26 | TorF = 0; 27 | vstr = ''; 28 | end 29 | rdate = ''; 30 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/have_feature_pardiso_legacy.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | have_feature_pardiso_legacy 6 | --------------------------- 7 | 8 | .. autofunction:: have_feature_pardiso_legacy 9 | -------------------------------------------------------------------------------- /docs/sphinx/source/functions/have_feature_pardiso_object.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: mips 2 | 3 | :raw-html:`
` 4 | 5 | have_feature_pardiso_object 6 | --------------------------- 7 | 8 | .. autofunction:: have_feature_pardiso_object 9 | -------------------------------------------------------------------------------- /lib/have_feature_pardiso_object.m: -------------------------------------------------------------------------------- 1 | function [TorF, vstr, rdate] = have_feature_pardiso_object() 2 | % have_feature_pardiso_object - Detect availability/version info for PARDISO (object interface). 3 | % 4 | % Private feature detection function implementing ``'pardiso_object'`` tag for 5 | % have_feature to detect support for the object-oriented (v6.x and later) 6 | % PARDISO interface. 7 | % 8 | % See also have_feature, have_feature_pardiso, have_feature_pardiso_legacy. 9 | 10 | % MIPS 11 | % Copyright (c) 2004-2024, Power Systems Engineering Research Center (PSERC) 12 | % by Ray Zimmerman, PSERC Cornell 13 | % 14 | % This file is part of MIPS. 15 | % Covered by the 3-clause BSD License (see LICENSE file for details). 16 | % See https://github.com/MATPOWER/mips for more info. 17 | 18 | TorF = exist('pardiso', 'file') == 2; 19 | rdate = ''; 20 | if TorF 21 | vstr = '6.x+'; 22 | try 23 | id = 1; 24 | A = sparse([1 2; 3 4]); 25 | b = [1;1]; 26 | p = pardiso(id, 11, 0); 27 | p.factorize(id, A); 28 | x = p.solve(id, A, b); 29 | p.free(id); 30 | p.clear(); 31 | if any(x ~= [-1; 1]) 32 | TorF = 0; 33 | end 34 | catch 35 | TorF = 0; 36 | end 37 | else 38 | vstr = ''; 39 | end 40 | -------------------------------------------------------------------------------- /lib/mipsver.m: -------------------------------------------------------------------------------- 1 | function rv = mipsver(varargin) 2 | % mipsver - Prints or returns installed MIPS version info. 3 | % :: 4 | % 5 | % mipsver 6 | % v = mipsver 7 | % v = mipsver('all') 8 | % 9 | % When called with an output argument and no input argument, mipsver 10 | % returns the current MIPS version numbers. With an input argument 11 | % (e.g. ``'all'``) it returns a struct with the fields ``Name``, 12 | % ``Version``, ``Release``, and ``Date`` *(all char arrays)*. Calling 13 | % mipsver without assigning the return value prints the version and 14 | % release date of the current installation of MIPS. 15 | % 16 | % See also mpver. 17 | 18 | % MIPS 19 | % Copyright (c) 2010-2025, Power Systems Engineering Research Center (PSERC) 20 | % by Ray Zimmerman, PSERC Cornell 21 | % 22 | % This file is part of MIPS. 23 | % Covered by the 3-clause BSD License (see LICENSE file for details). 24 | % See https://github.com/MATPOWER/mips for more info. 25 | 26 | v = struct( 'Name', 'MIPS', ... 27 | 'Version', '1.5.2', ... 28 | 'Release', '', ... 29 | 'Date', '12-Jul-2025' ); 30 | if nargout > 0 31 | if nargin > 0 32 | rv = v; 33 | else 34 | rv = v.Version; 35 | end 36 | else 37 | fprintf('%-22s Version %-9s %11s\n', v.Name, v.Version, v.Date); 38 | end 39 | -------------------------------------------------------------------------------- /lib/t/test_mips.m: -------------------------------------------------------------------------------- 1 | function success = test_mips(verbose, exit_on_fail) 2 | % test_mips - Run all MIPS tests. 3 | % :: 4 | % 5 | % test_mips 6 | % test_mips(verbose) 7 | % test_mips(verbose, exit_on_fail) 8 | % success = test_mips(...) 9 | % 10 | % Runs all of the MIPS tests. If ``verbose`` is true *(false by default)*, 11 | % it prints the details of the individual tests. If ``exit_on_fail`` is true 12 | % *(false by default)*, it will exit MATLAB or Octave with a status of 1 13 | % unless t_run_tests returns ``all_ok`` true. 14 | % 15 | % See also t_run_tests. 16 | 17 | % MIPS 18 | % Copyright (c) 2016-2024, Power Systems Engineering Research Center (PSERC) 19 | % by Ray Zimmerman, PSERC Cornell 20 | % 21 | % This file is part of MIPS. 22 | % Covered by the 3-clause BSD License (see LICENSE file for details). 23 | % See https://github.com/MATPOWER/mips for more info. 24 | 25 | if nargin < 2 26 | exit_on_fail = 0; 27 | if nargin < 1 28 | verbose = 0; 29 | end 30 | end 31 | 32 | tests = {}; 33 | 34 | %% MIPS tests 35 | tests{end+1} = 't_mplinsolve'; 36 | tests{end+1} = 't_mips'; 37 | tests{end+1} = 't_mips_pardiso'; 38 | tests{end+1} = 't_qps_mips'; 39 | 40 | %% run the tests 41 | all_ok = t_run_tests( tests, verbose ); 42 | 43 | %% handle success/failure 44 | if exit_on_fail && ~all_ok 45 | exit(1); 46 | end 47 | if nargout 48 | success = all_ok; 49 | end 50 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | We request that publications derived from the use of the MATPOWER 2 | Interior Point Solver (MIPS) explicitly acknowledge that fact by citing 3 | the following 2007 paper. 4 | 5 | H. Wang, C. E. Murillo-Sánchez, R. D. Zimmerman, R. J. Thomas, "On 6 | Computational Issues of Market-Based Optimal Power Flow," Power Systems, 7 | IEEE Transactions on, vol. 22, no. 3, pp. 1185-1193, Aug. 2007. 8 | doi: 10.1109/TPWRS.2007.901301. 9 | 10 | The MATPOWER Interior Point Solver (MIPS) User's Manual should also be 11 | cited explicitly in work that refers to or is derived from its content. 12 | The citation and DOI can be version-specific or general, as appropriate. 13 | For version 1.5.2, use: 14 | 15 | R. D. Zimmerman, H. Wang. MATPOWER Interior Point Solver (MIPS) 16 | User's Manual, Version 1.5.2. 2025. [Online]. 17 | Available: https://matpower.org/docs/MIPS-manual-1.5.2.pdf 18 | doi: 10.5281/zenodo.15871404 19 | 20 | For a version non-specific citation, use the following citation and DOI, 21 | with replaced by the year of the most recent release: 22 | 23 | R. D. Zimmerman, H. Wang. MATPOWER Interior Point Solver (MIPS) 24 | User's Manual. . [Online]. 25 | Available: https://matpower.org/docs/MIPS-manual.pdf 26 | doi: 10.5281/zenodo.3236506 27 | 28 | A list of versions of the User's Manual with release dates and 29 | version-specific DOI's can be found via the general DOI at 30 | https://doi.org/10.5281/zenodo.3236506. 31 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.3.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.3 2 | ---------------------- 3 | 4 | #### Released Oct 30, 2018 5 | 6 | Below is a summary of the changes since version 1.2.2 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### New Features: 11 | - Support for PARDISO 6.x. 12 | - New `mplinsolve` solver option `'LU'` for explicit LU decomposition 13 | with back substitution, with options in `opt.lu` for specifying the 14 | number of output arguments in call to `lu` (`opt.lu.nout`), whether 15 | to use permutation vectors or matrices (`opt.lu.vec`) and pivot 16 | threshold options (`opt.lu.thresh`). The following values for the 17 | `solver` argument act as shortcuts for specifying various 18 | combinations of options: `'LU3'`, `'LU3a'`, `'LU4'`, `'LU5'`, 19 | `'LU3m'`, `'LU3am'`, `'LU4m'`, `'LU5m'`. 20 | See `help mplinsolve` for details. 21 | *Thanks to Jose Luis Marin.* 22 | 23 | #### Bugs Fixed: 24 | - Fix bug preventing `pardiso.dparm` options from being set. 25 | 26 | #### Other Changes: 27 | - LaTeX source code for [MIPS User's Manual][2] included in `docs/src`. 28 | - Move `mplinsolve` PARDISO options to `opt.pardiso` in preparation 29 | for adding options for other solvers. 30 | 31 | 32 | [1]: https://github.com/MATPOWER/mips/blob/master/CHANGES.md 33 | [2]: https://github.com/MATPOWER/mips/blob/master/docs/MIPS-manual.pdf 34 | -------------------------------------------------------------------------------- /docs/sphinx/source/reference.rst: -------------------------------------------------------------------------------- 1 | .. _sec_mips_reference: 2 | 3 | Reference 4 | ========= 5 | 6 | 7 | Main MIPS Functions 8 | ------------------- 9 | 10 | The MIPS nonlinear programming (NLP) solver, a linear solver API function, and a QP solver wrapper function for MIPS. 11 | 12 | .. toctree:: 13 | 14 | functions/mips 15 | functions/mplinsolve 16 | functions/qps_mips 17 | 18 | 19 | Other Function 20 | -------------- 21 | 22 | Use this function to check the version of the installed MIPS. 23 | 24 | .. toctree:: 25 | 26 | functions/mipsver 27 | 28 | 29 | MIPS Examples 30 | ------------- 31 | 32 | These are examples of using MIPS to solve a NLP. 33 | 34 | .. toctree:: 35 | 36 | functions/mips_example1 37 | functions/mips_example2 38 | 39 | 40 | MIPS Tests 41 | ---------- 42 | 43 | These functions test that MIPS is installed and functioning as expected. 44 | 45 | .. toctree:: 46 | 47 | functions/test_mips 48 | functions/t_mips 49 | functions/t_mips_pardiso 50 | functions/t_mplinsolve 51 | functions/t_qps_mips 52 | 53 | 54 | Private Functions 55 | ----------------- 56 | 57 | The following are private functions that implement detection of specific 58 | optional functionality. They are not intended to be called directly, but 59 | rather are used to extend the capabilities of :func:`have_feature`. 60 | 61 | .. toctree:: 62 | 63 | functions/have_feature_lu_vec 64 | functions/have_feature_mips 65 | functions/have_feature_pardiso_legacy 66 | functions/have_feature_pardiso_object 67 | functions/have_feature_pardiso 68 | -------------------------------------------------------------------------------- /examples/mips_example2.m: -------------------------------------------------------------------------------- 1 | function mips_example2 2 | % mips_example2 - Example of constrained nonlinear optimization. 3 | % 4 | % Example of solving the following problem. 5 | % 6 | % .. math:: \min_{x_1,x_2,x_3} -x_1 x_2 - x_2 x_3 7 | % 8 | % subject to 9 | % 10 | % .. math:: x_1^2 - x_2^2 + x_3^2 - 2 \le 0 11 | % .. math:: x_1^2 + x_2^2 + x_3^2 - 10 \le 0 12 | 13 | problem = struct( ... 14 | 'f_fcn', @(x)f2(x), ... 15 | 'gh_fcn', @(x)gh2(x), ... 16 | 'hess_fcn', @(x, lam, cost_mult)hess2(x, lam, cost_mult), ... 17 | 'x0', [1; 1; 0], ... 18 | 'opt', struct('verbose', 2) ... 19 | ); 20 | [x, f, exitflag, output, lambda] = mips(problem); 21 | fprintf('\nf = %g exitflag = %d\n', f, exitflag); 22 | fprintf('\nx = \n'); 23 | fprintf(' %g\n', x); 24 | fprintf('\nlambda.ineqnonlin =\n'); 25 | fprintf(' %g\n', lambda.ineqnonlin); 26 | 27 | function [f, df, d2f] = f2(x) 28 | f = -x(1)*x(2) - x(2)*x(3); 29 | if nargout > 1 %% gradient is required 30 | df = -[x(2); x(1)+x(3); x(2)]; 31 | if nargout > 2 %% Hessian is required 32 | d2f = -[0 1 0; 1 0 1; 0 1 0]; %% actually not used since 33 | end %% 'hess_fcn' is provided 34 | end 35 | 36 | function [h, g, dh, dg] = gh2(x) 37 | h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10]; 38 | dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)]; 39 | g = []; dg = []; 40 | 41 | function Lxx = hess2(x, lam, cost_mult) 42 | if nargin < 3, cost_mult = 1; end %% allows to be used with 'fmincon' 43 | mu = lam.ineqnonlin; 44 | Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ... 45 | [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu]; 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 1996-2025, Power Systems Engineering Research Center (PSERC) 2 | and individual contributors (see AUTHORS file for details). 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 26 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /lib/have_feature_pardiso_legacy.m: -------------------------------------------------------------------------------- 1 | function [TorF, vstr, rdate] = have_feature_pardiso_legacy() 2 | % have_feature_pardiso_legacy - Detect availability/version info for PARDISO (legacy interface). 3 | % 4 | % Private feature detection function implementing ``'pardiso_legacy'`` tag 5 | % for have_feature to detect support for the legacy (v5.x) PARDISO interface, 6 | % with individual MEX files for factor, solve, etc. 7 | % 8 | % See also have_feature, have_feature_pardiso, have_feature_pardiso_object. 9 | 10 | % MIPS 11 | % Copyright (c) 2004-2024, Power Systems Engineering Research Center (PSERC) 12 | % by Ray Zimmerman, PSERC Cornell 13 | % 14 | % This file is part of MIPS. 15 | % Covered by the 3-clause BSD License (see LICENSE file for details). 16 | % See https://github.com/MATPOWER/mips for more info. 17 | 18 | TorF = exist('pardisoinit', 'file') == 3 && ... 19 | exist('pardisoreorder', 'file') == 3 && ... 20 | exist('pardisofactor', 'file') == 3 && ... 21 | exist('pardisosolve', 'file') == 3 && ... 22 | exist('pardisofree', 'file') == 3; 23 | rdate = ''; 24 | if TorF 25 | vstr = '6.x+'; 26 | try 27 | A = sparse([1 2; 3 4]); 28 | b = [1;1]; 29 | info = pardisoinit(11, 0); 30 | info = pardisoreorder(A, info, false); 31 | % % Summary PARDISO 5.1.0: ( reorder to reorder ) 32 | % pat = 'Summary PARDISO (\.*\d)+:'; 33 | % [s,e,tE,m,t] = regexp(evalc('info = pardisoreorder(A, info, true);'), pat); 34 | % if ~isempty(t) 35 | % vstr = t{1}{1}; 36 | % end 37 | info = pardisofactor(A, info, false); 38 | [x, info] = pardisosolve(A, b, info, false); 39 | pardisofree(info); 40 | if any(x ~= [-1; 1]) 41 | TorF = 0; 42 | end 43 | catch 44 | TorF = 0; 45 | end 46 | else 47 | vstr = ''; 48 | end 49 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # controls when action will run 4 | on: 5 | # triggers workflow on push events 6 | push: 7 | # allows workflow to be triggered manually from Actions tab 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | platform: [octave] 16 | # os: [macos-10.15, macos-11.0, macos-12.0, ubuntu-18.04, ubuntu-20.04, ubuntu-22.04] 17 | os: [macos-latest, ubuntu-22.04, ubuntu-24.04, ubuntu-latest] 18 | include: 19 | - platform: matlab 20 | os: ubuntu-latest 21 | 22 | runs-on: ${{ matrix.os }} 23 | 24 | steps: 25 | - name: Check out repository 26 | uses: actions/checkout@v4 27 | 28 | - name: Install Octave (Linux) 29 | if: matrix.platform == 'octave' && startsWith(matrix.os, 'ubuntu') 30 | uses: MATPOWER/action-install-octave-linux@v1 31 | 32 | - name: Install Octave (macOS) 33 | if: matrix.platform == 'octave' && startsWith(matrix.os, 'macos') 34 | uses: MATPOWER/action-install-octave-macos@v1 35 | 36 | - name: Install MATLAB 37 | if: matrix.platform == 'matlab' 38 | uses: matlab-actions/setup-matlab@v2 39 | 40 | - name: Configure MATLAB 41 | if: matrix.platform == 'matlab' 42 | uses: MATPOWER/action-configure-matlab@v2 43 | 44 | - name: ${{ env.ML_NAME }} ${{ env.ML_VER }} Installed 45 | run: $ML_CMD ver 46 | 47 | - name: Install MP-Test, Set MPTEST_PATH 48 | run: | 49 | git clone --depth=1 https://github.com/MATPOWER/mptest.git $HOME/mptest 50 | echo "MPTEST_PATH=$HOME/mptest/lib:$HOME/mptest/lib/t" >> $GITHUB_ENV 51 | 52 | - name: Set MIPS_PATH 53 | run: echo "MIPS_PATH=${GITHUB_WORKSPACE}/lib:${GITHUB_WORKSPACE}/lib/t:${GITHUB_WORKSPACE}/examples:${MPTEST_PATH}" >> $GITHUB_ENV 54 | 55 | - name: Test MP-Test 56 | run: env $ML_PATHVAR=$MPTEST_PATH $ML_CMD "mptestver; test_mptest(0,1)" 57 | 58 | - name: Test MIPS 59 | run: env $ML_PATHVAR=$MIPS_PATH $ML_CMD "mipsver; test_mips(0,1)" 60 | -------------------------------------------------------------------------------- /docs/relnotes/MIPS-Release-Notes-1.4.md: -------------------------------------------------------------------------------- 1 | What's New in MIPS 1.4 2 | ---------------------- 3 | 4 | #### Released Oct 8, 2020 5 | 6 | Below is a summary of the changes since version 1.3.1 of MIPS. See the 7 | [`CHANGES.md`][1] file for all the gory details. For release notes for 8 | previous versions, see Appendix C of the [MIPS User's Manual][2]. 9 | 10 | #### New Features: 11 | - Support for `have_feature()` from [MP-Test][3] to detect availability 12 | and version information for optional functionality. This is a modular, 13 | extensible replacement for `have_fcn()` from [MATPOWER][4] and 14 | [MP-Opt-Model][5]. 15 | - Feature detection functions for `lu()` and PARDISO, defining tags 16 | `'lu_vec'`, `'pardiso_legacy'`, `'pardiso_object'` and `'pardiso'` 17 | for `have\_feature()'`. 18 | - New functions: 19 | - `have_feature_lu_vec` detects support for the `lu(..., 'vector')` 20 | syntax. 21 | - `have_feature_pardiso_legacy` detects support for the legacy (v5.x) 22 | PARDISO interface, with individual MEX files for factor, solve, etc. 23 | - `have_feature_pardiso_object` detects support for the object-oriented 24 | (v6.x and later) PARDISO interface. 25 | - `have_feature_pardiso` detects availability/version of PARDISO. 26 | 27 | #### Bugs Fixed: 28 | - Silence inadvertent output from `mplinsolve()` when called without 29 | `solver` input argument. 30 | - Fix fatal errors when `mplinsolve()` is called with `'LU'` solver and 31 | dense `A` matrix. 32 | 33 | #### Other Changes: 34 | - Requires MP-Test 7.1 or later. 35 | - Remove `have_fcn()` dependencies in `mips()`, `t_mips_pardiso()` and 36 | `t_qps_mips()`. 37 | 38 | #### Incompatible Changes: 39 | - Calling `mips()` with `opt.linsolver` set to `'PARDISO'` now results in 40 | a fatal error if PARDISO is not installed, rather than warning and 41 | continuing with the default linear solver. 42 | 43 | 44 | [1]: ../../CHANGES.md 45 | [2]: ../MIPS-manual.pdf 46 | [3]: https://github.com/MATPOWER/mptest 47 | [4]: https://github.com/MATPOWER/matpower 48 | [5]: https://github.com/MATPOWER/mp-opt-model 49 | -------------------------------------------------------------------------------- /lib/t/generate_mips_autodoc.m: -------------------------------------------------------------------------------- 1 | function generate_mips_autodoc(install_dir) 2 | % generate_mips_autodoc - Generate the stubs and symlinks for Ref Manual. 3 | % :: 4 | % 5 | % generate_mips_autodoc(install_dir) 6 | % 7 | % Inputs: 8 | % install_dir (char array) : path to the install directory for the package 9 | % 10 | % Creates the .rst stubs and symlinks to the source files for all functions 11 | % and classes to be included in the Reference Manual. Creates all of the 12 | % inputs (lists of functions and classes) to pass to generate_autodoc_stubs 13 | % and generate_source_symlinks. 14 | 15 | % MIPS 16 | % Copyright (c) 2023-2025, Power Systems Engineering Research Center (PSERC) 17 | % by Ray Zimmerman, PSERC Cornell 18 | % 19 | % This file is part of MIPS. 20 | % Covered by the 3-clause BSD License (see LICENSE file for details). 21 | % See https://github.com/MATPOWER/mips for more info. 22 | 23 | if nargin < 1 24 | matpower_dir = '~/dev/projects/mips/'; 25 | end 26 | 27 | sphinx_src_dir = [matpower_dir 'docs/sphinx/source/']; 28 | 29 | lib_fcns = { 30 | 'have_feature_lu_vec', ... 31 | 'have_feature_mips', ... 32 | 'have_feature_pardiso_legacy', ... 33 | 'have_feature_pardiso_object', ... 34 | 'have_feature_pardiso', ... 35 | 'mips', ... 36 | 'mipsver', ... 37 | 'mplinsolve', ... 38 | 'qps_mips', ... 39 | }; 40 | ex_fcns = { 41 | 'mips_example1', ... 42 | 'mips_example2', ... 43 | }; 44 | lib_t_fcns = { 45 | 'test_mips', ... 46 | 't_mips', ... 47 | 't_mips_pardiso', ... 48 | 't_mplinsolve', ... 49 | 't_qps_mips', ... 50 | }; 51 | % 'generate_mips_autodoc', ... 52 | 53 | 54 | in = struct(... 55 | 'function', struct(... 56 | 'destdir', 'functions', ... 57 | 'gh_base_url', 'https://github.com/MATPOWER/mips/blob/master', ... 58 | 'list', struct(... 59 | 'mod', {'mips', 'mips', 'mips'}, ... 60 | 'src_path', {'lib', 'lib/t', 'examples'}, ... 61 | 'names', {lib_fcns, lib_t_fcns, ex_fcns} ... 62 | ) ... 63 | ) ... 64 | ); 65 | 66 | %% create stubs and symlinks for reference manual 67 | generate_autodoc_stubs(in, sphinx_src_dir); 68 | generate_source_symlinks(in, [sphinx_src_dir 'matlab-source/'], '../../../../../'); 69 | -------------------------------------------------------------------------------- /docs/sphinx/Building-Docs.md: -------------------------------------------------------------------------------- 1 | How to Build the Documentation 2 | ============================== 3 | 4 | The documentation for this project is based on [Sphinx][1], a [Python][2]-based 5 | documentation processing package. The documentation source is written in the 6 | [reStructuredText][3] (rST) format and compiled to HTML and/or PDF formats. 7 | 8 | As part of [MATPOWER][4], the documentation for this project is normally 9 | built as a component of the overall MATPOWER documentation. However, the HTML 10 | version can be build separately by following the steps below. 11 | 12 | 1. Install [Python][2]. 13 | 14 | 2. Create and activate a Python [virtual environment][5]. *(optional, but recommended)* 15 | 16 | Unix/macOS 17 | ``` 18 | python3 -m venv sphinx-env 19 | source sphinx-env/bin/activate 20 | ``` 21 | 22 | Windows 23 | ``` 24 | python3 -m venv sphinx-env 25 | .\sphinx-env\Scripts\activate 26 | ``` 27 | 28 | Then confirm you're in the virtual environment: 29 | 30 | Unix/macOS 31 | ``` 32 | which python 33 | ``` 34 | 35 | Windows 36 | ``` 37 | where python 38 | ``` 39 | 40 | To leave the virtual environment: 41 | ``` 42 | deactivate 43 | ``` 44 | 45 | 3. Install [Sphinx][1], [sphinxcontrib-matlabdomain][6], [sphinx-tabs][7] and 46 | [sphinx-rtd-theme][8]. 47 | ``` 48 | pip install -U sphinx 49 | pip install -U sphinxcontrib-matlabdomain 50 | pip install -U sphinx-tabs 51 | pip install -U sphinx-rtd-theme 52 | ``` 53 | 54 | 4. Include [mp-docs-shared][9], a collection of files shared by all of the 55 | [Sphinx][1] documention for [MATPOWER][4], in the `source` directory. 56 | ``` 57 | cd docs/sphinx/source 58 | git clone https://github.com/MATPOWER/mp-docs-shared.git 59 | ``` 60 | 61 | 5. In the `docs/sphinx` directory, type: 62 | ``` 63 | make html 64 | ``` 65 | 66 | The resulting HTML documentation can be found in `docs/sphinx/build/html` and 67 | accessed by opening `docs/sphinx/build/html/index.html` in a web browser. 68 | 69 | 70 | ---- 71 | [1]: https://www.sphinx-doc.org 72 | [2]: https://python.org 73 | [3]: https://www.writethedocs.org/guide/writing/reStructuredText/ 74 | [4]: https://matpower.org 75 | [5]: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment 76 | [6]: https://pypi.org/project/sphinxcontrib-matlabdomain/ 77 | [7]: https://pypi.org/project/sphinx-tabs/ 78 | [8]: https://pypi.org/project/sphinx-rtd-theme/ 79 | [9]: https://github.com/MATPOWER/mp-docs-shared/ 80 | -------------------------------------------------------------------------------- /docs/other/MIPS-Release-Checklist.md: -------------------------------------------------------------------------------- 1 | MIPS Release Checklist 2 | ====================== 3 | 4 | 5 | Pre-release 6 | ----------- 7 | - Check [MIPS issue tracker](https://github.com/MATPOWER/mips/issues) 8 | and `untracked/MIPS-To-Do-List.md` for to do items. 9 | - Create & checkout new `prep-for-release` branch from latest `master`. 10 | - Release notes: 11 | - Make sure Release History in Appendix C of `MIPS-manual.tex` is 12 | up-to-date. 13 | - Create `docs/relnotes/MIPS-Release-Notes-#.#.md` document from 14 | Appendix C of `MIPS-manual.tex`. 15 | - Update date in Copyright line in: 16 | - `LICENSE` 17 | - `docs/sphinx/source/conf.py`. 18 | - Update version number and date in: 19 | - `mipsver.m` 20 | - `docs/sphinx/source/conf.py` 21 | - `lib/Contents.m` 22 | - `docs/relnotes/MIPS-Release-Notes-#.#.md` 23 | - `docs/src/MIPS-manual/MIPS-manual.tex` 24 | - title page 25 | - copyright (front page and LICENSE text) 26 | - Appendix C Release History 27 | - `\mipsver` (update `\mpver`, `\mptestver`, `\mpomver`, `\mostver` too) 28 | - Sphinx docs 29 | - `mp-docs-shared/preamble.tex.txt` - \mipsver 30 | - `mp-docs-shared/prolog.rst.txt` - in URL in raw-html for |MIPSman| 31 | - In `README.md` and `docs/src/MIPS-manual/MIPS-manual.tex` 32 | - update output of: 33 | - `test_mips` in Section 2.2 34 | - (may require `rmpath('/usr/local/pardiso/current')` first) 35 | - `mips_example2` in Section 3.2 (has version and date) 36 | - check for any highlighting `\hl` 37 | - Create new DOI for this version of the User's Manual 38 | - Go to https://doi.org/10.5281/zenodo.3236506 39 | - Click "New Version" to reserve new DOI for new version 40 | - Make updates for current version specific citations: 41 | - version number (3 places) 42 | - year 43 | - latest version DOI, current is: 10.5281/zenodo.15871404 44 | - (update here each time) 45 | ... in the following places ... 46 | - CITATION file 47 | - Citing ... section of README.md 48 | - Citing ... section of User's Manual 49 | - Citing ... section of website (not currently here) 50 | - Make updates for non-version specific citations: 51 | - search everywhere for 10.5281/zenodo.3236506 and update year 52 | - User's Manual 53 | - search citations in all other projects being updated simultaneously 54 | - MATPOWER-manual.tex 55 | - MP-Opt-Model-manual.tex 56 | - search everywhere for 10.5281/zenodo.3236519 and update year (MATPOWER User's Manual) 57 | - User's Manual 58 | - search everywhere for 10.5281/zenodo.3236535 and update year (MATPOWER Software) 59 | - User's Manual 60 | - Create `MIPS-manual.pdf` from `MIPS-manual.tex` and move to `docs`. 61 | - Add release notice with date and version in `CHANGES.md`. 62 | - Commit all changes to `prep-for-release`. 63 | - Push `prep-for-release` to GitHub. 64 | - Make sure CI checks are ok. 65 | - Make copy of `docs/MIPS-manual.pdf` named `MIPS-manual-x.x.pdf` 66 | - copy to `docs` directory of `matpower.org-static` git repo 67 | - update `MIPS-manual.pdf` symlink on `https://matpower.org/docs/` to point 68 | to new `MIPS-manual-x.x.pdf` (replaces existing current version) 69 | - `cd dev/projects/matpower.org-static/docs` 70 | - `rm MIPS-manual.pdf` 71 | - `ln -s ./MIPS-manual-x.x.pdf MIPS-manual.pdf` 72 | - commit & push, then pull to matpower.org 73 | - upload `MIPS-manual-x.x.pdf` to Zenodo and finish entry for "New Version" 74 | - update: 75 | - Publication date 76 | - Version 77 | - Identifiers: 78 | - version number in "identical to" 79 | - Add link on `https://matpower.org/doc/manuals/` page 80 | 81 | 82 | Release 83 | ------- 84 | - Merge latest `prep-for-release` into `master`. 85 | - Tag with version number, e.g. `1.5.2`. 86 | - Push `master` to GitHub. 87 | - Publish new release on GitHub: https://github.com/MATPOWER/mips/releases/new 88 | - use (possibly shortened) contents of `docs/relnotes/MIPS-Release-Notes-#.#.md` 89 | 90 | 91 | Post-release 92 | ------------ 93 | - Merge latest `master` into `release`. 94 | - Push `release` to GitHub. 95 | - In manual 96 | - update version to dev version 97 | - comment out date line so it uses current date 98 | -------------------------------------------------------------------------------- /docs/sphinx/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import sphinx_rtd_theme 14 | import re 15 | 16 | 17 | # -- Project information ----------------------------------------------------- 18 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 19 | 20 | project = 'MIPS' 21 | copyright = '2009-2025, Power Systems Engineering Research Center (PSERC)' 22 | author = 'Ray D. Zimmerman, Hongye Wang' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '1.5.2' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 30 | 31 | extensions = [ 32 | 'sphinxcontrib.matlab', 33 | 'sphinx.ext.autodoc', 34 | 'sphinx.ext.extlinks', 35 | 'sphinx.ext.napoleon', 36 | 'sphinx_rtd_theme', 37 | 'sphinx_tabs.tabs', 38 | ] 39 | matlab_src_dir = 'matlab-source' 40 | primary_domain = 'mat' 41 | 42 | templates_path = ['_templates'] 43 | exclude_patterns = [] 44 | 45 | 46 | # -- Options for HTML output ------------------------------------------------- 47 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 48 | 49 | html_theme = 'sphinx_rtd_theme' 50 | html_static_path = ['_static'] 51 | html_css_files = ['css/matpower.css'] 52 | 53 | 54 | # -- Options for Sphinx RTD Theme ------------------------------------------------ 55 | # See https://pypi.org/project/sphinx-rtd-theme/ 56 | # https://github.com/readthedocs/sphinx_rtd_theme 57 | # https://sphinx-rtd-theme.readthedocs.io/ 58 | # https://sphinx-rtd-theme.readthedocs.io/en/stable/configuring.html 59 | 60 | html_theme_options = { 61 | 'logo_only': False, 62 | 'display_version': True, 63 | 'prev_next_buttons_location': 'both', 64 | 'style_nav_header_background': '#568085', # medium dark teal 65 | } 66 | 67 | 68 | # -- Other Options ----------------------------------------------------------- 69 | 70 | matlab_short_links = True 71 | # matlab_auto_link = "basic" 72 | matlab_auto_link = "all" 73 | matlab_show_property_default_value = True 74 | matlab_show_property_specs = True 75 | # autoclass_content = 'both' # 'class', 'init', 'both' 76 | autodoc_member_order = 'bysource' # 'alphabetical', 'groupwise', 'bysource' 77 | napoleon_use_param = False 78 | napoleon_use_rtype = False 79 | napoleon_custom_sections = [ 80 | ('Input', 'params_style'), 81 | ('Inputs', 'params_style'), 82 | ('Output', 'params_style'), 83 | ('Outputs', 'params_style'), 84 | ] 85 | 86 | rst_prolog = """ 87 | .. include:: /mp-docs-shared/prolog.rst.txt 88 | """ 89 | extlinks = { 90 | # 'mostman': ('https://matpower.org/docs/MOST-manual-%s.pdf', 'MOST User''s Manual'), 91 | 'doi': ('https://doi.org/%s', 'doi: %s'), 92 | } 93 | 94 | numfig = True # enable numbered references 95 | numfig_format = { 96 | 'figure': 'Figure %s', 97 | 'code-block': 'Listing %s', 98 | 'section': 'Section %s' } 99 | highlight_language = 'octave' # 'matlab' has issues with '...' 100 | # e.g. y = fcn(x, ...) 101 | math_number_all = True 102 | math_eqref_format = '({number})' 103 | 104 | 105 | # -- MathJax Macro Setup ----------------------------------------------------- 106 | # -- based on https://stackoverflow.com/questions/9728292/creating-latex-math-macros-within-sphinx#comment124804327_60497853 107 | mathjax3_config = { 108 | 'loader': {'load': ['[tex]/upgreek']}, 109 | 'tex': {'packages': {'[+]': ['upgreek']}, 110 | 'macros': {}} # create empty 111 | } 112 | 113 | with open('mp-docs-shared/mathCmds.tex.txt', 'r') as f: 114 | for line in f: 115 | macros = re.findall(r'(?` to denote the path to this directory. 35 | 36 | 2. Add the following directories to your MATLAB or Octave path: 37 | * `/lib` 38 | * `/lib/t` 39 | * `/examples` 40 | 41 | 3. At the MATLAB/Octave prompt, type `test_mips` to run the test suite and 42 | verify that MIPS is properly installed and functioning. The result 43 | should resemble the following: 44 | ``` 45 | >> test_mips 46 | t_mplinsolve......ok (8 of 180 skipped) 47 | t_mips............ok 48 | t_mips_pardiso....ok (60 of 60 skipped) 49 | t_qps_mips........ok 50 | All tests successful (304 passed, 68 skipped of 372) 51 | Elapsed time 0.07 seconds. 52 | ``` 53 | 54 | Documentation 55 | ------------- 56 | 57 | There are two primary sources of documentation for MIPS. The first is 58 | the [MIPS User's Manual][7], which gives an overview of the capabilities 59 | and structure of MIPS and describes the formulations behind the code. It 60 | can be found in your MIPS distribution at `/docs/MIPS-manual.pdf` 61 | and the latest version is always available at: 62 | . 63 | 64 | And second is the built-in `help` command. As with the built-in 65 | functions and toolbox routines in MATLAB and Octave, you can type `help` 66 | followed by the name of a command or M-file to get help on that particular 67 | function. All of the M-files in MIPS have such documentation and this 68 | should be considered the main reference for the calling options for each 69 | function, namely: `mips`, `mipsver`, and `qps_mips`. 70 | 71 | 72 | Publications 73 | ------------ 74 | 75 | 1. H. Wang, C. E. Murillo-Sánchez, R. D. Zimmerman, R. J. Thomas, 76 | ["On Computational Issues of Market-Based Optimal Power Flow,"][10] 77 | *Power Systems, IEEE Transactions on*, vol. 22, no. 3, 78 | pp. 1185-1193, Aug. 2007. 79 | doi: [10.1109/TPWRS.2007.901301][10]. 80 | 81 | 2. H. Wang, *On the Computation and Application of Multi-period 82 | Security-constrained Optimal Power Flow for Real-time Electricity 83 | Market Operations*, Ph.D. thesis, Electrical and Computer 84 | Engineering, Cornell University, May 2007. 85 | 86 | 87 | [Citing MIPS][11] 88 | ----------------- 89 | 90 | We request that publications derived from the use of the MATPOWER 91 | Interior Point Solver (MIPS) explicitly acknowledge that fact by citing 92 | the following 2007 paper. 93 | 94 | > H. Wang, C. E. Murillo-Sánchez, R. D. Zimmerman, R. J. Thomas, "On 95 | Computational Issues of Market-Based Optimal Power Flow," *Power Systems, 96 | IEEE Transactions on*, vol. 22, no. 3, pp. 1185-1193, Aug. 2007. 97 | doi: [10.1109/TPWRS.2007.901301][10] 98 | 99 | The [MATPOWER Interior Point Solver (MIPS) User's Manual][7] should also be 100 | cited explicitly in work that refers to or is derived from its content. 101 | The citation and DOI can be version-specific or general, as appropriate. 102 | For version 1.5.2, use: 103 | 104 | > R. D. Zimmerman, H. Wang. *MATPOWER Interior Point Solver (MIPS) 105 | User's Manual, Version 1.5.2*. 2025. [Online]. 106 | Available: https://matpower.org/docs/MIPS-manual-1.5.2.pdf 107 | doi: [10.5281/zenodo.15871404](https://doi.org/10.5281/zenodo.15871404) 108 | 109 | For a version non-specific citation, use the following citation and DOI, 110 | with *\* replaced by the year of the most recent release: 111 | 112 | > R. D. Zimmerman, H. Wang. *MATPOWER Interior Point Solver (MIPS) 113 | User's Manual*. *\*. [Online]. 114 | Available: https://matpower.org/docs/MIPS-manual.pdf 115 | doi: [10.5281/zenodo.3236506][12] 116 | 117 | A list of versions of the User's Manual with release dates and 118 | version-specific DOI's can be found via the general DOI at 119 | https://doi.org/10.5281/zenodo.3236506. 120 | 121 | 122 | Contributing 123 | ------------ 124 | 125 | Please see our [contributing guidelines][8] for details on how to 126 | contribute to the project or report issues. 127 | 128 | License 129 | ------- 130 | 131 | MIPS is distributed under the [3-clause BSD license][9]. 132 | 133 | ---- 134 | [1]: https://github.com/MATPOWER/mips 135 | [2]: http://www.pserc.cornell.edu/tspopf/ 136 | [3]: https://github.com/MATPOWER/matpower 137 | [4]: https://www.mathworks.com/ 138 | [5]: https://octave.org 139 | [6]: https://github.com/MATPOWER/mptest 140 | [7]: docs/MIPS-manual.pdf 141 | [8]: CONTRIBUTING.md 142 | [9]: LICENSE 143 | [10]: https://doi.org/10.1109/TPWRS.2007.901301 144 | [11]: CITATION 145 | [12]: https://doi.org/10.5281/zenodo.3236506 146 | -------------------------------------------------------------------------------- /lib/qps_mips.m: -------------------------------------------------------------------------------- 1 | function [x, f, eflag, output, lambda] = qps_mips(H, c, A, l, u, xmin, xmax, x0, opt) 2 | % qps_mips - Quadratic Program Solver based on |MIPS>|. 3 | % :: 4 | % 5 | % [x, f, exitflag, output, lambda] = ... 6 | % qps_mips(H, c, A, l, u, xmin, xmax, x0, opt) 7 | % 8 | % x = qps_mips(H, c, A, l, u) 9 | % x = qps_mips(H, c, A, l, u, xmin, xmax) 10 | % x = qps_mips(H, c, A, l, u, xmin, xmax, x0) 11 | % x = qps_mips(H, c, A, l, u, xmin, xmax, x0, opt) 12 | % x = qps_mips(problem) 13 | % where problem is a struct with fields: 14 | % H, c, A, l, u, xmin, xmax, x0, opt 15 | % all fields are optional, except if H is missing or all zeros, 16 | % then c must *not* be missing or all zeros, and linear 17 | % constraints or variable bounds must be supplied 18 | % x = qps_mips(...) 19 | % [x, f] = qps_mips(...) 20 | % [x, f, exitflag] = qps_mips(...) 21 | % [x, f, exitflag, output] = qps_mips(...) 22 | % [x, f, exitflag, output, lambda] = qps_mips(...) 23 | % 24 | % A wrapper function providing a standardized interface for using mips, 25 | % the |MIPSname| (|MIPS>|), to solve the following QP (quadratic programming) 26 | % problem: 27 | % 28 | % .. math:: \min_\x f(\x) = \frac{1}{2} \trans{\x} \param{\cmat{H}} \x + \trans{\param{\rvec{c}}} \x 29 | % :label: eq_qps_mips_obj_fcn 30 | % 31 | % subject to 32 | % 33 | % .. math:: \param{\rvec{l}} \le \param{\cmat{A}} \x \le \param{\rvec{u}} 34 | % :label: eq_qps_mips_lin_constraint 35 | % .. math:: \param{\x}_\mathrm{min} \le \x \le \param{\x}_\mathrm{max} 36 | % :label: eq_qps_mips_var_bounds 37 | % 38 | % where :eq:`eq_qps_mips_obj_fcn`--:eq:`eq_qps_mips_var_bounds` are, 39 | % respectively, the objective function, linear constraints, and variable 40 | % bounds. 41 | % 42 | % Inputs: 43 | % : *(all optional except that, if* ``H`` *is missing or all zeros, then* 44 | % ``c`` *must not be missing or all zeros, and linear constraints or 45 | % variable bounds must be supplied)* 46 | % H (double) : *(optional, default all zeros)* matrix :math:`\param{\cmat{H}}` 47 | % *(possibly sparse)* of quadratic cost coefficients 48 | % c (double) : *(optional, default all zeros)* vector of linear cost coefficients 49 | % :math:`\param{\rvec{c}}` 50 | % A, l, u (double) : *(optional, respective defaults* 51 | % :math:`[empty, -\infty, +\infty]` *)* matrix :math:`\param{\cmat{A}}` 52 | % and vectors :math:`\param{\rvec{l}}` and :math:`\param{\rvec{u}}` 53 | % to define the linear constraints in :eq:`eq_qps_mips_lin_constraint` 54 | % xmin, xmax (double) : *(optional, respective defaults* 55 | % :math:`[-\infty, +\infty]` *)* lower and upper bounds, 56 | % :math:`\param{\x}_\mathrm{min}` and :math:`\param{\x}_\mathrm{max}`, 57 | % on the optimization variables :math:`\x` 58 | % x0 (double) : *(optional, default all zeros)* starting value of optimization vector :math:`\x` 59 | % opt (struct) : *(optional)* MIPS options structure (see :func:`mips` for details) 60 | % problem (struct) : The inputs can alternatively be supplied in a single 61 | % ``problem`` struct with fields corresponding to the input arguments 62 | % described above, namely, ``H``, ``c``, ``A``, ``l``, ``u``, ``x0``, 63 | % ``xmin``, ``xmax``, and ``opt`` 64 | % 65 | % Outputs: 66 | % x (double) : solution vector, :math:`\x` 67 | % f (double) : final objective function value, :math:`f(\x)` 68 | % exitflag (integer) : exit flag 69 | % 70 | % - 1 = first order optimality conditions satisfied 71 | % - 0 = maximum number of iterations reached 72 | % - -1 = numerically failed 73 | % output (struct) : output struct with fields: 74 | % 75 | % - ``iterations`` - number of iterations performed 76 | % - ``hist`` - struct array with trajectories of the following: 77 | % 78 | % - ``feascond``, ``gradcond``, ``compcond``, ``costcond``, 79 | % ``gamma``, ``stepsize``, ``obj``, ``alphap``, ``alphad`` 80 | % - ``message`` - exit message 81 | % lambda (struct) : struct containing the Langrange and Kuhn-Tucker 82 | % multipliers on the constraints, with fields: 83 | % 84 | % - ``mu_l`` - lower (left-hand) limit on linear constraints 85 | % - ``mu_u`` - upper (right-hand) limit on linear constraints 86 | % - ``lower`` - lower bound on optimization variables 87 | % - ``upper`` - upper bound on optimization variables 88 | % 89 | % Note the calling syntax is almost identical to that of :func:`quadprog` 90 | % from MathWorks' Optimization Toolbox. The main difference is that 91 | % the linear constraints are specified with ``A``, ``l``, ``u`` instead of 92 | % ``A``, ``B``, ``Aeq``, ``Beq``. 93 | % 94 | % **Example:** (problem from https://v8doc.sas.com/sashtml/iml/chap8/sect12.htm):: 95 | % 96 | % H = [ 1003.1 4.3 6.3 5.9; 97 | % 4.3 2.2 2.1 3.9; 98 | % 6.3 2.1 3.5 4.8; 99 | % 5.9 3.9 4.8 10 ]; 100 | % c = zeros(4,1); 101 | % A = [ 1 1 1 1; 102 | % 0.17 0.11 0.10 0.18 ]; 103 | % l = [1; 0.10]; 104 | % u = [1; Inf]; 105 | % xmin = zeros(4,1); 106 | % x0 = [1; 0; 0; 1]; 107 | % opt = struct('verbose', 2); 108 | % [x, f, s, out, lambda] = qps_mips(H, c, A, l, u, xmin, [], x0, opt); 109 | % 110 | % See also mips. 111 | 112 | % MIPS 113 | % Copyright (c) 2010-2024, Power Systems Engineering Research Center (PSERC) 114 | % by Ray Zimmerman, PSERC Cornell 115 | % 116 | % This file is part of MIPS. 117 | % Covered by the 3-clause BSD License (see LICENSE file for details). 118 | % See https://github.com/MATPOWER/mips for more info. 119 | 120 | %%----- input argument handling ----- 121 | %% gather inputs 122 | if nargin == 1 && isstruct(H) %% problem struct 123 | p = H; 124 | else %% individual args 125 | p = struct('H', H, 'c', c, 'A', A, 'l', l, 'u', u); 126 | if nargin > 5 127 | p.xmin = xmin; 128 | if nargin > 6 129 | p.xmax = xmax; 130 | if nargin > 7 131 | p.x0 = x0; 132 | if nargin > 8 133 | p.opt = opt; 134 | end 135 | end 136 | end 137 | end 138 | end 139 | 140 | %% define nx, set default values for H and c 141 | if ~isfield(p, 'H') || ~nnz(p.H) 142 | if (~isfield(p, 'A') || isempty(p.A)) && ... 143 | (~isfield(p, 'xmin') || isempty(p.xmin)) && ... 144 | (~isfield(p, 'xmax') || isempty(p.xmax)) 145 | error('qps_mips: LP problem must include constraints or variable bounds'); 146 | else 147 | if isfield(p, 'A') && ~isempty(p.A) 148 | nx = size(p.A, 2); 149 | elseif isfield(p, 'xmin') && ~isempty(p.xmin) 150 | nx = length(p.xmin); 151 | else % if isfield(p, 'xmax') && ~isempty(p.xmax) 152 | nx = length(p.xmax); 153 | end 154 | end 155 | p.H = sparse(nx, nx); 156 | else 157 | nx = size(p.H, 1); 158 | end 159 | if ~isfield(p, 'c') || isempty(p.c) 160 | p.c = zeros(nx, 1); 161 | end 162 | if ~isfield(p, 'x0') || isempty(p.x0) 163 | p.x0 = zeros(nx, 1); 164 | end 165 | 166 | %%----- run optimization ----- 167 | p.f_fcn = @(x)qp_f(x, p.H, p.c); 168 | [x, f, eflag, output, lambda] = mips(p); 169 | 170 | %%----- objective function ----- 171 | function [f, df, d2f] = qp_f(x, H, c) 172 | f = 0.5 * x' * H * x + c' * x; 173 | if nargout > 1 174 | df = H * x + c; 175 | if nargout > 2 176 | d2f = H; 177 | end 178 | end 179 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | Change history for MIPS 2 | ======================= 3 | 4 | 5 | Version 1.5.2 - *July 12, 2025* 6 | ------------------------------- 7 | 8 | #### 5/12/24 9 | - Release 1.5.2. 10 | - Move examples `mips_example1.m` and `mips_example2.m` from `lib/t` 11 | to their own `examples` directory. 12 | 13 | #### 5/10/24 14 | - Add feature detection function `have_feature_mips()`, providing 15 | implementation of `'mips'` tag for `have_feature()`. 16 | 17 | Version 1.5.1 - *May 10, 2024* 18 | ------------------------------ 19 | 20 | #### 5/10/24 21 | - Release 1.5.1. 22 | 23 | #### 4/16/24 24 | - Add `full_hist` option to enable saving in `output.hist` trajectories 25 | of `x`, `z`, `g`, `h`, `lam`, and `mu` (issue [#4][3]). 26 | 27 | #### 3/12/24 28 | - Add Sphinx-based [Reference documentation][2]. 29 | 30 | 31 | Version 1.5 - *Dec 12, 2022* 32 | ---------------------------- 33 | 34 | #### 12/12/22 35 | - Release 1.5. 36 | 37 | #### 10/28/22 38 | - Add to `mplinsolve()` the ability to return a struct containing the matrix 39 | LU factorization, and to reuse this pre-factored matrix to solve 40 | additional systems with different right-hand-sides by passing the struct 41 | in place of the A matrix to subsequent calls. 42 | - Add option to `mplinsolve()` to solve transposed systems by setting 43 | `opt.tr` to 1, including when providing the pre-factored matrix for 44 | the original, non-transposed system. 45 | 46 | 47 | Version 1.4 - *Oct 8, 2020* 48 | --------------------------- 49 | 50 | #### 10/8/20 51 | - Release 1.4. 52 | 53 | #### 9/23/20 54 | - Add feature detection functions for LU and PARDISO, defining tags 55 | `'lu_vec'`, `'pardiso_legacy'`, `'pardiso_object'` and `'pardiso'` 56 | for `have_feature()`. Requires MP-Test 7.1 or later. 57 | - Remove custom LU and PARDISO detection code from `mplinsolve` and 58 | test functions, and switch to using `have_feature()`. 59 | 60 | #### 8/20/20 61 | - In User's Manual, add missing `linsolver` option in Table 3-3. 62 | - In User's Manual, add Sections 4 Other Functions, 4.1 Linear System 63 | Solvers - mplinsolve, and move Section 3.3 Quadratic Programming 64 | Solver to 4.2. 65 | 66 | #### 8/18/20 67 | - Silence inadvertent output from `mplinsolve()` when called without 68 | `solver` input argument. 69 | - Fix fatal errors when `mplinsolve()` is called with `LU` solver and 70 | dense `A` matrix. 71 | 72 | #### 4/23/20 73 | - Remove additional `have_fcn()` dependencies in `mips()`, 74 | `t_mips_pardiso()` and `t_qps_mips()`. 75 | - **INCOMPATIBLE CHANGE**: Calling `mips()` with `opt.linsolver` 76 | set to `'PARDISO'` now results in a fatal error if PARDISO is not 77 | installed, rather than warning and continuing with the default 78 | linear solver. 79 | 80 | #### 8/15/19 81 | - Fix bug in initialization of `mu` that resulted in fatal error 82 | in `t_mips` for some versions of MATLAB (e.g. R2013b on Mac). 83 | 84 | 85 | Version 1.3.1 - *Jun 20, 2019* 86 | ------------------------------ 87 | 88 | #### 6/20/19 89 | - Release 1.3.1. 90 | - Add `CITATION` file. 91 | - Other miscellaneous documentation updates, e.g. MATPOWER website 92 | links updated to https://matpower.org. 93 | 94 | 95 | Version 1.3 - *Oct 30, 2018* 96 | ---------------------------- 97 | 98 | #### 10/30/18 99 | - Release 1.3. 100 | 101 | #### 9/10/18 102 | - Add support for PARDISO v6.x. 103 | 104 | #### 5/7/18 105 | - Ignore warnings from Octave 4.4 about calling `lu` with less 106 | than 4 outputs and a sparse input. 107 | 108 | #### 11/29/17 109 | - Fix typo preventing `pardiso.dparm` options from being set. 110 | - Fix incorrect use of PARDISO options in `t_mplinsolve()`. 111 | 112 | #### 3/16/17 113 | - Move `mplinsolve` PARDISO options to `opt.pardiso` in preparation 114 | for adding options for other solvers. 115 | - Add `mplinsolve` solver option `'LU'` for explicit LU decomposition 116 | with back substitution, with options in `opt.lu` for specifying the 117 | number of output arguments in call to `lu` (`opt.lu.nout`), 118 | whether to use permutation vectors or matrices (`opt.lu.vec`) and 119 | pivot threshold options (`opt.lu.thresh`). The following values for 120 | the `solver` argument act as shortcuts for specifying various 121 | combinations of options: `'LU3'`, `'LU3a'`, `'LU4'`, `'LU5'`, 122 | `'LU3m'`, `'LU3am'`, `'LU4m'`, `'LU5m'`. See `help mplinsolve` for 123 | details. *Thanks to Jose Luis Marin.* 124 | 125 | #### 12/21/16 126 | - Add [Travis-CI][1] integration. *Thanks to Richard Lincoln.* 127 | 128 | 129 | Version 1.2.2 - *Dec 16, 2016* (released with MATPOWER 6.0) 130 | ----------------------------------------------------------- 131 | 132 | #### 12/15/16 133 | - Moved development to GitHub: . 134 | 135 | #### 12/9/16 136 | - Renamed from MATLAB Interior Point Solver to MATPOWER Interior 137 | Point Solver. 138 | 139 | #### 12/6/16 140 | - Remove dependence of `t_mpsolve()` on presence of `have_fcn()` to 141 | detect PARDISO installation. 142 | 143 | #### 11/1/16 144 | - Released MATPOWER 6.0b2. 145 | 146 | 147 | Version 1.2.1 - *Jun 1, 2016* (released with MATPOWER 6.0b1) 148 | ------------------------------------------------------------ 149 | 150 | #### 3/27/15 151 | - Fixed issue where default value of `feastol` option was not being 152 | set correctly in `mips()` when called directly (or via `qps_mips()`) 153 | with `feastol = 0`. 154 | 155 | 156 | Version 1.2 - *Mar 20, 2015* (released with MATPOWER 5.1) 157 | --------------------------------------------------------- 158 | 159 | #### 3/19/15 160 | - Added support for using PARDISO as linear solver for 161 | computing interior-point update steps in MIPS, via new `mplinsolver()` 162 | function and `linsolver` option. 163 | 164 | #### 2/25/15 165 | - Switch to more permissive 3-clause BSD license from GPL 3.0. 166 | 167 | 168 | Version 1.1 - *Dec 17, 2014* (released with MATPOWER 5.0) 169 | --------------------------------------------------------- 170 | 171 | #### 12/2/14 172 | - Additional user-settable options: `xi`, `sigma`, `z0`, 173 | `alpha_min`, `rho_min`, `rho_max`, `mu_threshold` and `max_stepsize`. 174 | - **INCOMPATIBLE CHANGE**: The name of the option to `mips()` 175 | to specify the maximum number of step-size reductions when `step_control` 176 | is on was changed from `max_red` to `sc.red_it` for consistency with 177 | other MATPOWER options. 178 | 179 | 180 | Version 1.0.2 - *Nov 5, 2013* (released with MATPOWER 5.0b1, *Jul 1, 2014*) 181 | ------------------------------------------------------------------------- 182 | 183 | #### 11/5/13 184 | - Fixed a bug in MIPS where a near-singular matrix could produce 185 | an extremely large Newton step, resulting in incorrectly satisfying 186 | the relative feasibility criterion for successful termination. 187 | 188 | 189 | Version 1.0.1 - *Apr 30, 2012* 190 | ------------------------------ 191 | 192 | #### 4/30/12 193 | - Fixed fatal bug in MIPS for unconstrained, scalar problems. 194 | *Thanks to Han Na Gwon.* 195 | 196 | #### 12/14/11 197 | - Released MATPOWER 4.1. 198 | 199 | 200 | Version 1.0 - *Feb 7, 2011* (released with MATPOWER 4.0) 201 | -------------------------------------------------------- 202 | 203 | - _no change_ 204 | 205 | 206 | Version 1.0b5 - *Dec 13, 2010* (released with MATPOWER 4.0b5) 207 | ------------------------------------------------------------- 208 | 209 | - _no change_ 210 | 211 | 212 | Version 1.0b4 - *May 21, 2010* (released with MATPOWER 4.0b4) 213 | ------------------------------------------------------------- 214 | 215 | #### 5/10/10 216 | - Modified input args for Hessian evaluation function for MIPS. 217 | Requires `cost_mult` as 3rd argument. 218 | 219 | #### 4/27/10 220 | - Check for NaN's in update step. 221 | 222 | 223 | Version 1.0b3 - *Apr 19, 2010* (released with MATPOWER 4.0b3) 224 | ------------------------------------------------------------ 225 | 226 | #### 4/19/10 227 | - Changed licensing to GNU General Public license. See 228 | `LICENSE` and `COPYING` files for details. 229 | 230 | #### 4/6/10 231 | - GNU Octave compatibility! (tested with Octave 3.2.3) 232 | 233 | 234 | Version 1.0b2 - *Mar 19, 2010* (released with MATPOWER 4.0b2) 235 | ------------------------------------------------------------ 236 | 237 | #### 3/10/10 238 | - Added optional input arg to `mipsver()` function to 239 | trigger return of entire version struct with `Name`, `Version`, 240 | `Release` and `Date` (similar to MATLAB's `ver()` function). 241 | - Massive help text update to more closely match MathWorks 242 | conventions; function names in ALL CAPS, See also ..., Examples, etc. 243 | 244 | #### 3/8/10 245 | - Added `mipsver()`. 246 | 247 | #### 3/1/10 248 | - Added a version number and printing of MIPS version lines 249 | to verbose output. 250 | 251 | #### 2/25/10 252 | - Swapped `g` and `h` (`G` and `H`) in notation to match 253 | convention used in previously published stuff. 254 | 255 | #### 1/25/10 256 | - Added `qps_mips()`, with calling syntax similar to 257 | `quadprog()` from the Optimization Toolbox. The main difference 258 | from the `quadprog()` API is that the constraints are specified 259 | as`l <= A*x <= u`, instead of `A*x <= b` and `Aeq*x == beq`. 260 | 261 | #### 1/19/10 262 | - Renamed the pure-MATLAB interior point solver from PDIPM to 263 | MIPS (MATLAB Interior Point Solver). 264 | 265 | #### 1/18/10 266 | - Changed order of input args to `pdipm()`, added option 267 | for single input struct (like fmincon), more documentation, all 268 | constraints are now optional, returns `exitflag = -1` for 269 | `numerically failed`, output includes `message` field, `lambda` 270 | only includes relevant fields. Added tests for pdipm as 271 | standalone solver. 272 | 273 | #### 1/12/10 274 | - Added history field to the output with trajectories of obj, 275 | termination criterion, etc. 276 | 277 | #### 1/10/10 278 | - Added acknowledgement of port from Hongye Wang's code. 279 | 280 | 281 | Version 1.0b1 - *Dec 24, 2009* (released with MATPOWER 4.0b1) 282 | ------------------------------------------------------------- 283 | 284 | #### 11/4/09 285 | - Removed unnecessary `return` statement at end of all M-files. If 286 | anything it should be an `end` statement, but even that is 287 | optional, so we just let functions get terminated by the 288 | end-of-file or another function declaration. 289 | 290 | #### 6/5/09 291 | - Break out of algorithm is any element of `x` becomes NaN. 292 | 293 | #### 3/24/09 294 | - Added step-controlled PDIPM variant. 295 | 296 | #### 3/19/09 297 | - Fixed some bugs in default args. 298 | 299 | #### 3/13/09 300 | - Added a pure MATLAB implementation of the PDIPM (primal-dual 301 | interior point method) solver. 302 | 303 | ---- 304 | [1]: https://travis-ci.org 305 | [2]: https://matpower.org/doc/mips/ 306 | [3]: https://github.com/MATPOWER/mips/issues/4 307 | -------------------------------------------------------------------------------- /lib/t/t_mips_pardiso.m: -------------------------------------------------------------------------------- 1 | function t_mips_pardiso(quiet) 2 | % t_mips_pardiso - Tests of mips, MIPS NLP solver, using PARDISO as linear solver. 3 | % :: 4 | % 5 | % t_mips_pardiso 6 | % t_mips_pardiso(quiet) 7 | 8 | % MIPS 9 | % Copyright (c) 2010-2024, Power Systems Engineering Research Center (PSERC) 10 | % by Ray Zimmerman, PSERC Cornell 11 | % 12 | % This file is part of MIPS. 13 | % Covered by the 3-clause BSD License (see LICENSE file for details). 14 | % See https://github.com/MATPOWER/mips for more info. 15 | 16 | if nargin < 1 17 | quiet = 0; 18 | end 19 | 20 | num_tests = 60; 21 | 22 | t_begin(num_tests, quiet); 23 | 24 | if have_feature('pardiso') 25 | 26 | opt = struct('linsolver', 'PARDISO'); 27 | 28 | t = 'unconstrained banana function : '; 29 | %% from MATLAB Optimization Toolbox's bandem.m 30 | f_fcn = @(x)f2(x); 31 | x0 = [-1.9; 2]; 32 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], struct('verbose', 2)); 33 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], opt); 34 | t_is(s, 1, 13, [t 'success']); 35 | t_is(x, [1; 1], 13, [t 'x']); 36 | t_is(f, 0, 13, [t 'f']); 37 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 38 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 39 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 40 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 41 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 42 | 43 | t = 'unconstrained 3-d quadratic : '; 44 | %% from http://www.akiti.ca/QuadProgEx0Constr.html 45 | f_fcn = @(x)f3(x); 46 | x0 = [0; 0; 0]; 47 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], struct('verbose', 2)); 48 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], opt); 49 | t_is(s, 1, 13, [t 'success']); 50 | t_is(x, [3; 5; 7], 13, [t 'x']); 51 | t_is(f, -244, 13, [t 'f']); 52 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 53 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 54 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 55 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 56 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 57 | 58 | t = 'constrained 4-d QP : '; 59 | %% from https://v8doc.sas.com/sashtml/iml/chap8/sect12.htm 60 | f_fcn = @(x)f4(x); 61 | x0 = [1; 0; 0; 1]; 62 | A = [ 1 1 1 1; 63 | 0.17 0.11 0.10 0.18 ]; 64 | l = [1; 0.10]; 65 | u = [1; Inf]; 66 | xmin = zeros(4,1); 67 | % [x, f, s, out, lam] = mips(f_fcn, x0, A, l, u, xmin, [], [], [], struct('verbose', 2)); 68 | [x, f, s, out, lam] = mips(f_fcn, x0, A, l, u, xmin, [], [], [], opt); 69 | t_is(s, 1, 13, [t 'success']); 70 | t_is(x, [0; 2.8; 0.2; 0]/3, 6, [t 'x']); 71 | t_is(f, 3.29/3, 6, [t 'f']); 72 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 73 | t_is(lam.mu_l, [6.58;0]/3, 6, [t 'lam.mu_l']); 74 | t_is(lam.mu_u, [0;0], 13, [t 'lam.mu_u']); 75 | t_is(lam.lower, [2.24;0;0;1.7667], 4, [t 'lam.lower']); 76 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 77 | 78 | % %% check with quadprog (for dev testing only) 79 | % H = [ 1003.1 4.3 6.3 5.9; 80 | % 4.3 2.2 2.1 3.9; 81 | % 6.3 2.1 3.5 4.8; 82 | % 5.9 3.9 4.8 10 ]; 83 | % c = zeros(4,1); 84 | % [x, f, s, out, lam] = quadprog(H,c,-A(2,:), -0.10, A(1,:), 1, xmin); 85 | % t_is(s, 1, 13, [t 'success']); 86 | % t_is(x, [0; 2.8; 0.2; 0]/3, 6, [t 'x']); 87 | % t_is(f, 3.29/3, 6, [t 'f']); 88 | % t_is(lam.eqlin, -6.58/3, 6, [t 'lam.eqlin']); 89 | % t_is(lam.ineqlin, 0, 13, [t 'lam.ineqlin']); 90 | % t_is(lam.lower, [2.24;0;0;1.7667], 4, [t 'lam.lower']); 91 | % t_is(lam.upper, [0;0;0;0], 13, [t 'lam.upper']); 92 | 93 | t = 'constrained 2-d nonlinear : '; 94 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#2-dimensional_example 95 | f_fcn = @(x)f5(x); 96 | gh_fcn = @(x)gh5(x); 97 | hess_fcn = @(x, lam, cost_mult)hess5(x, lam, cost_mult); 98 | x0 = [1.1; 0]; 99 | xmin = zeros(2, 1); 100 | % xmax = 3 * ones(2, 1); 101 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, [], gh_fcn, hess_fcn, struct('verbose', 2)); 102 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, [], gh_fcn, hess_fcn, opt); 103 | t_is(s, 1, 13, [t 'success']); 104 | t_is(x, [1; 1], 6, [t 'x']); 105 | t_is(f, -2, 6, [t 'f']); 106 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 107 | t_is(lam.ineqnonlin, [0;0.5], 6, [t 'lam.ineqnonlin']); 108 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 109 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 110 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 111 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 112 | % %% check with fmincon (for dev testing only) 113 | % % fmoptions = optimset('Algorithm', 'interior-point'); 114 | % % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], xmin, [], gh_fcn, fmoptions); 115 | % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], [], [], gh_fcn); 116 | % t_is(s, 1, 13, [t 'success']); 117 | % t_is(x, [1; 1], 4, [t 'x']); 118 | % t_is(f, -2, 6, [t 'f']); 119 | % t_is(lam.ineqnonlin, [0;0.5], 6, [t 'lam.ineqnonlin']); 120 | 121 | t = 'constrained 3-d nonlinear : '; 122 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#3-dimensional_example 123 | f_fcn = @(x)f6(x); 124 | gh_fcn = @(x)gh6(x); 125 | hess_fcn = @(x, lam, cost_mult)hess6(x, lam, cost_mult); 126 | x0 = [1; 1; 0]; 127 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], gh_fcn, hess_fcn, struct('verbose', 2, 'comptol', 1e-9)); 128 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], gh_fcn, hess_fcn, opt); 129 | t_is(s, 1, 13, [t 'success']); 130 | t_is(x, [1.58113883; 2.23606798; 1.58113883], 6, [t 'x']); 131 | t_is(f, -5*sqrt(2), 6, [t 'f']); 132 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 133 | t_is(lam.ineqnonlin, [0;sqrt(2)/2], 7, [t 'lam.ineqnonlin']); 134 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 135 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 136 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 137 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 138 | 139 | t = 'constrained 3-d nonlinear (struct) : '; 140 | p = struct('f_fcn', f_fcn, 'x0', x0, 'gh_fcn', gh_fcn, 'hess_fcn', hess_fcn); 141 | [x, f, s, out, lam] = mips(p); 142 | t_is(s, 1, 13, [t 'success']); 143 | t_is(x, [1.58113883; 2.23606798; 1.58113883], 6, [t 'x']); 144 | t_is(f, -5*sqrt(2), 6, [t 'f']); 145 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 146 | t_is(lam.ineqnonlin, [0;sqrt(2)/2], 7, [t 'lam.ineqnonlin']); 147 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 148 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 149 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 150 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 151 | 152 | t = 'constrained 4-d nonlinear : '; 153 | %% Hock & Schittkowski test problem #71 154 | f_fcn = @(x)f7(x); 155 | gh_fcn = @(x)gh7(x); 156 | hess_fcn = @(x, lam, sigma)hess7(x, lam, sigma); 157 | x0 = [1; 5; 5; 1]; 158 | xmin = ones(4, 1); 159 | xmax = 5 * xmin; 160 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, xmax, gh_fcn, hess_fcn, struct('verbose', 2, 'comptol', 1e-9)); 161 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, xmax, gh_fcn, hess_fcn, opt); 162 | t_is(s, 1, 13, [t 'success']); 163 | t_is(x, [1; 4.7429994; 3.8211503; 1.3794082], 6, [t 'x']); 164 | t_is(f, 17.0140173, 6, [t 'f']); 165 | t_is(lam.eqnonlin, 0.1614686, 5, [t 'lam.eqnonlin']); 166 | t_is(lam.ineqnonlin, 0.55229366, 5, [t 'lam.ineqnonlin']); 167 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 168 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 169 | t_is(lam.lower, [1.08787121024; 0; 0; 0], 5, [t 'lam.lower']); 170 | t_is(lam.upper, zeros(size(x)), 7, [t 'lam.upper']); 171 | 172 | else 173 | t_skip(num_tests, 'PARDISO not available.'); 174 | end 175 | 176 | t_end; 177 | 178 | 179 | % %%----- eg99 : linearly constrained fmincon example, mips can't solve ----- 180 | % function [f, df, d2f] = eg99(x) 181 | % f = -x(1)*x(2)*x(3); 182 | % df = -[ x(2)*x(3); 183 | % x(1)*x(3); 184 | % x(1)*x(2) ]; 185 | % d2f = -[ 0 x(3) x(2); 186 | % x(3) 0 x(1); 187 | % x(2) x(1) 0 ]; 188 | % end 189 | % 190 | % x0 = [10;10;10]; 191 | % A = [1 2 2]; 192 | % l = 0; 193 | % u = 72; 194 | % fmoptions = optimset('Display', 'testing'); 195 | % fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point'); 196 | % [x, f, s, out, lam] = fmincon(f_fcn, x0, [-A; A], [-l; u], [], [], [], [], [], fmoptions); 197 | % t_is(x, [24; 12; 12], 13, t); 198 | % t_is(f, -3456, 13, t); 199 | 200 | 201 | %% unconstrained banana function 202 | %% from MATLAB Optimization Toolbox's bandem.m 203 | function [f, df, d2f] = f2(x) 204 | a = 100; 205 | f = a*(x(2)-x(1)^2)^2+(1-x(1))^2; 206 | df = [ 4*a*(x(1)^3 - x(1)*x(2)) + 2*x(1)-2; 207 | 2*a*(x(2) - x(1)^2) ]; 208 | d2f = 4*a*[ 3*x(1)^2 - x(2) + 1/(2*a), -x(1); 209 | -x(1) 1/2 ]; 210 | 211 | 212 | %% unconstrained 3-d quadratic 213 | %% from http://www.akiti.ca/QuadProgEx0Constr.html 214 | function [f, df, d2f] = f3(x) 215 | H = [5 -2 -1; -2 4 3; -1 3 5]; 216 | c = [2; -35; -47]; 217 | f = 1/2 * x'*H*x + c'*x + 5; 218 | df = H*x + c; 219 | d2f = H; 220 | 221 | 222 | %% constrained 4-d QP 223 | %% from https://v8doc.sas.com/sashtml/iml/chap8/sect12.htm 224 | function [f, df, d2f] = f4(x) 225 | H = [ 1003.1 4.3 6.3 5.9; 226 | 4.3 2.2 2.1 3.9; 227 | 6.3 2.1 3.5 4.8; 228 | 5.9 3.9 4.8 10 ]; 229 | c = zeros(4,1); 230 | f = 1/2 * x'*H*x + c'*x; 231 | df = H*x + c; 232 | d2f = H; 233 | 234 | 235 | %% constrained 2-d nonlinear 236 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#2-dimensional_example 237 | function [f, df, d2f] = f5(x) 238 | c = -[1; 1]; 239 | f = c'*x; 240 | df = c; 241 | d2f = zeros(2,2); 242 | 243 | function [h, g, dh, dg] = gh5(x) 244 | h = [ -1 -1; 1 1] * x.^2 + [1; -2]; 245 | dh = 2 * [-x(1) x(1); -x(2) x(2)]; 246 | g = []; dg = []; 247 | 248 | function Lxx = hess5(x, lam, cost_mult) 249 | mu = lam.ineqnonlin; 250 | Lxx = 2*[-1 1]*mu*eye(2); 251 | 252 | 253 | %% constrained 3-d nonlinear 254 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#3-dimensional_example 255 | function [f, df, d2f] = f6(x) 256 | f = -x(1)*x(2) - x(2)*x(3); 257 | df = -[x(2); x(1)+x(3); x(2)]; 258 | d2f = -[0 1 0; 1 0 1; 0 1 0]; 259 | 260 | function [h, g, dh, dg] = gh6(x) 261 | h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10]; 262 | dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)]; 263 | g = []; dg = []; 264 | 265 | function Lxx = hess6(x, lam, cost_mult) 266 | if nargin < 3, cost_mult = 1; end 267 | mu = lam.ineqnonlin; 268 | Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ... 269 | [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu]; 270 | 271 | 272 | %% constrained 4-d nonlinear 273 | %% Hock & Schittkowski test problem #71 274 | function [f, df, d2f] = f7(x) 275 | f = x(1)*x(4)*sum(x(1:3)) + x(3); 276 | df = [ x(1)*x(4) + x(4)*sum(x(1:3)); 277 | x(1)*x(4); 278 | x(1)*x(4) + 1; 279 | x(1)*sum(x(1:3)) ]; 280 | d2f = sparse([ 2*x(4) x(4) x(4) 2*x(1)+x(2)+x(3); 281 | x(4) 0 0 x(1); 282 | x(4) 0 0 x(1); 283 | 2*x(1)+x(2)+x(3) x(1) x(1) 0 284 | ]); 285 | 286 | function [h, g, dh, dg] = gh7(x) 287 | g = sum(x.^2) - 40; 288 | h = -prod(x) + 25; 289 | dg = 2*x; 290 | dh = -prod(x)./x; 291 | 292 | function Lxx = hess7(x, lam, sigma) 293 | if nargin < 3, sigma = 1; end 294 | lambda = lam.eqnonlin; 295 | mu = lam.ineqnonlin; 296 | [f, df, d2f] = f7(x); 297 | Lxx = sigma * d2f + lambda*2*speye(4) - ... 298 | mu*sparse([ 0 x(3)*x(4) x(2)*x(4) x(2)*x(3); 299 | x(3)*x(4) 0 x(1)*x(4) x(1)*x(3); 300 | x(2)*x(4) x(1)*x(4) 0 x(1)*x(2); 301 | x(2)*x(3) x(1)*x(3) x(1)*x(2) 0 ]); 302 | -------------------------------------------------------------------------------- /lib/t/t_mips.m: -------------------------------------------------------------------------------- 1 | function t_mips(quiet) 2 | % t_mips - Tests of mips, MIPS NLP solver. 3 | % :: 4 | % 5 | % t_mips 6 | % t_mips(quiet) 7 | 8 | % MIPS 9 | % Copyright (c) 2010-2024, Power Systems Engineering Research Center (PSERC) 10 | % by Ray Zimmerman, PSERC Cornell 11 | % 12 | % This file is part of MIPS. 13 | % Covered by the 3-clause BSD License (see LICENSE file for details). 14 | % See https://github.com/MATPOWER/mips for more info. 15 | 16 | if nargin < 1 17 | quiet = 0; 18 | end 19 | 20 | num_tests = 60; 21 | 22 | t_begin(num_tests, quiet); 23 | 24 | t = 'unconstrained banana function : '; 25 | %% from MATLAB Optimization Toolbox's bandem.m 26 | f_fcn = @(x)f2(x); 27 | x0 = [-1.9; 2]; 28 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], struct('verbose', 2)); 29 | [x, f, s, out, lam] = mips(f_fcn, x0); 30 | t_is(s, 1, 13, [t 'success']); 31 | t_is(x, [1; 1], 13, [t 'x']); 32 | t_is(f, 0, 13, [t 'f']); 33 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 34 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 35 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 36 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 37 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 38 | 39 | t = 'unconstrained 3-d quadratic : '; 40 | %% from http://www.akiti.ca/QuadProgEx0Constr.html 41 | f_fcn = @(x)f3(x); 42 | x0 = [0; 0; 0]; 43 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], [], [], struct('verbose', 2)); 44 | [x, f, s, out, lam] = mips(f_fcn, x0); 45 | t_is(s, 1, 13, [t 'success']); 46 | t_is(x, [3; 5; 7], 13, [t 'x']); 47 | t_is(f, -244, 13, [t 'f']); 48 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 49 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 50 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 51 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 52 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 53 | 54 | t = 'constrained 4-d QP : '; 55 | %% from https://v8doc.sas.com/sashtml/iml/chap8/sect12.htm 56 | f_fcn = @(x)f4(x); 57 | x0 = [1; 0; 0; 1]; 58 | A = [ 1 1 1 1; 59 | 0.17 0.11 0.10 0.18 ]; 60 | l = [1; 0.10]; 61 | u = [1; Inf]; 62 | xmin = zeros(4,1); 63 | % [x, f, s, out, lam] = mips(f_fcn, x0, A, l, u, xmin, [], [], [], struct('verbose', 2)); 64 | [x, f, s, out, lam] = mips(f_fcn, x0, A, l, u, xmin); 65 | t_is(s, 1, 13, [t 'success']); 66 | t_is(x, [0; 2.8; 0.2; 0]/3, 6, [t 'x']); 67 | t_is(f, 3.29/3, 6, [t 'f']); 68 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 69 | t_is(lam.mu_l, [6.58;0]/3, 6, [t 'lam.mu_l']); 70 | t_is(lam.mu_u, [0;0], 13, [t 'lam.mu_u']); 71 | t_is(lam.lower, [2.24;0;0;1.7667], 4, [t 'lam.lower']); 72 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 73 | 74 | % %% check with quadprog (for dev testing only) 75 | % H = [ 1003.1 4.3 6.3 5.9; 76 | % 4.3 2.2 2.1 3.9; 77 | % 6.3 2.1 3.5 4.8; 78 | % 5.9 3.9 4.8 10 ]; 79 | % c = zeros(4,1); 80 | % [x, f, s, out, lam] = quadprog(H,c,-A(2,:), -0.10, A(1,:), 1, xmin); 81 | % t_is(s, 1, 13, [t 'success']); 82 | % t_is(x, [0; 2.8; 0.2; 0]/3, 6, [t 'x']); 83 | % t_is(f, 3.29/3, 6, [t 'f']); 84 | % t_is(lam.eqlin, -6.58/3, 6, [t 'lam.eqlin']); 85 | % t_is(lam.ineqlin, 0, 13, [t 'lam.ineqlin']); 86 | % t_is(lam.lower, [2.24;0;0;1.7667], 4, [t 'lam.lower']); 87 | % t_is(lam.upper, [0;0;0;0], 13, [t 'lam.upper']); 88 | 89 | t = 'constrained 2-d nonlinear : '; 90 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#2-dimensional_example 91 | f_fcn = @(x)f5(x); 92 | gh_fcn = @(x)gh5(x); 93 | hess_fcn = @(x, lam, cost_mult)hess5(x, lam, cost_mult); 94 | x0 = [1.1; 0]; 95 | xmin = zeros(2, 1); 96 | % xmax = 3 * ones(2, 1); 97 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, [], gh_fcn, hess_fcn, struct('verbose', 2)); 98 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, [], gh_fcn, hess_fcn); 99 | t_is(s, 1, 13, [t 'success']); 100 | t_is(x, [1; 1], 6, [t 'x']); 101 | t_is(f, -2, 6, [t 'f']); 102 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 103 | t_is(lam.ineqnonlin, [0;0.5], 6, [t 'lam.ineqnonlin']); 104 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 105 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 106 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 107 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 108 | % %% check with fmincon (for dev testing only) 109 | % % fmoptions = optimset('Algorithm', 'interior-point'); 110 | % % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], xmin, [], gh_fcn, fmoptions); 111 | % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], [], [], gh_fcn); 112 | % t_is(s, 1, 13, [t 'success']); 113 | % t_is(x, [1; 1], 4, [t 'x']); 114 | % t_is(f, -2, 6, [t 'f']); 115 | % t_is(lam.ineqnonlin, [0;0.5], 6, [t 'lam.ineqnonlin']); 116 | 117 | t = 'constrained 3-d nonlinear : '; 118 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#3-dimensional_example 119 | f_fcn = @(x)f6(x); 120 | gh_fcn = @(x)gh6(x); 121 | hess_fcn = @(x, lam, cost_mult)hess6(x, lam, cost_mult); 122 | x0 = [1; 1; 0]; 123 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], gh_fcn, hess_fcn, struct('verbose', 2, 'comptol', 1e-9)); 124 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], [], [], gh_fcn, hess_fcn); 125 | t_is(s, 1, 13, [t 'success']); 126 | t_is(x, [1.58113883; 2.23606798; 1.58113883], 6, [t 'x']); 127 | t_is(f, -5*sqrt(2), 6, [t 'f']); 128 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 129 | t_is(lam.ineqnonlin, [0;sqrt(2)/2], 7, [t 'lam.ineqnonlin']); 130 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 131 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 132 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 133 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 134 | % %% check with fmincon (for dev testing only) 135 | % % fmoptions = optimset('Algorithm', 'interior-point'); 136 | % % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], xmin, [], gh_fcn, fmoptions); 137 | % [x, f, s, out, lam] = fmincon(f_fcn, x0, [], [], [], [], [], [], gh_fcn); 138 | % t_is(s, 1, 13, [t 'success']); 139 | % t_is(x, [1.58113883; 2.23606798; 1.58113883], 4, [t 'x']); 140 | % t_is(f, -5*sqrt(2), 8, [t 'f']); 141 | % t_is(lam.ineqnonlin, [0;sqrt(2)/2], 8, [t 'lam.ineqnonlin']); 142 | 143 | t = 'constrained 3-d nonlinear (struct) : '; 144 | p = struct('f_fcn', f_fcn, 'x0', x0, 'gh_fcn', gh_fcn, 'hess_fcn', hess_fcn); 145 | [x, f, s, out, lam] = mips(p); 146 | t_is(s, 1, 13, [t 'success']); 147 | t_is(x, [1.58113883; 2.23606798; 1.58113883], 6, [t 'x']); 148 | t_is(f, -5*sqrt(2), 6, [t 'f']); 149 | t_is(out.hist(end).compcond, 0, 6, [t 'compcond']); 150 | t_is(lam.ineqnonlin, [0;sqrt(2)/2], 7, [t 'lam.ineqnonlin']); 151 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 152 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 153 | t_is(lam.lower, zeros(size(x)), 13, [t 'lam.lower']); 154 | t_is(lam.upper, zeros(size(x)), 13, [t 'lam.upper']); 155 | 156 | t = 'constrained 4-d nonlinear : '; 157 | %% Hock & Schittkowski test problem #71 158 | f_fcn = @(x)f7(x); 159 | gh_fcn = @(x)gh7(x); 160 | hess_fcn = @(x, lam, sigma)hess7(x, lam, sigma); 161 | x0 = [1; 5; 5; 1]; 162 | xmin = ones(4, 1); 163 | xmax = 5 * xmin; 164 | % [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, xmax, gh_fcn, hess_fcn, struct('verbose', 2, 'comptol', 1e-9)); 165 | [x, f, s, out, lam] = mips(f_fcn, x0, [], [], [], xmin, xmax, gh_fcn, hess_fcn); 166 | t_is(s, 1, 13, [t 'success']); 167 | t_is(x, [1; 4.7429994; 3.8211503; 1.3794082], 6, [t 'x']); 168 | t_is(f, 17.0140173, 6, [t 'f']); 169 | t_is(lam.eqnonlin, 0.1614686, 5, [t 'lam.eqnonlin']); 170 | t_is(lam.ineqnonlin, 0.55229366, 5, [t 'lam.ineqnonlin']); 171 | t_ok(isempty(lam.mu_l), [t 'lam.mu_l']); 172 | t_ok(isempty(lam.mu_u), [t 'lam.mu_u']); 173 | t_is(lam.lower, [1.08787121024; 0; 0; 0], 5, [t 'lam.lower']); 174 | t_is(lam.upper, zeros(size(x)), 7, [t 'lam.upper']); 175 | 176 | t_end; 177 | 178 | 179 | % %%----- eg99 : linearly constrained fmincon example, mips can't solve ----- 180 | % function [f, df, d2f] = eg99(x) 181 | % f = -x(1)*x(2)*x(3); 182 | % df = -[ x(2)*x(3); 183 | % x(1)*x(3); 184 | % x(1)*x(2) ]; 185 | % d2f = -[ 0 x(3) x(2); 186 | % x(3) 0 x(1); 187 | % x(2) x(1) 0 ]; 188 | % end 189 | % 190 | % x0 = [10;10;10]; 191 | % A = [1 2 2]; 192 | % l = 0; 193 | % u = 72; 194 | % fmoptions = optimset('Display', 'testing'); 195 | % fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point'); 196 | % [x, f, s, out, lam] = fmincon(f_fcn, x0, [-A; A], [-l; u], [], [], [], [], [], fmoptions); 197 | % t_is(x, [24; 12; 12], 13, t); 198 | % t_is(f, -3456, 13, t); 199 | 200 | 201 | %% unconstrained banana function 202 | %% from MATLAB Optimization Toolbox's bandem.m 203 | function [f, df, d2f] = f2(x) 204 | a = 100; 205 | f = a*(x(2)-x(1)^2)^2+(1-x(1))^2; 206 | df = [ 4*a*(x(1)^3 - x(1)*x(2)) + 2*x(1)-2; 207 | 2*a*(x(2) - x(1)^2) ]; 208 | d2f = 4*a*[ 3*x(1)^2 - x(2) + 1/(2*a), -x(1); 209 | -x(1) 1/2 ]; 210 | 211 | 212 | %% unconstrained 3-d quadratic 213 | %% from http://www.akiti.ca/QuadProgEx0Constr.html 214 | function [f, df, d2f] = f3(x) 215 | H = [5 -2 -1; -2 4 3; -1 3 5]; 216 | c = [2; -35; -47]; 217 | f = 1/2 * x'*H*x + c'*x + 5; 218 | df = H*x + c; 219 | d2f = H; 220 | 221 | 222 | %% constrained 4-d QP 223 | %% from https://v8doc.sas.com/sashtml/iml/chap8/sect12.htm 224 | function [f, df, d2f] = f4(x) 225 | H = [ 1003.1 4.3 6.3 5.9; 226 | 4.3 2.2 2.1 3.9; 227 | 6.3 2.1 3.5 4.8; 228 | 5.9 3.9 4.8 10 ]; 229 | c = zeros(4,1); 230 | f = 1/2 * x'*H*x + c'*x; 231 | df = H*x + c; 232 | d2f = H; 233 | 234 | 235 | %% constrained 2-d nonlinear 236 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#2-dimensional_example 237 | function [f, df, d2f] = f5(x) 238 | c = -[1; 1]; 239 | f = c'*x; 240 | df = c; 241 | d2f = zeros(2,2); 242 | 243 | function [h, g, dh, dg] = gh5(x) 244 | h = [ -1 -1; 1 1] * x.^2 + [1; -2]; 245 | dh = 2 * [-x(1) x(1); -x(2) x(2)]; 246 | g = []; dg = []; 247 | 248 | function Lxx = hess5(x, lam, cost_mult) 249 | mu = lam.ineqnonlin; 250 | Lxx = 2*[-1 1]*mu*eye(2); 251 | 252 | 253 | %% constrained 3-d nonlinear 254 | %% from https://en.wikipedia.org/wiki/Nonlinear_programming#3-dimensional_example 255 | function [f, df, d2f] = f6(x) 256 | f = -x(1)*x(2) - x(2)*x(3); 257 | df = -[x(2); x(1)+x(3); x(2)]; 258 | d2f = -[0 1 0; 1 0 1; 0 1 0]; 259 | 260 | function [h, g, dh, dg] = gh6(x) 261 | h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10]; 262 | dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)]; 263 | g = []; dg = []; 264 | 265 | function Lxx = hess6(x, lam, cost_mult) 266 | if nargin < 3, cost_mult = 1; end 267 | mu = lam.ineqnonlin; 268 | Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ... 269 | [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu]; 270 | 271 | 272 | %% constrained 4-d nonlinear 273 | %% Hock & Schittkowski test problem #71 274 | function [f, df, d2f] = f7(x) 275 | f = x(1)*x(4)*sum(x(1:3)) + x(3); 276 | df = [ x(1)*x(4) + x(4)*sum(x(1:3)); 277 | x(1)*x(4); 278 | x(1)*x(4) + 1; 279 | x(1)*sum(x(1:3)) ]; 280 | d2f = sparse([ 2*x(4) x(4) x(4) 2*x(1)+x(2)+x(3); 281 | x(4) 0 0 x(1); 282 | x(4) 0 0 x(1); 283 | 2*x(1)+x(2)+x(3) x(1) x(1) 0 284 | ]); 285 | 286 | function [h, g, dh, dg] = gh7(x) 287 | g = sum(x.^2) - 40; 288 | h = -prod(x) + 25; 289 | dg = 2*x; 290 | dh = -prod(x)./x; 291 | 292 | function Lxx = hess7(x, lam, sigma) 293 | if nargin < 3, sigma = 1; end 294 | lambda = lam.eqnonlin; 295 | mu = lam.ineqnonlin; 296 | [f, df, d2f] = f7(x); 297 | Lxx = sigma * d2f + lambda*2*speye(4) - ... 298 | mu*sparse([ 0 x(3)*x(4) x(2)*x(4) x(2)*x(3); 299 | x(3)*x(4) 0 x(1)*x(4) x(1)*x(3); 300 | x(2)*x(4) x(1)*x(4) 0 x(1)*x(2); 301 | x(2)*x(3) x(1)*x(3) x(1)*x(2) 0 ]); 302 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | MIPS Contributors Guide 2 | ======================= 3 | 4 | 5 | Getting Involved 6 | ---------------- 7 | 8 | [MIPS][1] and [MATPOWER][2] are community efforts and your involvement 9 | is greatly appreciated. 10 | We are always looking for help in identifying and fixing bugs, writing test 11 | cases, improving documentation, answering queries on the mailing lists, 12 | enhancing existing functionality and implementing new features that fit 13 | within the general scope of the project. 14 | 15 | Please take a moment to review this document before contributing, as it 16 | helps to communicate your respect for the time and efforts of the MIPS 17 | developer community managing and developing this open source project. 18 | 19 | 20 | Repository Organization 21 | ----------------------- 22 | 23 | This repository, for the MIPS distribution, is organized in the 24 | following directories: 25 | - `docs` - User's Manual 26 | - `lib` - software that implements MIPS's core functions 27 | 28 | This repository is also included in the core MATPOWER repository as a 29 | subrepository using [`git subrepo`][4]. 30 | 31 | 32 | Mailing Lists 33 | ------------- 34 | 35 | Your participation is welcomed on the two mailing lists for MATPOWER and MIPS 36 | users and developers, [MATPOWER-L][5] and [MATPOWER-DEV-L][6], respectively. 37 | We can always use help in answering questions from newer users. 38 | 39 | 40 | Reporting a Bug 41 | --------------- 42 | 43 | The [MIPS issue tracker][7] is the preferred channel for reporting bugs or 44 | submitting code changes (pull requests). A good bug report is extremely 45 | helpful and benefits the entire community, so if you find a bug, including 46 | a mistake in the documentation, please report it. 47 | 48 | 1. **Confirm it is a bug.** You should be able to demonstrate that it 49 | is an error caused by the code in this repository. If it is simply that 50 | you do not understand a result you are getting, ask a question on the 51 | [MATPOWER discussion mailing list][5] instead of submitting an issue 52 | *(after searching [the archives][8] to see if your question has already 53 | been answered, of course)*. 54 | 55 | 2. **Check if it has already been reported or fixed.** Make sure the bug 56 | still exists by attempting to reproduce it using the latest `master` 57 | branch in the repository. Search the issues on GitHub to make sure it has 58 | not already been reported. 59 | 60 | 3. **Isolate the problem.** Create a reduced test case with no external 61 | dependencies, if possible, that demonstrates the problem, so others can 62 | easily reproduce it. The simpler the case the better. 63 | 64 | 4. **Submit an issue that includes a detailed report.** A good bug report 65 | will avoid the need for the developers to track you down for more information. 66 | - Use an accurate, descriptive title for your issue. 67 | - Describe your environment - better yet, include the output of `ver` 68 | and `mipsver` on your system. 69 | - Include a few lines of code or attach a script file that reproduces 70 | the bug. 71 | - Describe the result you got and what you expected. 72 | - Select "bug" under "Labels". 73 | 74 | _**Note:** Bugs or issues related to core MATPOWER functions should be 75 | submitted to the main [MATPOWER issue tracker][9]._ 76 | 77 | 78 | Reviewing Issues 79 | ---------------- 80 | 81 | If you see an issue or bug report submitted by someone else, please consider 82 | helping out by attempting to reproduce the issue on your system. Report your 83 | experience in a comment on the issue. Even if you are not comfortable 84 | submitting a patch to fix it, any information you can add to help the 85 | developers locate a solution is greatly appreciated. Simply leave your 86 | comments on the issue. The same goes for review of pull requests, which 87 | are discussed below. 88 | 89 | 90 | Submitting Additions or Modifications to the Code 91 | ------------------------------------------------- 92 | 93 | Code contributions are a great help and are always welcome. This includes 94 | bug fixes, enhancements to existing functionality, new features or tests, 95 | and even edits to the included documentation. It is always a good idea to 96 | discuss your ideas first on the [MATPOWER developer mailing list][6], especially 97 | for larger or more complex contributions. 98 | 99 | Contributions should be submitted as pull requests, as described below. 100 | Before submitting your pull request, please make sure you have tested 101 | your changes and that they follow the [MATPOWER developer guidelines][10]. 102 | 103 | ### Getting started 104 | 105 | #### Step 1 : [Set Up Git][11]. 106 | 107 | Make sure git knows your name and email address: 108 | 109 | ```bash 110 | git config --global user.name "Random Citizen" 111 | git config --global user.email "random.citizen@example.com" 112 | ``` 113 | 114 | #### Step 2 : [Fork][12] the repository. 115 | 116 | Click "Fork" on the [repository page][1] on GitHub to create your own fork 117 | of the project. 118 | 119 | #### Step 3 : Clone 120 | 121 | Check out your copy locally and configure the remotes: 122 | 123 | ```bash 124 | # clone your fork of the repo into the current directory 125 | git clone https://github.com//mips.git 126 | # go to the newly cloned directory 127 | cd mips 128 | # assign the original repo to a remote called "upstream" 129 | git remote add upstream https://github.com/MATPOWER/mips.git 130 | ``` 131 | 132 | ### Making your changes 133 | 134 | #### Step 4 : Update 135 | 136 | If it has been a while since you first made your clone, get all of the 137 | latest changes from the upstream repository: 138 | 139 | ```bash 140 | git checkout master 141 | git pull upstream master 142 | ``` 143 | 144 | #### Step 5 : Branch 145 | 146 | Create a new topic branch where you can work on your new feature, change 147 | or fix. Always create it from an up-to-date `master` branch: 148 | 149 | ```bash 150 | git checkout -b 151 | ``` 152 | 153 | #### Step 6 : Commit 154 | 155 | Edit your local copy of the files to implement your feature, change or fix. 156 | Then commit your changes in logical chunks. Do not combine multiple logical 157 | changes in a single commit. And please adhere to the guidlines below for 158 | commit messages. 159 | 160 | Add and commit: 161 | 162 | ```bash 163 | git add my/changed/files 164 | git commit 165 | ``` 166 | 167 | Writing good commit messages is important. A commit message should describe 168 | what changed and why. Follow these guidelines when writing one: 169 | 170 | 1. The first line should be 50 characters or less and contain a short 171 | description of the change. Begin with a capitalized imperative verb, 172 | for example, "Fix issue #4", not "Fixed issue #4" or "Fixes issue #4". 173 | All other words in this description should be in lowercase with the 174 | exception of proper nouns, acronyms, and references to code, such as 175 | function or variable names. 176 | 2. Keep the second line blank. 177 | 3. Wrap all other lines at 72 columns. 178 | 179 | If your patch fixes an open issue, the issue should be referenced in the 180 | first line of the commit message with the issue number preceded by a hash 181 | symbol (`#`), e.g. `Fix #4, Q limit violations` and at the end of the 182 | message with the full URL. Use the `Fixes:` prefix for bug fixes. For 183 | other references use `Refs:`. For example, a good commit message might 184 | look something like: 185 | 186 | ```text 187 | Fix issue #4, Q limit violations in CPF. 188 | 189 | More detailed explanatory text, if necessary. Wrap it to about 72 190 | characters or so. In some contexts, the first line is treated as the 191 | subject of an email and the rest of the text as the body. The blank 192 | line separating the summary from the body is critical (unless you omit 193 | the body entirely); tools like rebase can get confused if you run the 194 | two together. 195 | 196 | Further paragraphs come after blank lines. 197 | 198 | - Bullet points are okay, too. 199 | 200 | - Typically a hyphen or asterisk is used for the bullet, followed by a 201 | single space, with blank lines in between, but conventions vary here. 202 | 203 | - Use a hanging indent 204 | 205 | Fixes: https://github.com/MATPOWER/mips/issues/4 206 | Refs: https://www.mail-archive.com/matpower-l@cornell.edu/msg05557.html 207 | Refs: https://github.com/MATPOWER/mips/pull/5 208 | ``` 209 | 210 | #### Step 7 : Test 211 | 212 | Bug fixes and features **should come with tests**, either added to the 213 | appropriate existing test function in `lib/t`, or in a new test function 214 | with a descriptive name beginning with `t_`, in which case it should also 215 | be added to `test_mips.m`. See the documentation for [MP-Test][3] and 216 | the existing MIPS test files (e.g. [`t_mips`](lib/t/t_mips.m)) for 217 | examples of how to write tests. 218 | 219 | You can run your tests by typing the name of your test function at the 220 | MATLAB or Octave prompt, or `test_mips` to run the entire test suite. 221 | 222 | ### Sharing your changes 223 | 224 | #### Step 8 : Rebase 225 | 226 | Use `git rebase` (not `git merge`) to sync your work with the upstream 227 | development branch from time to time, and especially before pushing. 228 | 229 | ```bash 230 | git fetch upstream 231 | git rebase upstream/master 232 | ``` 233 | 234 | And use Git's [interactive rebase][13] feature to tidy up your commits, if 235 | necessary, *before* making them public. See [this article][14] for some 236 | helpful background on `git rebase` vs. `git merge`. 237 | 238 | #### Step 9 : Push 239 | 240 | Push your topic branch up to your fork on GitHub. 241 | 242 | ```bash 243 | git push origin 244 | ``` 245 | 246 | #### Step 10 : [Open a Pull Request][15] 247 | 248 | Open a pull request against the `master` branch, by going to the GitHub page 249 | for your fork (`https://github.com//mips`), and selecting 250 | your topic branch. Click the "Pull Request" button and fill out the form 251 | using a clear, accurate title and description. 252 | 253 | _**IMPORTANT:** By submitting a pull request, you represent that you have 254 | the right to license your contribution to PSERC and the community, and 255 | agree by submitting the patch that your contributions are licensed under 256 | the [3-clause BSD license][16]._ 257 | 258 | #### Step 11 : Discuss and update 259 | 260 | You will probably get feedback or requests for changes to your pull request. 261 | This is a normal part of the submission process, so don't be surprised or 262 | discouraged. 263 | 264 | To make changes to an existing pull request, make the changes to your branch. 265 | When you push that branch to your fork, GitHub will automatically update the 266 | pull request. Each time the pull request is updated it triggers a CI 267 | (continuous integration) test run which results in a check mark or an 268 | X next to the commit on the pull request page and next to the pull request 269 | name in the issue tracker, indicating whether or not all tests passed. 270 | 271 | After your pull request has been reviewed and approved by a MATPOWER 272 | Collaborator, it can be merged into the upstream MIPS repository. Once 273 | this has happened the pull request is closed and your contributions are 274 | part of the project and available to the world! Congratulations and many 275 | thanks! 276 | 277 | 278 | ### Git Workflow and Branching Model 279 | 280 | We use [GitHub Flow][18], meaning that the `master` branch should always 281 | be ready for release and all new work is done in descriptively named 282 | branches off of `master`, which are then reviewed via pull requests. The 283 | only addition is that we do still have a `release` branch that always 284 | points to the latest versioned release. We also use tags like `6.0` to 285 | tag each release. 286 | 287 | 288 | Licensing 289 | --------- 290 | 291 | By submitting a pull request, you represent that you have the right to 292 | license your contribution to PSERC and the community, and agree by 293 | submitting the patch that your contributions are licensed under the 294 | [3-clause BSD license][16]. 295 | 296 | 297 | Thanks 298 | ------ 299 | 300 | We would like to express our appreciation to everyone who has contributed to 301 | the MIPS project and community for helping to make it a useful tool for 302 | the optimization and power systems communities. **Thank you!** 303 | 304 | --- 305 | 306 | [1]: https://github.com/MATPOWER/mips 307 | [2]: https://github.com/MATPOWER/matpower 308 | [3]: https://github.com/MATPOWER/mptest 309 | [4]: https://github.com/ingydotnet/git-subrepo 310 | [5]: https://matpower.org/mailing-lists/#discusslist 311 | [6]: https://matpower.org/mailing-lists/#devlist 312 | [7]: https://github.com/MATPOWER/mips/issues 313 | [8]: https://www.mail-archive.com/matpower-l@cornell.edu/ 314 | [9]: https://github.com/MATPOWER/matpower/issues 315 | [10]: https://github.com/MATPOWER/matpower/blob/master/docs/MATPOWER-dev-guide.md 316 | [11]: https://help.github.com/articles/set-up-git/ 317 | [12]: https://help.github.com/articles/fork-a-repo/ 318 | [13]: https://help.github.com/articles/interactive-rebase 319 | [14]: https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa#.7gmldhj6m 320 | [15]: https://help.github.com/articles/about-pull-requests/ 321 | [16]: LICENSE 322 | [18]: https://scottchacon.com/2011/08/31/github-flow.html 323 | -------------------------------------------------------------------------------- /lib/mplinsolve.m: -------------------------------------------------------------------------------- 1 | function [x, f] = mplinsolve(A, b, solver, opt) 2 | % mplinsolve - Solve A * x = b using specified solver. 3 | % :: 4 | % 5 | % x = mplinsolve(A, b) 6 | % x = mplinsolve(A, b, solver) 7 | % x = mplinsolve(A, b, solver, opt) 8 | % x = mplinsolve(factors, b, ...) 9 | % factors = mplinsolve(A) 10 | % factors = mplinsolve(A, [], ...) 11 | % [x, factors] = mplinsolve(A, b, 'lu' ...) 12 | % 13 | % Solves the linear system of equations ``A * x == b`` for ``x`` 14 | % using the selected solver. 15 | % 16 | % Inputs: 17 | % A (double): sparse matrix 18 | % factors (struct) : contains (e.g. LU) factors of ``A`` from previous 19 | % call to mplinsolve, with a ``type`` field to identify which of the 20 | % following sets of additional fields are included: 21 | % 22 | % ======== ================= ======================================== 23 | % ``type`` add'l fields description 24 | % ======== ================= ======================================== 25 | % 1 ``L, U, p, qa`` 3 output Gilbert-Peierls, permutation vectors 26 | % 2 ``L, U, P, Qa`` 3 output Gilbert-Peierls, permutation matrices 27 | % 3 ``L, U, p, q`` 4 output UMFPACK, permutation vectors 28 | % 4 ``L, U, P, Q`` 4 output UMFPACK, permutation matrices 29 | % 5 ``L, U, p, q, R`` same as 3, with row scaling 30 | % 6 ``L, U, P, Q, R`` same as 4, with row scaling 31 | % ======== ================= ======================================== 32 | % b (double) : RHS vector (or full matrix) 33 | % solver (char array) : *(optional, default* ``''`` *)* selected linear 34 | % system solver 35 | % 36 | % - ``''`` -- use default solver, currently this is 37 | % always the built-in backslash operator 38 | % - ``'\'`` -- built-in backslash operator 39 | % - ``'LU'`` -- use explicit LU decomposition and back substitution 40 | % 41 | % The following are also provided as short-cuts, with less 42 | % overhead and thus better performance on small systems, as 43 | % alternatives for ``'LU'`` with the following options: 44 | % 45 | % =========== =============== ============== ================ 46 | % ``solver`` ``opt.lu.nout`` ``opt.lu.vec`` ``opt.lu.thresh`` 47 | % =========== =============== ============== ================ 48 | % ``'LU3'`` 3 1 1.0 49 | % ``'LU3a'`` 3 1 50 | % ``'LU4'`` 4 1 51 | % ``'LU5'`` 5 1 52 | % ``'LU3m'`` 3 0 1.0 53 | % ``'LU3am'`` 3 0 54 | % ``'LU4m'`` 4 0 55 | % ``'LU5m'`` 5 0 56 | % =========== =============== ============== ================ 57 | % - ``'PARDISO'`` -- PARDISO 58 | % opt (struct) : options for certain solvers (e.g. :func:`lu` and PARDISO), 59 | % with fields: 60 | % 61 | % - ``lu`` : struct of options to determine form of call to :func:`lu` 62 | % solver, with the following possible fields *(default value in 63 | % parens)*: 64 | % 65 | % - ``nout`` *(4)* - number of output args for call to :func:`lu`, 66 | % UMFPACK is used for 4 or 5 output args, Gilbert-Peierls 67 | % algorithm with AMD ordering for 3 output args. 68 | % - ``vec`` *(1)* - use permutation vectors instead of matrices 69 | % (permutation matrices used by default for MATLAB < 7.3) 70 | % - ``thresh`` - pivot threshold, see ``help lu`` for details 71 | % - ``pardiso`` : struct of PARDISO options *(default shown in parens)*, 72 | % see PARDISO documentation for details 73 | % 74 | % - ``verbose`` *(0)* - true or false 75 | % - ``mtype`` *(11, i.e. real and nonsymmetric)* - matrix type 76 | % - ``solver`` *(0, i.e. sparse direct)* - solver method 77 | % - ``iparm`` *([])* - :math:`n \by 2` matrix of integer parameters 78 | % 1st, 2nd columns are index, value of parameter respectively 79 | % - ``dparm`` *([])* - :math:`n \by 2` matrix of double parameters 80 | % 1st, 2nd columns are index, value of parameter respectively 81 | % - ``tr`` *(0)* : if true, solve transposed system ``A' * x = b`` 82 | % 83 | % Outputs: 84 | % x : solution vector (or matrix) satisfying ``A * x == b`` 85 | % factors : see description under Inputs 86 | 87 | % MIPS 88 | % Copyright (c) 2015-2024, Power Systems Engineering Research Center (PSERC) 89 | % by Ray Zimmerman, PSERC Cornell 90 | % 91 | % This file is part of MIPS. 92 | % Covered by the 3-clause BSD License (see LICENSE file for details). 93 | % See https://github.com/MATPOWER/mips for more info. 94 | 95 | if nargin < 4 96 | opt = []; 97 | if nargin < 3 98 | solver = ''; 99 | end 100 | end 101 | 102 | %% solve transpose? 103 | if isfield(opt, 'tr') 104 | tr = opt.tr; 105 | else 106 | tr = 0; 107 | end 108 | have_f = isstruct(A); 109 | have_b = nargin >= 2 && ~isempty(b); 110 | is_LU = length(solver) >= 2 && all(solver(1:2) == 'LU'); 111 | if ~is_LU && ~have_b 112 | solver = 'LU'; 113 | is_LU = 1; 114 | end 115 | is_LU = is_LU || have_f; 116 | 117 | %% prepare LU factors, if necessary 118 | if have_f 119 | f = A; %% factors provided 120 | elseif is_LU %% perform factorization if it's LU & we have A (not factors) 121 | switch solver 122 | case 'LU3' %% 3 output LU: Gilbert-Peierls alg, perm vec, 1.0 piv thresh 123 | q = amd(A); %% permutation vector for AMD reordering 124 | if issparse(A) 125 | [L, U, p] = lu(A(q,q), 1.0, 'vector'); 126 | else 127 | [L, U, p] = lu(A(q,q), 'vector'); 128 | end 129 | f = struct('type', 1, 'L', L, 'U', U, 'p', p, 'qa', q); 130 | case 'LU3a' %% 3 output LU: Gilbert-Peierls alg, permutation vectors 131 | q = amd(A); %% permutation vector for AMD reordering 132 | [L, U, p] = lu(A(q,q), 'vector'); 133 | f = struct('type', 1, 'L', L, 'U', U, 'p', p, 'qa', q); 134 | case 'LU4' %% 4 output LU: UMFPACK, permutation vectors 135 | [L, U, p, q] = lu(A, 'vector'); 136 | f = struct('type', 3, 'L', L, 'U', U, 'p', p, 'q', q); 137 | case 'LU5' %% 5 output LU: UMFPACK w/row scaling, permutation vectors 138 | [L, U, p, q, R] = lu(A, 'vector'); 139 | f = struct('type', 5, 'L', L, 'U', U, 'p', p, 'q', q, 'R', R); 140 | case 'LU3m' %% 3 output LU: Gilbert-Peierls alg, perm mat, 1.0 piv thresh 141 | Q = sparse(amd(A), 1:size(A, 1), 1); %% permutation matrix for AMD reordering 142 | if issparse(A) 143 | [L, U, P] = lu(Q'*A*Q, 1.0); 144 | else 145 | [L, U, P] = lu(Q'*A*Q); 146 | end 147 | f = struct('type', 2, 'L', L, 'U', U, 'P', P, 'Qa', Q); 148 | case 'LU3am' %% 3 output LU: Gilbert-Peierls alg, permutation matrices 149 | Q = sparse(amd(A), 1:size(A, 1), 1); %% permutation matrix for AMD reordering 150 | [L, U, P] = lu(Q'*A*Q); 151 | f = struct('type', 2, 'L', L, 'U', U, 'P', P, 'Qa', Q); 152 | case 'LU4m' %% 4 output LU: UMFPACK, permutation matrices 153 | [L, U, P, Q] = lu(A); 154 | f = struct('type', 4, 'L', L, 'U', U, 'P', P, 'Q', Q); 155 | case 'LU5m' %% 5 output LU: UMFPACK w/row scaling, permutation matrices 156 | [L, U, P, Q, R] = lu(A); 157 | f = struct('type', 6, 'L', L, 'U', U, 'P', P, 'Q', Q, 'R', R); 158 | case 'LU' %% explicit LU, with options struct 159 | %% default options 160 | nout = 4; %% 4 output args, UMFPACK 161 | if ~issparse(A) 162 | nout = 3; 163 | end 164 | vec = have_feature('lu_vec'); %% use permulation vectors, if available 165 | thresh = []; %% use default pivot threshold 166 | if isfield(opt, 'lu') 167 | opt_lu = opt.lu; 168 | if isfield(opt_lu, 'nout') 169 | nout = opt_lu.nout; 170 | end 171 | if isfield(opt_lu, 'vec') 172 | vec = opt_lu.vec; 173 | end 174 | if isfield(opt_lu, 'thresh') 175 | thresh = opt_lu.thresh; 176 | end 177 | end 178 | %% call the appropriate form 179 | switch nout 180 | case 3 %% 3 output args: Gilbert-Peierls algorithm, with AMD reordering 181 | q = amd(A); %% permutation vector for AMD reordering 182 | n = size(A, 1); 183 | if vec 184 | if isempty(thresh) 185 | [L, U, p] = lu(A(q,q), 'vector'); 186 | else 187 | [L, U, p] = lu(A(q,q), thresh, 'vector'); 188 | end 189 | f = struct('type', 1, 'L', L, 'U', U, 'p', p, 'qa', q); 190 | else 191 | Q = sparse(q, 1:n, 1); %% permutation matrix for AMD reordering 192 | if isempty(thresh) 193 | [L, U, P] = lu(Q'*A*Q); 194 | else 195 | [L, U, P] = lu(Q'*A*Q, thresh); 196 | end 197 | f = struct('type', 2, 'L', L, 'U', U, 'P', P, 'Qa', Q); 198 | end 199 | case 4 %% 4 output args: UMFPACK 200 | if vec 201 | [L, U, p, q] = lu(A, 'vector'); 202 | f = struct('type', 3, 'L', L, 'U', U, 'p', p, 'q', q); 203 | else 204 | [L, U, P, Q] = lu(A); 205 | f = struct('type', 4, 'L', L, 'U', U, 'P', P, 'Q', Q); 206 | end 207 | case 5 %% 5 output args: UMFPACK w/row scaling 208 | if vec 209 | [L, U, p, q, R] = lu(A, 'vector'); 210 | f = struct('type', 5, 'L', L, 'U', U, 'p', p, 'q', q, 'R', R); 211 | else 212 | [L, U, P, Q, R] = lu(A); 213 | f = struct('type', 6, 'L', L, 'U', U, 'P', P, 'Q', Q, 'R', R); 214 | end 215 | end 216 | end 217 | end 218 | 219 | %% solve system 220 | if have_b 221 | if is_LU %% use LU factors 222 | if tr %% solve transposed system 223 | switch f.type 224 | case 1 %% 3 output LU: Gilbert-Peierls alg, perm vectors 225 | x = zeros(size(f.L, 1), 1); 226 | x(f.qa(f.p)) = f.L' \ ( f.U' \ b(f.qa) ); 227 | case 2 %% 3 output LU: Gilbert-Peierls alg, perm matrices 228 | x = f.Qa * f.P' * ( f.L' \ (f.U' \ (f.Qa' * b)) ); 229 | case 3 %% 4 output LU: UMFPACK, perm vectors 230 | x = zeros(size(f.L, 1), 1); 231 | x(f.p) = f.L' \ ( f.U' \ b(f.q) ); 232 | case 4 %% 4 output LU: UMFPACK, perm matrices 233 | x = f.P' * ( f.L' \ (f.U' \ (f.Q' * b)) ); 234 | case 5 %% 5 output LU: UMFPACK w/row scaling, perm vectors 235 | x = f.R(f.p, :) \ (f.L' \ ( f.U' \ b(f.q) )); 236 | case 6 %% 5 output LU: UMFPACK w/row scaling, perm vectors 237 | x = f.R \ (f.P' * ( f.L' \ (f.U' \ (f.Q' * b))) ); 238 | end 239 | else %% solve non-transposed system 240 | switch f.type 241 | case 1 %% 3 output LU: Gilbert-Peierls alg, perm vectors 242 | x = zeros(size(f.L, 1), 1); 243 | x(f.qa) = f.U \ ( f.L \ b(f.qa(f.p)) ); 244 | case 2 %% 3 output LU: Gilbert-Peierls alg, perm matrices 245 | x = f.Qa * ( f.U \ (f.L \ (f.P * f.Qa' * b)) ); 246 | case 3 %% 4 output LU: UMFPACK, perm vectors 247 | x = zeros(size(f.L, 1), 1); 248 | x(f.q) = f.U \ ( f.L \ b(f.p) ); 249 | case 4 %% 4 output LU: UMFPACK, perm matrices 250 | x = f.Q * ( f.U \ (f.L \ (f.P * b)) ); 251 | case 5 %% 5 output LU: UMFPACK w/row scaling, perm vectors 252 | x = zeros(size(f.L, 1), 1); 253 | x(f.q) = f.U \ ( f.L \ (f.R(:, f.p) \ b)); 254 | case 6 %% 5 output LU: UMFPACK w/row scaling, perm vectors 255 | x = f.Q * ( f.U \ (f.L \ (f.P * (f.R \ b))) ); 256 | end 257 | end 258 | else %% not LU 259 | if tr %% use transposed system 260 | A = A'; 261 | end 262 | 263 | switch solver 264 | case {'', '\'} %% use built-in \ operator 265 | x = A \ b; 266 | case {'PARDISO'} 267 | %% set default options 268 | verbose = false; 269 | mtype = 11; 270 | pardiso_solver = 0; 271 | 272 | %% override if provided via opt 273 | if ~isempty(opt) && isfield(opt, 'pardiso') 274 | if isfield(opt.pardiso, 'verbose') && opt.pardiso.verbose 275 | verbose = true; 276 | end 277 | if isfield(opt.pardiso, 'mtype') 278 | mtype = opt.pardiso.mtype; 279 | end 280 | if isfield(opt.pardiso, 'solver') 281 | pardiso_solver = opt.pardiso.solver; 282 | end 283 | end 284 | 285 | %% begin setup and solve 286 | v6 = have_feature('pardiso_object'); 287 | if v6 %% PARDISO v6+ 288 | id = 1; 289 | p = pardiso(id, mtype, pardiso_solver); 290 | if verbose 291 | p.verbose(); 292 | end 293 | else %% PARDISO v5 294 | p = pardisoinit(mtype, pardiso_solver); 295 | end 296 | if ~isempty(opt) && isfield(opt, 'pardiso') 297 | if isfield(opt.pardiso, 'iparm') && ~isempty(opt.pardiso.iparm) 298 | p.iparm(opt.pardiso.iparm(:, 1)) = opt.pardiso.iparm(:, 2); 299 | end 300 | if isfield(opt.pardiso, 'dparm') && ~isempty(opt.pardiso.dparm) 301 | p.dparm(opt.pardiso.dparm(:, 1)) = opt.pardiso.dparm(:, 2); 302 | end 303 | end 304 | if v6 || abs(mtype) == 2 || mtype == 6 %% need non-zero diagonal 305 | nx = size(A, 1); 306 | if abs(mtype) == 2 || mtype == 6 %% symmetric 307 | myeps = 1e-14; 308 | A = tril(A); 309 | else %% non-symmetric 310 | myeps = 1e-8; 311 | end 312 | A = A + myeps * speye(nx, nx); 313 | end 314 | if v6 315 | p.factorize(id, A); 316 | x = p.solve(id, A, b); 317 | p.free(id); 318 | p.clear(); 319 | else 320 | p = pardisoreorder(A, p, verbose); 321 | p = pardisofactor(A, p, verbose); 322 | [x, p] = pardisosolve(A, b, p, verbose); 323 | pardisofree(p); 324 | end 325 | otherwise 326 | warning('mplinsolve: ''%s'' is not a valid value for SOLVER, using default.', solver); 327 | x = A \ b; 328 | end 329 | end 330 | end 331 | 332 | %% return only factors 333 | if ~have_b 334 | x = f; 335 | end 336 | -------------------------------------------------------------------------------- /lib/mips.m: -------------------------------------------------------------------------------- 1 | function [x, f, eflag, output, lambda] = mips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt) 2 | % mips - MATPOWER Interior Point Solver (|MIPS>|). 3 | % :: 4 | % 5 | % [x, f, exitflag, output, lambda] = ... 6 | % mips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt); 7 | % 8 | % x = mips(f_fcn, x0) 9 | % x = mips(f_fcn, x0, A, l) 10 | % x = mips(f_fcn, x0, A, l, u) 11 | % x = mips(f_fcn, x0, A, l, u, xmin) 12 | % x = mips(f_fcn, x0, A, l, u, xmin, xmax) 13 | % x = mips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn) 14 | % x = mips(f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt) 15 | % x = mips(problem) 16 | % where problem is a struct with fields: 17 | % f_fcn, x0, A, l, u, xmin, xmax, gh_fcn, hess_fcn, opt 18 | % all fields except f_fcn and x0 are optional 19 | % x = mips(...) 20 | % [x, f] = mips(...) 21 | % [x, f, exitflag] = mips(...) 22 | % [x, f, exitflag, output] = mips(...) 23 | % [x, f, exitflag, output, lambda] = mips(...) 24 | % 25 | % Primal-dual interior point method for NLP (nonlinear programming). 26 | % Minimize a function :math:`f(\x)` beginning from a starting point 27 | % ``x0``, subject to optional linear and nonlinear constraints and 28 | % variable bounds. 29 | % 30 | % .. math:: \min_\x f(\x) 31 | % :label: eq_mips_obj_fcn 32 | % 33 | % subject to 34 | % 35 | % .. math:: \g(\x) = 0 36 | % .. math:: \h(\x) \le 0 37 | % .. math:: \param{\rvec{l}} \le \param{\rmat{A}} \x \le \param{\rvec{u}} 38 | % :label: eq_mips_lin_constraint 39 | % .. math:: \param{\x}_\mathrm{min} \le \x \le \param{\x}_\mathrm{max} 40 | % :label: eq_mips_var_bounds 41 | % 42 | % where :eq:`eq_mips_obj_fcn`--:eq:`eq_mips_var_bounds` are, 43 | % respectively, the objective function, nonlinear equality constraints, 44 | % nonlinear inequality constraints, linear constraints, and variable bounds. 45 | % 46 | % Inputs: 47 | % : *(all optional except* ``f_fcn`` *and* ``x0`` *)* 48 | % f_fcn (function handle) : handle to function that evaluates the 49 | % objective function :math:`f(\x)`, its gradients and Hessian for 50 | % a given value of :math:`x`. If there are nonlinear constraints, 51 | % the Hessian information is provided by the ``hess_fcn`` function 52 | % passed in the 9th argument and is not required here. Calling 53 | % syntax for this function:: 54 | % 55 | % [f, df, d2f] = f_fcn(x) 56 | % 57 | % x0 (double) : starting value of optimization vector :math:`\x` 58 | % A, l, u (double) : *(optional, respective defaults* 59 | % :math:`[empty, -\infty, +\infty]` *)* matrix :math:`\param{\cmat{A}}` 60 | % and vectors :math:`\param{\rvec{l}}` and :math:`\param{\rvec{u}}` 61 | % to define the linear constraints in :eq:`eq_mips_lin_constraint` 62 | % xmin, xmax (double) : *(optional, respective defaults* 63 | % :math:`[-\infty, +\infty]` *)* lower and upper bounds, 64 | % :math:`\param{\x}_\mathrm{min}` and :math:`\param{\x}_\mathrm{max}`, 65 | % on the optimization variables :math:`\x` 66 | % gh_fcn (function handle) : *(optional)* handle to function that 67 | % evaluates the nonlinear constraints :math:`\g(\x)` and :math:`\h(\x)` 68 | % and their gradients for a given value of :math:`x`. Calling syntax 69 | % for this function is:: 70 | % 71 | % [h, g, dh, dg] = gh_fcn(x) 72 | % 73 | % where the columns of ``dh`` and ``dg`` are the gradients of the 74 | % corresponding elements of ``h`` and ``g``, i.e. ``dh`` and ``dg`` 75 | % are transposes of the Jacobians of ``h`` and ``g``, respectively. 76 | % hess_fcn (function handle) : *(optional)* handle to function that 77 | % computes the Hessian of the Lagrangian for given values of 78 | % :math:`\x`, :math:`\lam` and :math:`\muv`, where 79 | % :math:`\lam` and :math:`\muv` are the multipliers on the equality 80 | % and inequality constraints, :math:`\g` and :math:`\h`, respectively. 81 | % The calling syntax for this function is:: 82 | % 83 | % Lxx = hess_fcn(x, lam) 84 | % 85 | % where :math:`\lam` = ``lam.eqnonlin`` and :math:`\muv` = 86 | % ``lam.ineqnonlin``. 87 | % opt (struct) : *(optional)* options structure with the following fields, 88 | % all of which are also optional *(default values shown in 89 | % parentheses)* 90 | % 91 | % - ``verbose`` *(0)* - controls level of progress output displayed 92 | % 93 | % - 0 = no progress output 94 | % - 1 = some progress output 95 | % - 2 = verbose progress output 96 | % - ``linsolver`` *(* ``''`` *)* - linear system solver for solving 97 | % update steps 98 | % 99 | % - ``''`` = default solver (currently same as ``'\'``) 100 | % - ``'\'`` = built-in ``\`` operator 101 | % - ``'PARDISO'`` = PARDISO solver *(if available)* 102 | % - ``feastol`` *(1e-6)* - termination tolerance for feasibility 103 | % condition 104 | % - ``gradtol`` *(1e-6)* - termination tolerance for gradient 105 | % condition 106 | % - ``comptol`` *(1e-6)* - termination tolerance for complementarity 107 | % condition 108 | % - ``costtol`` *(1e-6)* - termination tolerance for cost condition 109 | % - ``max_it`` *(150)* - maximum number of iterations 110 | % - ``step_control`` *(0)* - set to 1 to enable step-size control 111 | % - ``sc.red_it`` *(20)* - maximum number of step-size reductions if 112 | % step-control is on 113 | % - ``cost_mult`` *(1)* - cost multiplier used to scale the objective 114 | % function for improved conditioning. *Note: This value is 115 | % also passed as the 3rd argument to the Hessian evaluation 116 | % function so that it can appropriately scale the 117 | % objective function term in the Hessian of the 118 | % Lagrangian.* 119 | % - ``xi`` *(0.99995)* - constant :math:`\xi` used in :math:`alpha` 120 | % updates [#]_ 121 | % - ``sigma`` *(0.1)* - centering parameter :math:`\sigma` [1]_ 122 | % - ``z0`` *(1)* - used to initialize slack variables [1]_ 123 | % - ``alpha_min`` *(1e-8)* - returns ``exitflag`` = -1 if either alpha 124 | % parameter, :math:`\alpha_p` or :math:`\alpha_d` becomes smaller 125 | % than this value [1]_ 126 | % - ``rho_min`` *(0.95)* - lower bound on ``rho_t`` [1]_ 127 | % - ``rho_max`` *(1.05)* - upper bound on ``rho_t`` [1]_ 128 | % - ``mu_threshold`` *(1e-5)* - KT multipliers smaller than this value 129 | % for non-binding constraints are forced to zero 130 | % - ``max_stepsize`` *(1e10)* - returns ``exitflag`` = -1 if the 131 | % 2-norm of the reduced Newton step exceeds this value [1]_ 132 | % - ``full_hist`` *(0)* - set to 1 to enable saving in ``output.hist`` 133 | % trajectories of ``x``, ``z``, ``g``, ``h``, ``lam``, ``mu`` 134 | % problem (struct) : The inputs can alternatively be supplied in a single 135 | % ``problem`` struct with fields corresponding to the input arguments 136 | % described above, namely, ``f_fcn``, ``x0``, ``A``, ``l``, ``u``, 137 | % ``xmin``, ``xmax``, ``gh_fcn``, ``hess_fcn``, and ``opt``, where 138 | % all except ``f_fcn`` and ``x0`` are optional 139 | % 140 | % .. [#] See the "Primal-Dual Interior Point Algorithm" chapter in the 141 | % |MIPSman| for details. 142 | % 143 | % Outputs: 144 | % x (double) : solution vector, :math:`\x` 145 | % f (double) : final objective function value, :math:`f(\x)` 146 | % exitflag (integer) : exit flag 147 | % 148 | % - 1 = first order optimality conditions satisfied 149 | % - 0 = maximum number of iterations reached 150 | % - -1 = numerically failed 151 | % output (struct) : output struct with fields: 152 | % 153 | % - ``iterations`` - number of iterations performed 154 | % - ``hist`` - struct array with trajectories of the following: 155 | % 156 | % - ``feascond``, ``gradcond``, ``compcond``, ``costcond``, 157 | % ``gamma``, ``stepsize``, ``obj``, ``alphap``, ``alphad`` 158 | % - ``message`` - exit message 159 | % lambda (struct) : struct containing the Langrange and Kuhn-Tucker 160 | % multipliers on the constraints, with fields: 161 | % 162 | % - ``eqnonlin`` - nonlinear equality constraints 163 | % - ``ineqnonlin`` - nonlinear inequality constraints 164 | % - ``mu_l`` - lower (left-hand) limit on linear constraints 165 | % - ``mu_u`` - upper (right-hand) limit on linear constraints 166 | % - ``lower`` - lower bound on optimization variables 167 | % - ``upper`` - upper bound on optimization variables 168 | % 169 | % **Note:** The calling syntax is almost identical to that of :func:`fmincon` 170 | % from MathWorks' Optimization Toolbox. The main difference is that 171 | % the linear constraints are specified with ``A``, ``l``, ``u`` instead of 172 | % ``A``, ``B``, ``Aeq``, ``Beq``. The functions for evaluating the objective 173 | % function, constraints and Hessian are identical. 174 | % 175 | % **Example:** (problem from https://en.wikipedia.org/wiki/Nonlinear_programming):: 176 | % 177 | % function [f, df, d2f] = f2(x) 178 | % f = -x(1)*x(2) - x(2)*x(3); 179 | % if nargout > 1 % gradient is required 180 | % df = -[x(2); x(1)+x(3); x(2)]; 181 | % if nargout > 2 % Hessian is required 182 | % d2f = -[0 1 0; 1 0 1; 0 1 0]; % actually not used since 183 | % end % 'hess_fcn' is provided 184 | % end 185 | % 186 | % function [h, g, dh, dg] = gh2(x) 187 | % h = [ 1 -1 1; 1 1 1] * x.^2 + [-2; -10]; 188 | % dh = 2 * [x(1) x(1); -x(2) x(2); x(3) x(3)]; 189 | % g = []; dg = []; 190 | % 191 | % function Lxx = hess2(x, lam, cost_mult) 192 | % if nargin < 3, cost_mult = 1; end 193 | % mu = lam.ineqnonlin; 194 | % Lxx = cost_mult * [0 -1 0; -1 0 -1; 0 -1 0] + ... 195 | % [2*[1 1]*mu 0 0; 0 2*[-1 1]*mu 0; 0 0 2*[1 1]*mu]; 196 | % 197 | % problem = struct( ... 198 | % 'f_fcn', @(x)f2(x), ... 199 | % 'gh_fcn', @(x)gh2(x), ... 200 | % 'hess_fcn', @(x, lam, cost_mult)hess2(x, lam, cost_mult), ... 201 | % 'x0', [1; 1; 0], ... 202 | % 'opt', struct('verbose', 2) ... 203 | % ); 204 | % [x, f, exitflag, output, lambda] = mips(problem); 205 | % 206 | % Ported by Ray Zimmerman from C code written by H. Wang for his 207 | % PhD dissertation: 208 | % 209 | % H. Wang, *On the Computation and Application of Multi-period 210 | % Security-Constrained Optimal Power Flow for Real-time 211 | % Electricity Market Operations,* Ph.D. thesis, Electrical and 212 | % Computer Engineering, Cornell University, May 2007. 213 | % 214 | % Please see also: 215 | % 216 | % H. Wang, C. E. Murillo-Sanchez, R. D. Zimmerman, R. J. Thomas, 217 | % "On Computational Issues of Market-Based Optimal Power Flow", 218 | % *IEEE Transactions on Power Systems*, Vol. 22, No. 3, Aug. 2007, 219 | % pp. 1185-1193. :doi:`10.1109/TPWRS.2007.901301` 220 | 221 | % MIPS 222 | % Copyright (c) 2009-2024, Power Systems Engineering Research Center (PSERC) 223 | % by Ray Zimmerman, PSERC Cornell 224 | % 225 | % This file is part of MIPS. 226 | % Covered by the 3-clause BSD License (see LICENSE file for details). 227 | % See https://github.com/MATPOWER/mips for more info. 228 | 229 | %%----- input argument handling ----- 230 | %% gather inputs 231 | if nargin == 1 && isstruct(f_fcn) %% problem struct 232 | p = f_fcn; 233 | f_fcn = p.f_fcn; 234 | x0 = p.x0; 235 | nx = size(x0, 1); %% number of optimization variables 236 | if isfield(p, 'opt'), opt = p.opt; else, opt = []; end 237 | if isfield(p, 'hess_fcn'), hess_fcn = p.hess_fcn; else, hess_fcn = ''; end 238 | if isfield(p, 'gh_fcn'), gh_fcn = p.gh_fcn; else, gh_fcn = ''; end 239 | if isfield(p, 'xmax'), xmax = p.xmax; else, xmax = []; end 240 | if isfield(p, 'xmin'), xmin = p.xmin; else, xmin = []; end 241 | if isfield(p, 'u'), u = p.u; else, u = []; end 242 | if isfield(p, 'l'), l = p.l; else, l = []; end 243 | if isfield(p, 'A'), A = p.A; else, A=sparse(0,nx); end 244 | else %% individual args 245 | nx = size(x0, 1); %% number of optimization variables 246 | if nargin < 10 247 | opt = []; 248 | if nargin < 9 249 | hess_fcn = ''; 250 | if nargin < 8 251 | gh_fcn = ''; 252 | if nargin < 7 253 | xmax = []; 254 | if nargin < 6 255 | xmin = []; 256 | if nargin < 5 257 | u = []; 258 | if nargin < 4 259 | l = []; 260 | A = sparse(0,nx); 261 | end 262 | end 263 | end 264 | end 265 | end 266 | end 267 | end 268 | end 269 | %% set default argument values if missing 270 | if isempty(A) || (~isempty(A) && (isempty(l) || all(l == -Inf)) && ... 271 | (isempty(u) || all(u == Inf))) 272 | A = sparse(0,nx); %% no limits => no linear constraints 273 | end 274 | nA = size(A, 1); %% number of original linear constraints 275 | if isempty(u) %% By default, linear inequalities are ... 276 | u = Inf(nA, 1); %% ... unbounded above and ... 277 | end 278 | if isempty(l) 279 | l = -Inf(nA, 1); %% ... unbounded below. 280 | end 281 | if isempty(xmin) %% By default, optimization variables are ... 282 | xmin = -Inf(nx, 1); %% ... unbounded below and ... 283 | end 284 | if isempty(xmax) 285 | xmax = Inf(nx, 1); %% ... unbounded above. 286 | end 287 | if isempty(gh_fcn) 288 | nonlinear = false; %% no nonlinear constraints present 289 | gn = []; hn = []; 290 | else 291 | nonlinear = true; %% we have some nonlinear constraints 292 | end 293 | 294 | %% default options 295 | if isempty(opt) 296 | opt = struct('verbose', 0); 297 | end 298 | if ~isfield(opt, 'linsolver') || isempty(opt.linsolver) 299 | opt.linsolver = ''; 300 | end 301 | if ~isfield(opt, 'feastol') || isempty(opt.feastol) || opt.feastol == 0 302 | opt.feastol = 1e-6; 303 | end 304 | if ~isfield(opt, 'gradtol') || isempty(opt.gradtol) || opt.gradtol == 0 305 | opt.gradtol = 1e-6; 306 | end 307 | if ~isfield(opt, 'comptol') || isempty(opt.comptol) || opt.comptol == 0 308 | opt.comptol = 1e-6; 309 | end 310 | if ~isfield(opt, 'costtol') || isempty(opt.costtol) || opt.costtol == 0 311 | opt.costtol = 1e-6; 312 | end 313 | if ~isfield(opt, 'max_it') || isempty(opt.max_it) 314 | opt.max_it = 150; 315 | end 316 | if ~isfield(opt, 'sc') || ~isfield(opt.sc, 'red_it') || isempty(opt.sc.red_it) 317 | opt.sc.red_it = 20; 318 | end 319 | if ~isfield(opt, 'step_control') || isempty(opt.step_control) 320 | opt.step_control = 0; 321 | end 322 | if ~isfield(opt, 'cost_mult') || isempty(opt.cost_mult) 323 | opt.cost_mult = 1; 324 | end 325 | if ~isfield(opt, 'verbose') || isempty(opt.verbose) 326 | opt.verbose = 0; 327 | end 328 | %% algorithm constants 329 | if ~isfield(opt, 'xi') || isempty(opt.xi) 330 | opt.xi = 0.99995; %% OPT_IPM_PHI 331 | end 332 | if ~isfield(opt, 'sigma') || isempty(opt.sigma) 333 | opt.sigma = 0.1; %% OPT_IPM_SIGMA, centering parameter 334 | end 335 | if ~isfield(opt, 'z0') || isempty(opt.z0) 336 | opt.z0 = 1; %% OPT_IPM_INIT_SLACK 337 | end 338 | if ~isfield(opt, 'alpha_min') || isempty(opt.alpha_min) 339 | opt.alpha_min = 1e-8; %% OPT_AP_AD_MIN 340 | end 341 | if ~isfield(opt, 'rho_min') || isempty(opt.rho_min) 342 | opt.rho_min = 0.95; %% OPT_IPM_QUAD_LOWTHRESH 343 | end 344 | if ~isfield(opt, 'rho_max') || isempty(opt.rho_max) 345 | opt.rho_max = 1.05; %% OPT_IPM_QUAD_HIGHTHRESH 346 | end 347 | if ~isfield(opt, 'mu_threshold') || isempty(opt.mu_threshold) 348 | opt.mu_threshold = 1e-5; %% SCOPF_MULTIPLIERS_FILTER_THRESH 349 | end 350 | if ~isfield(opt, 'max_stepsize') || isempty(opt.max_stepsize) 351 | opt.max_stepsize = 1e10; 352 | end 353 | if ~isfield(opt, 'full_hist') || isempty(opt.full_hist) 354 | opt.full_hist = 0; 355 | end 356 | 357 | %% initialize history 358 | if opt.full_hist 359 | hist(opt.max_it+1) = struct('feascond', 0, 'gradcond', 0, 'compcond', 0, ... 360 | 'costcond', 0, 'gamma', 0, 'stepsize', 0, 'obj', 0, ... 361 | 'alphap', 0, 'alphad', 0, 'x', [], 'z', [], 'g', [], 'h', [], ... 362 | 'lam', [], 'mu', []); 363 | else 364 | hist(opt.max_it+1) = struct('feascond', 0, 'gradcond', 0, 'compcond', 0, ... 365 | 'costcond', 0, 'gamma', 0, 'stepsize', 0, 'obj', 0, ... 366 | 'alphap', 0, 'alphad', 0); 367 | end 368 | 369 | %%----- set up problem ----- 370 | %% constants 371 | [xi, sigma, z0, alpha_min, rho_min, rho_max, mu_threshold, max_stepsize] = ... 372 | deal(opt.xi, opt.sigma, opt.z0, opt.alpha_min, ... 373 | opt.rho_min, opt.rho_max, opt.mu_threshold, opt.max_stepsize); 374 | if xi >= 1 || xi < 0.5 375 | error('mips: opt.xi (%g) must be a number slightly less than 1', opt.xi); 376 | end 377 | if sigma > 1 || sigma <= 0 378 | error('mips: opt.sigma (%g) must be a number between 0 and 1', opt.sigma); 379 | end 380 | 381 | %% initialize 382 | i = 0; %% iteration counter 383 | converged = 0; %% flag 384 | eflag = 0; %% exit flag 385 | 386 | %% add var limits to linear constraints 387 | AA = [speye(nx); A]; 388 | ll = [xmin; l]; 389 | uu = [xmax; u]; 390 | 391 | %% split up linear constraints 392 | ieq = find( abs(uu-ll) <= eps ); %% equality 393 | igt = find( uu >= 1e10 & ll > -1e10 ); %% greater than, unbounded above 394 | ilt = find( ll <= -1e10 & uu < 1e10 ); %% less than, unbounded below 395 | ibx = find( (abs(uu-ll) > eps) & (uu < 1e10) & (ll > -1e10) ); 396 | Ae = AA(ieq, :); 397 | be = uu(ieq, 1); 398 | Ai = [ AA(ilt, :); -AA(igt, :); AA(ibx, :); -AA(ibx, :) ]; 399 | bi = [ uu(ilt, 1); -ll(igt, 1); uu(ibx, 1); -ll(ibx, 1) ]; 400 | 401 | %% evaluate cost f(x0) and constraints g(x0), h(x0) 402 | x = x0; 403 | [f, df] = f_fcn(x); %% cost 404 | f = f * opt.cost_mult; 405 | df = df * opt.cost_mult; 406 | if nonlinear 407 | [hn, gn, dhn, dgn] = gh_fcn(x); %% nonlinear constraints 408 | h = [hn; Ai * x - bi]; %% inequality constraints 409 | g = [gn; Ae * x - be]; %% equality constraints 410 | dh = [dhn Ai']; %% 1st derivative of inequalities 411 | dg = [dgn Ae']; %% 1st derivative of equalities 412 | else 413 | h = Ai * x - bi; %% inequality constraints 414 | g = Ae * x - be; %% equality constraints 415 | dh = Ai'; %% 1st derivative of inequalities 416 | dg = Ae'; %% 1st derivative of equalities 417 | end 418 | 419 | %% grab some dimensions 420 | neq = size(g, 1); %% number of equality constraints 421 | niq = size(h, 1); %% number of inequality constraints 422 | neqnln = size(gn, 1); %% number of nonlinear equality constraints 423 | niqnln = size(hn, 1); %% number of nonlinear inequality constraints 424 | nlt = length(ilt); %% number of upper bounded linear inequalities 425 | ngt = length(igt); %% number of lower bounded linear inequalities 426 | nbx = length(ibx); %% number of doubly bounded linear inequalities 427 | 428 | %% initialize gamma, lam, mu, z, e 429 | gamma = 1; %% barrier coefficient, r in Harry's code 430 | lam = zeros(neq, 1); 431 | z = z0 * ones(niq, 1); 432 | mu = z; 433 | k = find(h < -z0); 434 | z(k) = -h(k); 435 | k = find(gamma ./ z > z0); %% (seems k is always empty if gamma = z0 = 1) 436 | if ~isempty(k) 437 | mu(k) = gamma / z(k); 438 | end 439 | e = ones(niq, 1); 440 | 441 | %% check tolerance 442 | f0 = f; 443 | if opt.step_control 444 | L = f + lam' * g + mu' * (h+z) - gamma * sum(log(z)); 445 | end 446 | Lx = df + dg * lam + dh * mu; 447 | if isempty(h) 448 | maxh = zeros(1,0); 449 | else 450 | maxh = max(h); 451 | end 452 | feascond = max([norm(g, Inf), maxh]) / (1 + max([ norm(x, Inf), norm(z, Inf) ])); 453 | gradcond = norm(Lx, Inf) / (1 + max([ norm(lam, Inf), norm(mu, Inf) ])); 454 | compcond = (z' * mu) / (1 + norm(x, Inf)); 455 | costcond = abs(f - f0) / (1 + abs(f0)); 456 | %% save history 457 | if opt.full_hist 458 | hist(i+1) = struct('feascond', feascond, 'gradcond', gradcond, ... 459 | 'compcond', compcond, 'costcond', costcond, 'gamma', gamma, ... 460 | 'stepsize', 0, 'obj', f/opt.cost_mult, 'alphap', 0, 'alphad', 0, ... 461 | 'x', x, 'z', z, 'g', g, 'h', h, 'lam', lam, 'mu', mu); 462 | else 463 | hist(i+1) = struct('feascond', feascond, 'gradcond', gradcond, ... 464 | 'compcond', compcond, 'costcond', costcond, 'gamma', gamma, ... 465 | 'stepsize', 0, 'obj', f/opt.cost_mult, 'alphap', 0, 'alphad', 0); 466 | end 467 | if strcmp(upper(opt.linsolver), 'PARDISO') 468 | ls = 'PARDISO'; 469 | mplinsolve_opt = struct('pardiso', ... 470 | struct('mtype', -2, ... 471 | 'iparm', [8, 1; %% max it refinement steps 472 | 10, 12;%% eps pivot 473 | 11, 1; %% use scaling vectors 474 | 13, 2; %% improved accuracy 475 | 18, 0; %% do not determine nnz in LU 476 | 21, 3; %% ? undocumented pivoting 477 | ] )); 478 | else 479 | ls = 'built-in'; 480 | mplinsolve_opt = []; 481 | end 482 | if opt.verbose 483 | if opt.step_control, s = '-sc'; else, s = ''; end 484 | v = mipsver('all'); 485 | fprintf('MATPOWER Interior Point Solver -- MIPS%s, Version %s, %s\n (using %s linear solver)', ... 486 | s, v.Version, v.Date, ls); 487 | if opt.verbose > 1 488 | fprintf('\n it objective step size feascond gradcond compcond costcond '); 489 | fprintf('\n---- ------------ --------- ------------ ------------ ------------ ------------'); 490 | fprintf('\n%3d %12.8g %10s %12g %12g %12g %12g', ... 491 | i, f/opt.cost_mult, '', feascond, gradcond, compcond, costcond); 492 | end 493 | end 494 | if feascond < opt.feastol && gradcond < opt.gradtol && ... 495 | compcond < opt.comptol && costcond < opt.costtol 496 | converged = 1; 497 | if opt.verbose 498 | fprintf('\nConverged!\n'); 499 | end 500 | end 501 | 502 | %%----- do Newton iterations ----- 503 | while (~converged && i < opt.max_it) 504 | %% update iteration counter 505 | i = i + 1; 506 | 507 | %% compute update step 508 | lambda = struct('eqnonlin', lam(1:neqnln), 'ineqnonlin', mu(1:niqnln)); 509 | if nonlinear 510 | if isempty(hess_fcn) 511 | fprintf('mips: Hessian evaluation via finite differences not yet implemented.\n Please provide your own hessian evaluation function.'); 512 | end 513 | Lxx = hess_fcn(x, lambda, opt.cost_mult); 514 | else 515 | [f_, df_, d2f] = f_fcn(x); %% cost 516 | Lxx = d2f * opt.cost_mult; 517 | end 518 | zinvdiag = sparse(1:niq, 1:niq, 1 ./ z, niq, niq); 519 | mudiag = sparse(1:niq, 1:niq, mu, niq, niq); 520 | dh_zinv = dh * zinvdiag; 521 | M = Lxx + dh_zinv * mudiag * dh'; 522 | N = Lx + dh_zinv * (mudiag * h + gamma * e); 523 | dxdlam = mplinsolve([M dg; dg' sparse(neq, neq)], [-N; -g], opt.linsolver, mplinsolve_opt); 524 | % AAA = [ 525 | % M dg; 526 | % dg' sparse(neq, neq) 527 | % ]; 528 | % rc = 1/condest(AAA); 529 | % if rc < 1e-22 530 | % fprintf('my RCOND = %g\n', rc); 531 | % n = size(AAA, 1); 532 | % AAA = AAA + 1e-3 * speye(n,n); 533 | % end 534 | % bbb = [-N; -g]; 535 | % dxdlam = AAA \ bbb; 536 | if any(isnan(dxdlam)) || norm(dxdlam) > max_stepsize 537 | if opt.verbose 538 | fprintf('\nNumerically Failed\n'); 539 | end 540 | eflag = -1; 541 | break; 542 | end 543 | dx = dxdlam(1:nx, 1); 544 | dlam = dxdlam(nx+(1:neq), 1); 545 | dz = -h - z - dh' * dx; 546 | dmu = -mu + zinvdiag *(gamma*e - mudiag * dz); 547 | 548 | %% optional step-size control 549 | sc = 0; 550 | if opt.step_control 551 | x1 = x + dx; 552 | 553 | %% evaluate cost, constraints, derivatives at x1 554 | [f1, df1] = f_fcn(x1); %% cost 555 | f1 = f1 * opt.cost_mult; 556 | df1 = df1 * opt.cost_mult; 557 | if nonlinear 558 | [hn1, gn1, dhn1, dgn1] = gh_fcn(x1); %% nonlinear constraints 559 | h1 = [hn1; Ai * x1 - bi]; %% inequality constraints 560 | g1 = [gn1; Ae * x1 - be]; %% equality constraints 561 | dh1 = [dhn1 Ai']; %% 1st derivative of inequalities 562 | dg1 = [dgn1 Ae']; %% 1st derivative of equalities 563 | else 564 | h1 = Ai * x1 - bi; %% inequality constraints 565 | g1 = Ae * x1 - be; %% equality constraints 566 | dh1 = dh; %% 1st derivative of inequalities 567 | dg1 = dg; %% 1st derivative of equalities 568 | end 569 | 570 | %% check tolerance 571 | Lx1 = df1 + dg1 * lam + dh1 * mu; 572 | if isempty(h1) 573 | maxh1 = zeros(1,0); 574 | else 575 | maxh1 = max(h1); 576 | end 577 | feascond1 = max([norm(g1, Inf), maxh1]) / (1 + max([ norm(x1, Inf), norm(z, Inf) ])); 578 | gradcond1 = norm(Lx1, Inf) / (1 + max([ norm(lam, Inf), norm(mu, Inf) ])); 579 | 580 | if feascond1 > feascond && gradcond1 > gradcond 581 | sc = 1; 582 | end 583 | end 584 | if sc 585 | alpha = 1; 586 | for j = 1:opt.sc.red_it 587 | dx1 = alpha * dx; 588 | x1 = x + dx1; 589 | f1 = f_fcn(x1); %% cost 590 | f1 = f1 * opt.cost_mult; 591 | if nonlinear 592 | [hn1, gn1] = gh_fcn(x1); %% nonlinear constraints 593 | h1 = [hn1; Ai * x1 - bi]; %% inequality constraints 594 | g1 = [gn1; Ae * x1 - be]; %% equality constraints 595 | else 596 | h1 = Ai * x1 - bi; %% inequality constraints 597 | g1 = Ae * x1 - be; %% equality constraints 598 | end 599 | L1 = f1 + lam' * g1 + mu' * (h1+z) - gamma * sum(log(z)); 600 | if opt.verbose > 2 601 | fprintf('\n %3d %10g', -j, norm(dx1)); 602 | end 603 | rho = (L1 - L) / (Lx' * dx1 + 0.5 * dx1' * Lxx * dx1); 604 | if rho > rho_min && rho < rho_max 605 | break; 606 | else 607 | alpha = alpha / 2; 608 | end 609 | end 610 | dx = alpha * dx; 611 | dz = alpha * dz; 612 | dlam = alpha * dlam; 613 | dmu = alpha * dmu; 614 | end 615 | 616 | %% do the update 617 | k = find(dz < 0); 618 | if isempty(k) 619 | alphap = 1; 620 | else 621 | alphap = min( [xi * min(z(k) ./ -dz(k)) 1] ); 622 | end 623 | k = find(dmu < 0); 624 | if isempty(k) 625 | alphad = 1; 626 | else 627 | alphad = min( [xi * min(mu(k) ./ -dmu(k)) 1] ); 628 | end 629 | x = x + alphap * dx; 630 | z = z + alphap * dz; 631 | lam = lam + alphad * dlam; 632 | mu = mu + alphad * dmu; 633 | if niq > 0 634 | gamma = sigma * (z' * mu) / niq; 635 | end 636 | 637 | %% evaluate cost, constraints, derivatives 638 | [f, df] = f_fcn(x); %% cost 639 | f = f * opt.cost_mult; 640 | df = df * opt.cost_mult; 641 | if nonlinear 642 | [hn, gn, dhn, dgn] = gh_fcn(x); %% nonlinear constraints 643 | h = [hn; Ai * x - bi]; %% inequality constraints 644 | g = [gn; Ae * x - be]; %% equality constraints 645 | dh = [dhn Ai']; %% 1st derivative of inequalities 646 | dg = [dgn Ae']; %% 1st derivative of equalities 647 | else 648 | h = Ai * x - bi; %% inequality constraints 649 | g = Ae * x - be; %% equality constraints 650 | %% 1st derivatives are constant, still dh = Ai', dg = Ae' 651 | end 652 | 653 | %% check tolerance 654 | Lx = df + dg * lam + dh * mu; 655 | if isempty(h) 656 | maxh = zeros(1,0); 657 | else 658 | maxh = max(h); 659 | end 660 | feascond = max([norm(g, Inf), maxh]) / (1 + max([ norm(x, Inf), norm(z, Inf) ])); 661 | gradcond = norm(Lx, Inf) / (1 + max([ norm(lam, Inf), norm(mu, Inf) ])); 662 | compcond = (z' * mu) / (1 + norm(x, Inf)); 663 | costcond = abs(f - f0) / (1 + abs(f0)); 664 | %% save history 665 | if opt.full_hist 666 | hist(i+1) = struct('feascond', feascond, 'gradcond', gradcond, ... 667 | 'compcond', compcond, 'costcond', costcond, 'gamma', gamma, ... 668 | 'stepsize', norm(dx), 'obj', f/opt.cost_mult, ... 669 | 'alphap', alphap, 'alphad', alphad, ... 670 | 'x', x, 'z', z, 'g', g, 'h', h, 'lam', lam, 'mu', mu); 671 | else 672 | hist(i+1) = struct('feascond', feascond, 'gradcond', gradcond, ... 673 | 'compcond', compcond, 'costcond', costcond, 'gamma', gamma, ... 674 | 'stepsize', norm(dx), 'obj', f/opt.cost_mult, ... 675 | 'alphap', alphap, 'alphad', alphad); 676 | end 677 | 678 | if opt.verbose > 1 679 | fprintf('\n%3d %12.8g %10.5g %12g %12g %12g %12g', ... 680 | i, f/opt.cost_mult, norm(dx), feascond, gradcond, compcond, costcond); 681 | end 682 | if feascond < opt.feastol && gradcond < opt.gradtol && ... 683 | compcond < opt.comptol && costcond < opt.costtol 684 | converged = 1; 685 | if opt.verbose 686 | fprintf('\nConverged!\n'); 687 | end 688 | else 689 | if any(isnan(x)) || alphap < alpha_min || alphad < alpha_min || ... 690 | gamma < eps || gamma > 1/eps 691 | if opt.verbose 692 | fprintf('\nNumerically Failed\n'); 693 | end 694 | eflag = -1; 695 | break; 696 | end 697 | f0 = f; 698 | if opt.step_control 699 | L = f + lam' * g + mu' * (h+z) - gamma * sum(log(z)); 700 | end 701 | end 702 | end 703 | 704 | if opt.verbose 705 | if ~converged 706 | fprintf('\nDid not converge in %d iterations.\n', i); 707 | end 708 | end 709 | 710 | %%----- package up results ----- 711 | hist = hist(1:i+1); 712 | if eflag ~= -1 713 | eflag = converged; 714 | end 715 | output = struct('iterations', i, 'hist', hist, 'message', ''); 716 | if eflag == 0 717 | output.message = 'Did not converge'; 718 | elseif eflag == 1 719 | output.message = 'Converged'; 720 | elseif eflag == -1 721 | output.message = 'Numerically failed'; 722 | else 723 | output.message = 'Please hang up and dial again'; 724 | end 725 | 726 | %% zero out multipliers on non-binding constraints 727 | mu(h < -opt.feastol & mu < mu_threshold) = 0; 728 | 729 | %% un-scale cost and prices 730 | f = f / opt.cost_mult; 731 | lam = lam / opt.cost_mult; 732 | mu = mu / opt.cost_mult; 733 | 734 | %% re-package multipliers into struct 735 | lam_lin = lam((neqnln+1):neq); %% lambda for linear constraints 736 | mu_lin = mu((niqnln+1):niq); %% mu for linear constraints 737 | kl = find(lam_lin < 0); %% lower bound binding 738 | ku = find(lam_lin > 0); %% upper bound binding 739 | 740 | mu_l = zeros(nx+nA, 1); 741 | mu_l(ieq(kl)) = -lam_lin(kl); 742 | mu_l(igt) = mu_lin(nlt+(1:ngt)); 743 | mu_l(ibx) = mu_lin(nlt+ngt+nbx+(1:nbx)); 744 | 745 | mu_u = zeros(nx+nA, 1); 746 | mu_u(ieq(ku)) = lam_lin(ku); 747 | mu_u(ilt) = mu_lin(1:nlt); 748 | mu_u(ibx) = mu_lin(nlt+ngt+(1:nbx)); 749 | 750 | fields = { ... 751 | 'mu_l', mu_l((nx+1):end), ... 752 | 'mu_u', mu_u((nx+1):end), ... 753 | 'lower', mu_l(1:nx), ... 754 | 'upper', mu_u(1:nx) ... 755 | }; 756 | 757 | if niqnln > 0 758 | fields = { ... 759 | 'ineqnonlin', mu(1:niqnln), ... 760 | fields{:} ... 761 | }; 762 | end 763 | if neqnln > 0 764 | fields = { ... 765 | 'eqnonlin', lam(1:neqnln), ... 766 | fields{:} ... 767 | }; 768 | end 769 | 770 | lambda = struct(fields{:}); 771 | 772 | % lambda = struct( ... 773 | % 'eqnonlin', lam(1:neqnln), ... 774 | % 'ineqnonlin', mu(1:niqnln), ... 775 | % 'mu_l', mu_l((nx+1):end), ... 776 | % 'mu_u', mu_u((nx+1):end), ... 777 | % 'lower', mu_l(1:nx), ... 778 | % 'upper', mu_u(1:nx) ); 779 | -------------------------------------------------------------------------------- /lib/t/t_mplinsolve.m: -------------------------------------------------------------------------------- 1 | function t_mplinsolve(quiet) 2 | % t_mplinsolve - Tests of mplinsolve, MIPS/|MATPOWER| linear solvers. 3 | % :: 4 | % 5 | % t_mplinsolve 6 | % t_mplinsolve(quiet) 7 | 8 | % MIPS 9 | % Copyright (c) 2015-2024, Power Systems Engineering Research Center (PSERC) 10 | % by Ray Zimmerman, PSERC Cornell 11 | % 12 | % This file is part of MIPS. 13 | % Covered by the 3-clause BSD License (see LICENSE file for details). 14 | % See https://github.com/MATPOWER/mips for more info. 15 | 16 | if nargin < 1 17 | quiet = 0; 18 | end 19 | 20 | t_begin(180, quiet); 21 | 22 | isoctave = exist('OCTAVE_VERSION', 'builtin') == 5; 23 | if isoctave 24 | lu_warning_id = 'Octave:lu:sparse_input'; 25 | s = warning('query', lu_warning_id); 26 | warning('off', lu_warning_id); 27 | end 28 | 29 | %% non-sparse A matrix crashes some MATLAB lu() calls on certain 30 | %% combinations of MATLAB and macOS versions 31 | mlv = have_feature('matlab', 'vnum'); 32 | skipcrash = ~isempty(mlv) && mlv < 8.003 && mlv > 7.013 && ... 33 | strcmp(computer, 'MACI64'); 34 | 35 | ijs = [ 36 | 1 1 1205.63; 37 | 4 1 -1205.63; 38 | 25 1 17.3611; 39 | 28 1 -17.3611; 40 | 43 1 1; 41 | 2 2 1024; 42 | 8 2 -1024; 43 | 26 2 16; 44 | 32 2 -16; 45 | 3 3 1164.84; 46 | 6 3 -1164.84; 47 | 27 3 17.0648; 48 | 30 3 -17.0648; 49 | 1 4 -1205.63; 50 | 4 4 2201.34; 51 | 5 4 -453.695; 52 | 9 4 -542.009; 53 | 13 4 0.776236; 54 | 14 4 -0.451721; 55 | 18 4 -0.324515; 56 | 25 4 -17.3611; 57 | 28 4 39.4759; 58 | 29 4 -10.5107; 59 | 33 4 -11.6041; 60 | 37 4 -3.30738; 61 | 38 4 1.94219; 62 | 42 4 1.36519; 63 | 4 5 -453.695; 64 | 5 5 581.372; 65 | 6 5 -127.677; 66 | 13 5 -0.451721; 67 | 14 5 0.568201; 68 | 15 5 -0.11648; 69 | 28 5 -10.5107; 70 | 29 5 16.0989; 71 | 30 5 -5.58824; 72 | 37 5 1.94219; 73 | 38 5 -3.2242; 74 | 39 5 1.28201; 75 | 3 6 -1164.84; 76 | 5 6 -127.677; 77 | 6 6 1676.74; 78 | 7 6 -384.227; 79 | 14 6 -0.11648; 80 | 15 6 0.163059; 81 | 16 6 -0.0465791; 82 | 27 6 -17.0648; 83 | 29 6 -5.58824; 84 | 30 6 32.4374; 85 | 31 6 -9.78427; 86 | 38 6 1.28201; 87 | 39 6 -2.4371; 88 | 40 6 1.15509; 89 | 6 7 -384.227; 90 | 7 7 1141.16; 91 | 8 7 -756.935; 92 | 15 7 -0.0465791; 93 | 16 7 0.371828; 94 | 17 7 -0.325249; 95 | 30 7 -9.78427; 96 | 31 7 23.4822; 97 | 32 7 -13.698; 98 | 39 7 1.15509; 99 | 40 7 -2.77221; 100 | 41 7 1.61712; 101 | 2 8 -1024; 102 | 7 8 -756.935; 103 | 8 8 1925.77; 104 | 9 8 -144.836; 105 | 16 8 -0.325249; 106 | 17 8 0.844105; 107 | 18 8 -0.518855; 108 | 26 8 -16; 109 | 31 8 -13.698; 110 | 32 8 35.6731; 111 | 33 8 -5.97513; 112 | 40 8 1.61712; 113 | 41 8 -2.80473; 114 | 42 8 1.1876; 115 | 4 9 -542.009; 116 | 8 9 -144.836; 117 | 9 9 686.845; 118 | 13 9 -0.324515; 119 | 17 9 -0.518855; 120 | 18 9 0.84337; 121 | 28 9 -11.6041; 122 | 32 9 -5.97513; 123 | 33 9 17.5792; 124 | 37 9 1.36519; 125 | 41 9 1.1876; 126 | 42 9 -2.55279; 127 | 10 10 1207.63; 128 | 13 10 -1205.63; 129 | 34 10 17.3611; 130 | 37 10 -17.3611; 131 | 11 11 1026; 132 | 17 11 -1024; 133 | 35 11 16; 134 | 41 11 -16; 135 | 12 12 1166.84; 136 | 15 12 -1164.84; 137 | 36 12 17.0648; 138 | 39 12 -17.0648; 139 | 4 13 0.776236; 140 | 5 13 -0.451721; 141 | 9 13 -0.324515; 142 | 10 13 -1205.63; 143 | 13 13 2190.83; 144 | 14 13 -447.892; 145 | 18 13 -535.137; 146 | 28 13 3.30738; 147 | 29 13 -1.94219; 148 | 33 13 -1.36519; 149 | 34 13 -17.3611; 150 | 37 13 39.1419; 151 | 38 13 -10.5107; 152 | 42 13 -11.6041; 153 | 4 14 -0.451721; 154 | 5 14 0.568201; 155 | 6 14 -0.11648; 156 | 13 14 -447.892; 157 | 14 14 573.221; 158 | 15 14 -122.862; 159 | 28 14 -1.94219; 160 | 29 14 3.2242; 161 | 30 14 -1.28201; 162 | 37 14 -10.5107; 163 | 38 14 15.5829; 164 | 39 14 -5.58824; 165 | 5 15 -0.11648; 166 | 6 15 0.163059; 167 | 7 15 -0.0465791; 168 | 12 15 -1164.84; 169 | 14 15 -122.862; 170 | 15 15 1669.87; 171 | 16 15 -379.651; 172 | 29 15 -1.28201; 173 | 30 15 2.4371; 174 | 31 15 -1.15509; 175 | 36 15 -17.0648; 176 | 38 15 -5.58824; 177 | 39 15 31.8704; 178 | 40 15 -9.78427; 179 | 6 16 -0.0465791; 180 | 7 16 0.371828; 181 | 8 16 -0.325249; 182 | 15 16 -379.651; 183 | 16 16 1131.92; 184 | 17 16 -750.073; 185 | 30 16 -1.15509; 186 | 31 16 2.77221; 187 | 32 16 -1.61712; 188 | 39 16 -9.78427; 189 | 40 16 23.1242; 190 | 41 16 -13.698; 191 | 7 17 -0.325249; 192 | 8 17 0.844105; 193 | 9 17 -0.518855; 194 | 11 17 -1024; 195 | 16 17 -750.073; 196 | 17 17 1914.92; 197 | 18 17 -138.499; 198 | 31 17 -1.61712; 199 | 32 17 2.80473; 200 | 33 17 -1.1876; 201 | 35 17 -16; 202 | 40 17 -13.698; 203 | 41 17 35.2181; 204 | 42 17 -5.97513; 205 | 4 18 -0.324515; 206 | 8 18 -0.518855; 207 | 9 18 0.84337; 208 | 13 18 -535.137; 209 | 17 18 -138.499; 210 | 18 18 676.012; 211 | 28 18 -1.36519; 212 | 32 18 -1.1876; 213 | 33 18 2.55279; 214 | 37 18 -11.6041; 215 | 41 18 -5.97513; 216 | 42 18 17.0972; 217 | 19 19 1.88667; 218 | 25 19 -1; 219 | 20 20 1.54931; 220 | 26 20 -1; 221 | 21 21 1.78346; 222 | 27 21 -1; 223 | 22 22 0.666667; 224 | 34 22 -1; 225 | 23 23 0.666667; 226 | 35 23 -1; 227 | 24 24 0.666667; 228 | 36 24 -1; 229 | 1 25 17.3611; 230 | 4 25 -17.3611; 231 | 19 25 -1; 232 | 2 26 16; 233 | 8 26 -16; 234 | 20 26 -1; 235 | 3 27 17.0648; 236 | 6 27 -17.0648; 237 | 21 27 -1; 238 | 1 28 -17.3611; 239 | 4 28 39.4759; 240 | 5 28 -10.5107; 241 | 9 28 -11.6041; 242 | 13 28 3.30738; 243 | 14 28 -1.94219; 244 | 18 28 -1.36519; 245 | 4 29 -10.5107; 246 | 5 29 16.0989; 247 | 6 29 -5.58824; 248 | 13 29 -1.94219; 249 | 14 29 3.2242; 250 | 15 29 -1.28201; 251 | 3 30 -17.0648; 252 | 5 30 -5.58824; 253 | 6 30 32.4374; 254 | 7 30 -9.78427; 255 | 14 30 -1.28201; 256 | 15 30 2.4371; 257 | 16 30 -1.15509; 258 | 6 31 -9.78427; 259 | 7 31 23.4822; 260 | 8 31 -13.698; 261 | 15 31 -1.15509; 262 | 16 31 2.77221; 263 | 17 31 -1.61712; 264 | 2 32 -16; 265 | 7 32 -13.698; 266 | 8 32 35.6731; 267 | 9 32 -5.97513; 268 | 16 32 -1.61712; 269 | 17 32 2.80473; 270 | 18 32 -1.1876; 271 | 4 33 -11.6041; 272 | 8 33 -5.97513; 273 | 9 33 17.5792; 274 | 13 33 -1.36519; 275 | 17 33 -1.1876; 276 | 18 33 2.55279; 277 | 10 34 17.3611; 278 | 13 34 -17.3611; 279 | 22 34 -1; 280 | 11 35 16; 281 | 17 35 -16; 282 | 23 35 -1; 283 | 12 36 17.0648; 284 | 15 36 -17.0648; 285 | 24 36 -1; 286 | 4 37 -3.30738; 287 | 5 37 1.94219; 288 | 9 37 1.36519; 289 | 10 37 -17.3611; 290 | 13 37 39.1419; 291 | 14 37 -10.5107; 292 | 18 37 -11.6041; 293 | 4 38 1.94219; 294 | 5 38 -3.2242; 295 | 6 38 1.28201; 296 | 13 38 -10.5107; 297 | 14 38 15.5829; 298 | 15 38 -5.58824; 299 | 5 39 1.28201; 300 | 6 39 -2.4371; 301 | 7 39 1.15509; 302 | 12 39 -17.0648; 303 | 14 39 -5.58824; 304 | 15 39 31.8704; 305 | 16 39 -9.78427; 306 | 6 40 1.15509; 307 | 7 40 -2.77221; 308 | 8 40 1.61712; 309 | 15 40 -9.78427; 310 | 16 40 23.1242; 311 | 17 40 -13.698; 312 | 7 41 1.61712; 313 | 8 41 -2.80473; 314 | 9 41 1.1876; 315 | 11 41 -16; 316 | 16 41 -13.698; 317 | 17 41 35.2181; 318 | 18 41 -5.97513; 319 | 4 42 1.36519; 320 | 8 42 1.1876; 321 | 9 42 -2.55279; 322 | 13 42 -11.6041; 323 | 17 42 -5.97513; 324 | 18 42 17.0972; 325 | 1 43 1; 326 | ]; 327 | A = sparse(ijs(:, 1), ijs(:, 2), ijs(:, 3)); 328 | b = [ 329 | 0; 330 | 0; 331 | 0; 332 | 0; 333 | 0; 334 | 0; 335 | 0; 336 | 0; 337 | 0; 338 | 0; 339 | 0; 340 | 0; 341 | -0.00896054; 342 | -0.0617829; 343 | -0.0772931; 344 | -0.0230638; 345 | -0.0185934; 346 | -0.02; 347 | -0.336; 348 | -0.2755; 349 | -0.353; 350 | 0; 351 | 0; 352 | 0; 353 | 1.3; 354 | 1.55; 355 | 1.4; 356 | 0; 357 | -0.9; 358 | 0; 359 | -1; 360 | 0; 361 | -1.25; 362 | 0; 363 | 0; 364 | 0; 365 | 0.167; 366 | -0.042; 367 | 0.2835; 368 | -0.171; 369 | 0.2275; 370 | -0.259; 371 | 0; 372 | ]; 373 | % ex = [ %% for original symmetrical system 374 | % 0; 375 | % 0.04612219791119214; 376 | % 0.0509334351882598; 377 | % -0.05953571031927305; 378 | % -0.09461814898578046; 379 | % -0.008909854578010561; 380 | % -0.05785829019394401; 381 | % -0.02232729212460287; 382 | % -0.1137760871247425; 383 | % -0.03062777824802364; 384 | % -0.01013282572376477; 385 | % -0.005330939680091628; 386 | % -0.02914165388753019; 387 | % -0.03376073204420303; 388 | % 4.021341450281111e-05; 389 | % -0.01727289094763518; 390 | % -0.008382063634320435; 391 | % -0.04854008812629265; 392 | % -0.2663945795760685; 393 | % -0.4548081594272799; 394 | % -0.3787862287965494; 395 | % -0.02580075363496279; 396 | % -0.02801219343110931; 397 | % -0.09165765332863518; 398 | % -0.1665986614487812; 399 | % -0.4291388294822789; 400 | % -0.3225500876094941; 401 | % 3.967864472606993; 402 | % 5.577372159790927; 403 | % 3.762341481664236; 404 | % 5.858342308599034; 405 | % 3.951628532808602; 406 | % 6.471657726723339; 407 | % -0.01720051102355974; 408 | % -0.01867480495813735; 409 | % -0.06110513277164123; 410 | % -0.1239317474796463; 411 | % -0.1848327901217308; 412 | % -0.4283638085291988; 413 | % 0.07640167050820651; 414 | % -0.1319901818980452; 415 | % 0.4366406661538687; 416 | % 0.0007894844305239289; 417 | % ]; 418 | A(8, 2) = -500; %% make non-symmetrical 419 | ex = [ 420 | 0.000000000000000 421 | 0.015818764480650 422 | 0.028627515055857 423 | -0.066470494209706 424 | -0.106338553472755 425 | -0.029556247483918 426 | -0.080778493974592 427 | -0.046876059940052 428 | -0.126748712178182 429 | -0.032582479109501 430 | -0.010646589107665 431 | -0.006489850319503 432 | -0.030082640379903 433 | -0.034809123585434 434 | -0.001497869375252 435 | -0.018761742104354 436 | -0.009797350675461 437 | -0.049351378784847 438 | -0.145999102975876 439 | -0.546882809268771 440 | -0.407105729011254 441 | -0.043399950168419 442 | -0.013587814915265 443 | -0.085187156417456 444 | 0.060547872388504 445 | -0.571791005228199 446 | -0.373056783462411 447 | 4.199136375632448 448 | 5.730774734397821 449 | 3.598555773194044 450 | 5.477255481510613 451 | 3.440677757696717 452 | 6.533433414753445 453 | -0.028933314578930 454 | -0.009058547806115 455 | -0.056791466007356 456 | -0.206286450370091 457 | -0.246526980342321 458 | -0.398303747647950 459 | 0.132430861414235 460 | -0.064740631105635 461 | 0.368923140091142 462 | -8.288373070379230 463 | ]; 464 | 465 | t = ''''' : '; 466 | x = mplinsolve(A, b, ''); 467 | t_is(x, ex, 12, [t 'x']); 468 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 469 | x = mplinsolve(full(A), b, ''); 470 | t_is(x, ex, 12, [t 'x (full A)']); 471 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 472 | 473 | t = '\ : '; 474 | x = mplinsolve(A, b, '\'); 475 | t_is(x, ex, 12, [t 'x']); 476 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 477 | x = mplinsolve(full(A), b, '\'); 478 | t_is(x, ex, 12, [t 'x (full A)']); 479 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 480 | 481 | t = '\ (transpose) : '; 482 | opt = struct('tr', 1); 483 | x = mplinsolve(A', b, '\', opt); 484 | t_is(x, ex, 12, [t 'x']); 485 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 486 | x = mplinsolve(full(A'), b, '\', opt); 487 | t_is(x, ex, 12, [t 'x (full A)']); 488 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 489 | 490 | t = 'LU : '; 491 | x = mplinsolve(A, b, 'LU'); 492 | t_is(x, ex, 12, [t 'x']); 493 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 494 | if skipcrash 495 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 496 | else 497 | x = mplinsolve(full(A), b, 'LU'); 498 | t_is(x, ex, 12, [t 'x (full A)']); 499 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 500 | end 501 | 502 | t = 'LU (transpose) : '; 503 | opt = struct('tr', 1); 504 | x = mplinsolve(A', b, 'LU', opt); 505 | t_is(x, ex, 12, [t 'x']); 506 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 507 | if skipcrash 508 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 509 | else 510 | x = mplinsolve(full(A'), b, 'LU', opt); 511 | t_is(x, ex, 12, [t 'x (full A)']); 512 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 513 | end 514 | 515 | t = 'LU3 : '; 516 | x = mplinsolve(A, b, 'LU3'); 517 | t_is(x, ex, 12, [t 'x']); 518 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 519 | if skipcrash 520 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 521 | else 522 | x = mplinsolve(full(A), b, 'LU3'); 523 | t_is(x, ex, 12, [t 'x (full A)']); 524 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 525 | end 526 | t = 'LU, nout = 3, vec = 1, thresh = 1 : '; 527 | opt = struct('nout', 3, 'vec', 1, 'thresh', 1); 528 | x = mplinsolve(A, b, 'LU', opt); 529 | t_is(x, ex, 12, [t 'x']); 530 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 531 | if skipcrash 532 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 533 | else 534 | x = mplinsolve(full(A), b, 'LU', opt); 535 | t_is(x, ex, 12, [t 'x (full A)']); 536 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 537 | end 538 | 539 | t = 'LU3a : '; 540 | x = mplinsolve(A, b, 'LU3a'); 541 | t_is(x, ex, 12, [t 'x']); 542 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 543 | if skipcrash 544 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 545 | else 546 | x = mplinsolve(full(A), b, 'LU3a'); 547 | t_is(x, ex, 12, [t 'x (full A)']); 548 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 549 | end 550 | t = 'LU, nout = 3, vec = 1 : '; 551 | opt = struct('nout', 3, 'vec', 1); 552 | x = mplinsolve(A, b, 'LU', opt); 553 | t_is(x, ex, 12, [t 'x']); 554 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 555 | if skipcrash 556 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 557 | else 558 | x = mplinsolve(full(A), b, 'LU', opt); 559 | t_is(x, ex, 12, [t 'x (full A)']); 560 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 561 | end 562 | 563 | t = 'LU4 : '; 564 | x = mplinsolve(A, b, 'LU4'); 565 | t_is(x, ex, 12, [t 'x']); 566 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 567 | t = 'LU, nout = 4, vec = 1 : '; 568 | opt = struct('nout', 4, 'vec', 1); 569 | x = mplinsolve(A, b, 'LU', opt); 570 | t_is(x, ex, 12, [t 'x']); 571 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 572 | 573 | t = 'LU5 : '; 574 | x = mplinsolve(A, b, 'LU5'); 575 | t_is(x, ex, 12, [t 'x']); 576 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 577 | t = 'LU, nout = 5, vec = 1 : '; 578 | opt = struct('nout', 5, 'vec', 1); 579 | x = mplinsolve(A, b, 'LU', opt); 580 | t_is(x, ex, 12, [t 'x']); 581 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 582 | 583 | t = 'LU3m : '; 584 | x = mplinsolve(A, b, 'LU3m'); 585 | t_is(x, ex, 12, [t 'x']); 586 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 587 | if skipcrash 588 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 589 | else 590 | x = mplinsolve(full(A), b, 'LU3m'); 591 | t_is(x, ex, 12, [t 'x (full A)']); 592 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 593 | end 594 | t = 'LU, nout = 3, vec = 0, thresh = 1 : '; 595 | opt = struct('nout', 3, 'vec', 0, 'thresh', 1); 596 | x = mplinsolve(A, b, 'LU', opt); 597 | t_is(x, ex, 12, [t 'x']); 598 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 599 | if skipcrash 600 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 601 | else 602 | x = mplinsolve(full(A), b, 'LU', opt); 603 | t_is(x, ex, 12, [t 'x (full A)']); 604 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 605 | end 606 | 607 | t = 'LU3am : '; 608 | x = mplinsolve(A, b, 'LU3am'); 609 | t_is(x, ex, 12, [t 'x']); 610 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 611 | if skipcrash 612 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 613 | else 614 | x = mplinsolve(full(A), b, 'LU3am'); 615 | t_is(x, ex, 12, [t 'x (full A)']); 616 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 617 | end 618 | t = 'LU, nout = 3, vec = 0 : '; 619 | opt = struct('nout', 3, 'vec', 0); 620 | x = mplinsolve(A, b, 'LU', opt); 621 | t_is(x, ex, 12, [t 'x']); 622 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 623 | if skipcrash 624 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 625 | else 626 | x = mplinsolve(full(A), b, 'LU', opt); 627 | t_is(x, ex, 12, [t 'x (full A)']); 628 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 629 | end 630 | 631 | t = 'LU4m : '; 632 | x = mplinsolve(A, b, 'LU4m'); 633 | t_is(x, ex, 12, [t 'x']); 634 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 635 | t = 'LU, nout = 4, vec = 0 : '; 636 | opt = struct('nout', 4, 'vec', 0); 637 | x = mplinsolve(A, b, 'LU', opt); 638 | t_is(x, ex, 12, [t 'x']); 639 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 640 | 641 | t = 'LU5m : '; 642 | x = mplinsolve(A, b, 'LU5m'); 643 | t_is(x, ex, 12, [t 'x']); 644 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 645 | t = 'LU, nout = 5, vec = 0 : '; 646 | opt = struct('nout', 5, 'vec', 0); 647 | x = mplinsolve(A, b, 'LU', opt); 648 | t_is(x, ex, 12, [t 'x']); 649 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 650 | 651 | %%----- repeat all LU tests with saved factors ----- 652 | t = 'pre-factored LU : '; 653 | f = mplinsolve(A); 654 | x = mplinsolve(f, b); 655 | t_is(x, ex, 12, [t 'x']); 656 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 657 | if skipcrash 658 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 659 | else 660 | f = mplinsolve(full(A)); 661 | x = mplinsolve(f, b); 662 | t_is(x, ex, 12, [t 'x (full A)']); 663 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 664 | end 665 | 666 | t = 'pre-factored LU3 : '; 667 | f = mplinsolve(A, [], 'LU3'); 668 | x = mplinsolve(f, b, 'LU3'); 669 | t_is(x, ex, 12, [t 'x']); 670 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 671 | if skipcrash 672 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 673 | else 674 | f = mplinsolve(full(A), [], 'LU3'); 675 | x = mplinsolve(f, b, 'LU3'); 676 | t_is(x, ex, 12, [t 'x (full A)']); 677 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 678 | end 679 | t = 'pre-factored LU, nout = 3, vec = 1, thresh = 1 : '; 680 | opt = struct('nout', 3, 'vec', 1, 'thresh', 1); 681 | [x, f] = mplinsolve(A, b, 'LU', opt); 682 | x = mplinsolve(f, b, 'LU', opt); 683 | t_is(x, ex, 12, [t 'x']); 684 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 685 | if skipcrash 686 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 687 | else 688 | opt = struct('nout', 3, 'vec', 1, 'thresh', 1); 689 | [x, f] = mplinsolve(full(A), b, 'LU', opt); 690 | x = mplinsolve(f, b, 'LU', opt); 691 | t_is(x, ex, 12, [t 'x (full A)']); 692 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 693 | end 694 | 695 | t = 'pre-factored LU3a : '; 696 | [x1, f] = mplinsolve(A, b, 'LU3a'); 697 | x = mplinsolve(f, b, 'LU3a'); 698 | t_is(x, ex, 12, [t 'x']); 699 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 700 | if skipcrash 701 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 702 | else 703 | [x1, f] = mplinsolve(full(A), b, 'LU3a'); 704 | x = mplinsolve(f, b, 'LU3a'); 705 | t_is(x, ex, 12, [t 'x (full A)']); 706 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 707 | end 708 | t = 'pre-factored LU, nout = 3, vec = 1 : '; 709 | opt = struct('nout', 3, 'vec', 1); 710 | f = mplinsolve(A, [], 'LU', opt); 711 | x = mplinsolve(f, b, 'LU', opt); 712 | t_is(x, ex, 12, [t 'x']); 713 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 714 | if skipcrash 715 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 716 | else 717 | opt = struct('nout', 3, 'vec', 1); 718 | f = mplinsolve(full(A), [], 'LU', opt); 719 | x = mplinsolve(f, b, 'LU', opt); 720 | t_is(x, ex, 12, [t 'x (full A)']); 721 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 722 | end 723 | 724 | t = 'pre-factored LU4 : '; 725 | [x, f] = mplinsolve(A, b, 'LU4'); 726 | x = mplinsolve(f, b, 'LU4'); 727 | t_is(x, ex, 12, [t 'x']); 728 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 729 | t = 'pre-factored LU, nout = 4, vec = 1 : '; 730 | opt = struct('nout', 4, 'vec', 1); 731 | f = mplinsolve(A, [], 'LU', opt); 732 | x = mplinsolve(f, b, 'LU', opt); 733 | t_is(x, ex, 12, [t 'x']); 734 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 735 | 736 | t = 'pre-factored LU5 : '; 737 | f = mplinsolve(A, [], 'LU5'); 738 | x = mplinsolve(f, b, 'LU5'); 739 | t_is(x, ex, 12, [t 'x']); 740 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 741 | t = 'pre-factored LU, nout = 5, vec = 1 : '; 742 | opt = struct('nout', 5, 'vec', 1); 743 | [x, f] = mplinsolve(A, b, 'LU', opt); 744 | x = mplinsolve(f, b, 'LU', opt); 745 | t_is(x, ex, 12, [t 'x']); 746 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 747 | 748 | t = 'pre-factored LU3m : '; 749 | f = mplinsolve(A, [], 'LU3m'); 750 | x = mplinsolve(f, b, 'LU3m'); 751 | t_is(x, ex, 12, [t 'x']); 752 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 753 | if skipcrash 754 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 755 | else 756 | f = mplinsolve(full(A), [], 'LU3m'); 757 | x = mplinsolve(f, b, 'LU3m'); 758 | t_is(x, ex, 12, [t 'x (full A)']); 759 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 760 | end 761 | t = 'pre-factored LU, nout = 3, vec = 0, thresh = 1 : '; 762 | opt = struct('nout', 3, 'vec', 0, 'thresh', 1); 763 | [x, f] = mplinsolve(A, b, 'LU', opt); 764 | x = mplinsolve(f, b, 'LU', opt); 765 | t_is(x, ex, 12, [t 'x']); 766 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 767 | if skipcrash 768 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 769 | else 770 | opt = struct('nout', 3, 'vec', 0, 'thresh', 1); 771 | f = mplinsolve(full(A), [], 'LU', opt); 772 | x = mplinsolve(f, b, 'LU', opt); 773 | t_is(x, ex, 12, [t 'x (full A)']); 774 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 775 | end 776 | 777 | t = 'pre-factored LU3am : '; 778 | f = mplinsolve(A, [], 'LU3am'); 779 | x = mplinsolve(f, b, 'LU3am'); 780 | t_is(x, ex, 12, [t 'x']); 781 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 782 | if skipcrash 783 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 784 | else 785 | f = mplinsolve(full(A), [], 'LU3am'); 786 | x = mplinsolve(f, b, 'LU3am'); 787 | t_is(x, ex, 12, [t 'x (full A)']); 788 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 789 | end 790 | t = 'pre-factored LU, nout = 3, vec = 0 : '; 791 | opt = struct('nout', 3, 'vec', 0); 792 | f = mplinsolve(A, [], 'LU', opt); 793 | x = mplinsolve(f, b, 'LU', opt); 794 | t_is(x, ex, 12, [t 'x']); 795 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 796 | if skipcrash 797 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 798 | else 799 | opt = struct('nout', 3, 'vec', 0); 800 | [x, f] = mplinsolve(full(A), b, 'LU', opt); 801 | x = mplinsolve(f, b, 'LU', opt); 802 | t_is(x, ex, 12, [t 'x (full A)']); 803 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 804 | end 805 | 806 | t = 'pre-factored LU4m : '; 807 | [x1, f] = mplinsolve(A, b, 'LU4m'); 808 | x = mplinsolve(f, b, 'LU4m'); 809 | t_is(x, ex, 12, [t 'x']); 810 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 811 | t = 'pre-factored LU, nout = 4, vec = 0 : '; 812 | opt = struct('nout', 4, 'vec', 0); 813 | f = mplinsolve(A, [], 'LU', opt); 814 | x = mplinsolve(f, b, 'LU', opt); 815 | t_is(x, ex, 12, [t 'x']); 816 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 817 | 818 | t = 'pre-factored LU5m : '; 819 | f = mplinsolve(A, [], 'LU5m'); 820 | x = mplinsolve(f, b, 'LU5m'); 821 | t_is(x, ex, 12, [t 'x']); 822 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 823 | t = 'pre-factored LU, nout = 5, vec = 0 : '; 824 | opt = struct('nout', 5, 'vec', 0); 825 | [x, f] = mplinsolve(A, b, 'LU', opt); 826 | x = mplinsolve(f, b, 'LU', opt); 827 | t_is(x, ex, 12, [t 'x']); 828 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 829 | 830 | %%----- repeat all LU tests with saved factors AND transpose ----- 831 | t = 'transposed LU : '; 832 | f = mplinsolve(A'); 833 | x = mplinsolve(f, b, 'LU', struct('tr', 1)); 834 | t_is(x, ex, 12, [t 'x']); 835 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 836 | if skipcrash 837 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 838 | else 839 | f = mplinsolve(full(A')); 840 | x = mplinsolve(f, b, 'LU', struct('tr', 1)); 841 | t_is(x, ex, 12, [t 'x (full A)']); 842 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 843 | end 844 | 845 | t = 'transposed LU3 : '; 846 | f = mplinsolve(A', [], 'LU3'); 847 | x = mplinsolve(f, b, 'LU3', struct('tr', 1)); 848 | t_is(x, ex, 12, [t 'x']); 849 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 850 | if skipcrash 851 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 852 | else 853 | [x1, f] = mplinsolve(full(A'), b, 'LU3'); 854 | x = mplinsolve(f, b, 'LU3', struct('tr', 1)); 855 | t_is(x, ex, 12, [t 'x (full A)']); 856 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 857 | end 858 | t = 'transposed LU, nout = 3, vec = 1, thresh = 1 : '; 859 | opt = struct('nout', 3, 'vec', 1, 'thresh', 1); 860 | [x, f] = mplinsolve(A', b, 'LU', opt); 861 | opt.tr = 1; 862 | x = mplinsolve(f, b, 'LU', opt); 863 | t_is(x, ex, 12, [t 'x']); 864 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 865 | if skipcrash 866 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 867 | else 868 | opt = struct('nout', 3, 'vec', 1, 'thresh', 1); 869 | [x, f] = mplinsolve(full(A'), b, 'LU', opt); 870 | opt.tr = 1; 871 | x = mplinsolve(f, b, 'LU', opt); 872 | t_is(x, ex, 12, [t 'x (full A)']); 873 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 874 | end 875 | 876 | t = 'transposed LU3a : '; 877 | f = mplinsolve(A', [], 'LU3a'); 878 | x = mplinsolve(f, b, 'LU3a', struct('tr', 1)); 879 | t_is(x, ex, 12, [t 'x']); 880 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 881 | if skipcrash 882 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 883 | else 884 | f = mplinsolve(full(A'), [], 'LU3a'); 885 | x = mplinsolve(f, b, 'LU3a', struct('tr', 1)); 886 | t_is(x, ex, 12, [t 'x (full A)']); 887 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 888 | end 889 | t = 'transposed LU, nout = 3, vec = 1 : '; 890 | opt = struct('nout', 3, 'vec', 1); 891 | f = mplinsolve(A', [], 'LU', opt); 892 | opt.tr = 1; 893 | x = mplinsolve(f, b, 'LU', opt); 894 | t_is(x, ex, 12, [t 'x']); 895 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 896 | if skipcrash 897 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 898 | else 899 | opt = struct('nout', 3, 'vec', 1); 900 | [x, f] = mplinsolve(full(A'), b, 'LU', opt); 901 | opt.tr = 1; 902 | x = mplinsolve(f, b, 'LU', opt); 903 | t_is(x, ex, 12, [t 'x (full A)']); 904 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 905 | end 906 | 907 | t = 'transposed LU4 : '; 908 | [x1, f] = mplinsolve(A', b, 'LU4'); 909 | x = mplinsolve(f, b, 'LU4', struct('tr', 1)); 910 | t_is(x, ex, 12, [t 'x']); 911 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 912 | t = 'transposed LU, nout = 4, vec = 1 : '; 913 | opt = struct('nout', 4, 'vec', 1); 914 | f = mplinsolve(A', [], 'LU', opt); 915 | opt.tr = 1; 916 | x = mplinsolve(f, b, 'LU', opt); 917 | t_is(x, ex, 12, [t 'x']); 918 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 919 | 920 | t = 'transposed LU5 : '; 921 | f = mplinsolve(A', [], 'LU5'); 922 | x = mplinsolve(f, b, 'LU5', struct('tr', 1)); 923 | t_is(x, ex, 12, [t 'x']); 924 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 925 | t = 'transposed LU, nout = 5, vec = 1 : '; 926 | opt = struct('nout', 5, 'vec', 1); 927 | f = mplinsolve(A', [], 'LU', opt); 928 | opt.tr = 1; 929 | x = mplinsolve(f, b, 'LU', opt); 930 | t_is(x, ex, 12, [t 'x']); 931 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 932 | 933 | t = 'transposed LU3m : '; 934 | [x1, f] = mplinsolve(A', b, 'LU3m'); 935 | x = mplinsolve(f, b, 'LU3m', struct('tr', 1)); 936 | t_is(x, ex, 12, [t 'x']); 937 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 938 | if skipcrash 939 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 940 | else 941 | f = mplinsolve(full(A'), [], 'LU3m'); 942 | x = mplinsolve(f, b, 'LU3m', struct('tr', 1)); 943 | t_is(x, ex, 12, [t 'x (full A)']); 944 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 945 | end 946 | t = 'transposed LU, nout = 3, vec = 0, thresh = 1 : '; 947 | opt = struct('nout', 3, 'vec', 0, 'thresh', 1); 948 | f = mplinsolve(A', [], 'LU', opt); 949 | opt.tr = 1; 950 | x = mplinsolve(f, b, 'LU', opt); 951 | t_is(x, ex, 12, [t 'x']); 952 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 953 | if skipcrash 954 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 955 | else 956 | opt = struct('nout', 3, 'vec', 0, 'thresh', 1); 957 | [x, f] = mplinsolve(full(A'), b, 'LU', opt); 958 | opt.tr = 1; 959 | x = mplinsolve(f, b, 'LU', opt); 960 | t_is(x, ex, 12, [t 'x (full A)']); 961 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 962 | end 963 | 964 | t = 'transposed LU3am : '; 965 | [x1, f] = mplinsolve(A', b, 'LU3am'); 966 | x = mplinsolve(f, b, 'LU3am', struct('tr', 1)); 967 | t_is(x, ex, 12, [t 'x']); 968 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 969 | if skipcrash 970 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 971 | else 972 | f = mplinsolve(full(A'), [], 'LU3am'); 973 | x = mplinsolve(f, b, 'LU3am', struct('tr', 1)); 974 | t_is(x, ex, 12, [t 'x (full A)']); 975 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 976 | end 977 | t = 'transposed LU, nout = 3, vec = 0 : '; 978 | opt = struct('nout', 3, 'vec', 0); 979 | f = mplinsolve(A', [], 'LU', opt); 980 | opt.tr = 1; 981 | x = mplinsolve(f, b, 'LU', opt); 982 | t_is(x, ex, 12, [t 'x']); 983 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 984 | if skipcrash 985 | t_skip(2, [t 'potential MATLAB crash with non-sparse A']); 986 | else 987 | opt = struct('nout', 3, 'vec', 0); 988 | f = mplinsolve(full(A'), [], 'LU', opt); 989 | opt.tr = 1; 990 | x = mplinsolve(f, b, 'LU', opt); 991 | t_is(x, ex, 12, [t 'x (full A)']); 992 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x|| (full A)']); 993 | end 994 | 995 | t = 'transposed LU4m : '; 996 | f = mplinsolve(A', [], 'LU4m'); 997 | x = mplinsolve(f, b, 'LU4m', struct('tr', 1)); 998 | t_is(x, ex, 12, [t 'x']); 999 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 1000 | t = 'transposed LU, nout = 4, vec = 0 : '; 1001 | opt = struct('nout', 4, 'vec', 0); 1002 | f = mplinsolve(A', [], 'LU', opt); 1003 | opt.tr = 1; 1004 | x = mplinsolve(f, b, 'LU', opt); 1005 | t_is(x, ex, 12, [t 'x']); 1006 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 1007 | 1008 | t = 'transposed LU5m : '; 1009 | [x1, f] = mplinsolve(A', b, 'LU5m'); 1010 | x = mplinsolve(f, b, 'LU5m', struct('tr', 1)); 1011 | t_is(x, ex, 12, [t 'x']); 1012 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 1013 | t = 'transposed LU, nout = 5, vec = 0 : '; 1014 | opt = struct('nout', 5, 'vec', 0); 1015 | [x, f] = mplinsolve(A', b, 'LU', opt); 1016 | opt.tr = 1; 1017 | x = mplinsolve(f, b, 'LU', opt); 1018 | t_is(x, ex, 12, [t 'x']); 1019 | t_is(norm(b - A*x), 0, 12, [t '||b - A*x||']); 1020 | 1021 | %% PARDISO 1022 | if have_feature('pardiso') 1023 | if have_feature('pardiso_object') 1024 | tols = [6 5 12 12 6 5]; %% tolerances for PARDISO v6 1025 | else 1026 | tols = [13 13 12 12 1 2]; %% tolerances for PARDISO v5 1027 | end 1028 | vb = false; 1029 | 1030 | t = 'PARDISO (direct) : '; 1031 | opt = struct('pardiso', struct('solver', 0, 'verbose', vb)); 1032 | x = mplinsolve(A, b, 'PARDISO', opt); 1033 | t_is(x, ex, tols(1), [t 'x']); 1034 | t_is(norm(b - A*x), 0, tols(2), [t '||b - A*x||']); 1035 | 1036 | t = 'PARDISO (direct, transpose) : '; 1037 | opt = struct('pardiso', struct('solver', 0, 'tr', 1, 'verbose', vb)); 1038 | x = mplinsolve(A', b, 'PARDISO', opt); 1039 | t_is(x, ex, tols(1), [t 'x']); 1040 | t_is(norm(b - A*x), 0, tols(2), [t '||b - A*x||']); 1041 | 1042 | t = 'PARDISO (direct, symmetric indefinite) : '; 1043 | opt = struct('pardiso', struct('solver', 0, 'mtype', -2, 'verbose', vb)); 1044 | x = mplinsolve(A, b, 'PARDISO', opt); 1045 | t_is(x, ex, tols(3), [t 'x']); 1046 | t_is(norm(b - A*x), 0, tols(4), [t '||b - A*x||']); 1047 | 1048 | t = 'PARDISO (iterative) : '; 1049 | opt = struct('pardiso', struct('solver', 1, 'verbose', vb)); 1050 | [x, info] = mplinsolve(A, b, 'PARDISO', opt); 1051 | t_is(x, ex, tols(5), [t 'x']); 1052 | t_is(norm(b - A*x), 0, tols(6), [t '||b - A*x||']); 1053 | else 1054 | t_skip(8, ['PARDISO not available']); 1055 | end 1056 | 1057 | if isoctave 1058 | warning(s.state, lu_warning_id); 1059 | end 1060 | 1061 | t_end; 1062 | --------------------------------------------------------------------------------