├── .bumpversion.cfg ├── .github ├── ISSUE_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── build.yml │ ├── build_mkl.yml │ ├── build_openmp.yml │ ├── buildpp.yml │ ├── cmake.yml │ ├── cmake_mkl.yml │ ├── cmake_openmp.yml │ ├── coverage.yml │ ├── docs.yml │ ├── gpu.yml │ └── valgrind.yml ├── .gitignore ├── CITATION.cff ├── CMakeLists.txt ├── LICENSE.txt ├── Makefile ├── README.md ├── cmake ├── AddInstallRPATHSupport.cmake ├── AddUninstallTarget.cmake ├── InstallBasicPackageFiles.cmake └── scs_types.h.in ├── docs └── src │ ├── Doxyfile │ ├── Makefile │ ├── _static │ ├── css │ │ └── scs_theme.css │ ├── favicon.ico │ ├── scs_logo.png │ └── scs_logo_transparent.png │ ├── algorithm │ ├── acceleration.rst │ ├── equilibration.rst │ ├── index.rst │ ├── relaxation.rst │ ├── scale.rst │ └── warm_start.rst │ ├── api │ ├── c.rst │ ├── compile_flags.rst │ ├── cones.rst │ ├── exit_flags.rst │ ├── index.rst │ ├── info.rst │ ├── javascript.rst │ ├── julia.rst │ ├── matlab.rst │ ├── matrices.rst │ ├── python.rst │ ├── r.rst │ ├── ruby.rst │ └── settings.rst │ ├── blas_lapack │ └── index.rst │ ├── citing │ └── index.rst │ ├── conf.py │ ├── contributing │ └── index.rst │ ├── examples │ ├── .gitignore │ ├── c.rst │ ├── index.rst │ ├── javascript.rst │ ├── javascript_disc.html │ ├── julia.rst │ ├── matlab.rst │ ├── python.rst │ ├── python │ │ ├── basic_qp.rst │ │ ├── entropy.py │ │ ├── entropy.py.out │ │ ├── entropy.rst │ │ ├── lasso.py │ │ ├── lasso.py.out │ │ ├── lasso.rst │ │ ├── mat_completion.py │ │ ├── mat_completion.py.out │ │ ├── mat_completion.rst │ │ ├── mpc.py │ │ ├── mpc.py.out │ │ ├── mpc.rst │ │ ├── qp.py │ │ └── qp.py.out │ ├── qp.c │ ├── qp.c.out │ ├── qp.m │ ├── qp.m.out │ ├── qp.prob │ ├── r.rst │ └── ruby.rst │ ├── files │ ├── qp_solvers_benchmark.png │ ├── windows1.png │ ├── windows2.png │ └── windows3.png │ ├── help │ └── index.rst │ ├── index.rst │ ├── install │ ├── c.rst │ ├── index.rst │ ├── javascript.rst │ ├── julia.rst │ ├── matlab.rst │ ├── python.rst │ ├── r.rst │ └── ruby.rst │ ├── linear_solver │ └── index.rst │ ├── make.bat │ └── requirements.txt ├── include ├── aa.h ├── cones.h ├── ctrlc.h ├── glbopts.h ├── linalg.h ├── linsys.h ├── normalize.h ├── rw.h ├── scs.h ├── scs_blas.h ├── scs_types.h ├── scs_work.h └── util.h ├── linsys ├── cpu │ ├── direct │ │ ├── private.c │ │ └── private.h │ └── indirect │ │ ├── private.c │ │ └── private.h ├── csparse.c ├── csparse.h ├── external │ ├── amd │ │ ├── LICENSE.txt │ │ ├── SuiteSparse_config.c │ │ ├── SuiteSparse_config.h │ │ ├── amd.h │ │ ├── amd_1.c │ │ ├── amd_2.c │ │ ├── amd_aat.c │ │ ├── amd_control.c │ │ ├── amd_defaults.c │ │ ├── amd_dump.c │ │ ├── amd_global.c │ │ ├── amd_info.c │ │ ├── amd_internal.h │ │ ├── amd_order.c │ │ ├── amd_post_tree.c │ │ ├── amd_postorder.c │ │ ├── amd_preprocess.c │ │ ├── amd_valid.c │ │ └── changes │ └── qdldl │ │ ├── LICENSE │ │ ├── README.md │ │ ├── changes │ │ ├── qdldl.c │ │ ├── qdldl.h │ │ └── qdldl_types.h ├── gpu │ ├── gpu.c │ ├── gpu.h │ └── indirect │ │ ├── private.c │ │ └── private.h ├── mkl │ └── direct │ │ ├── private.c │ │ └── private.h ├── scs_matrix.c └── scs_matrix.h ├── scs.mk ├── src ├── aa.c ├── cones.c ├── ctrlc.c ├── exp_cone.c ├── linalg.c ├── normalize.c ├── rw.c ├── scs.c ├── scs_version.c └── util.c └── test ├── minunit.h ├── problem_utils.h ├── problems ├── degenerate.h ├── hs21_tiny_qp.h ├── hs21_tiny_qp_rw.h ├── infeasible_tiny_qp.h ├── max_ent ├── max_ent.h ├── mpc_bug.h ├── mpc_bug1 ├── mpc_bug2 ├── mpc_bug3 ├── qafiro_tiny_qp.h ├── random_prob ├── random_prob.h ├── rob_gauss_cov_est.h ├── small_lp.h ├── small_qp.h ├── test_exp_cone.h ├── test_prob_from_data_file.h ├── test_validation.h └── unbounded_tiny_qp.h ├── random_socp_prob.c ├── rng.h ├── run_from_file.c └── run_tests.c /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 3.2.7 3 | 4 | [bumpversion:file:README.md] 5 | 6 | [bumpversion:file:CITATION.cff] 7 | 8 | [bumpversion:file:include/glbopts.h] 9 | 10 | [bumpversion:file:CMakeLists.txt] 11 | 12 | [bumpversion:file:docs/src/conf.py] 13 | 14 | [bumpversion:file:docs/src/Doxyfile] 15 | 16 | [bumpversion:file:docs/src/citing/index.rst] 17 | 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Please read this first** 2 | 3 | If you are have a problem that SCS struggles with you can pass a string to the 4 | `write_data_filename` argument and SCS will dump a file containing the problem 5 | to disk. Zip the file and send it to us or attach it to this bug report for easy 6 | reproduction of the issue. 7 | 8 | A common cause of issues is not linking BLAS/LAPACK libraries correctly. If you 9 | are having this issue please search for resources on installing and linking 10 | these libraries first. You can try openblas if you need a BLAS library. 11 | 12 | 13 | ## Specifications 14 | - OS: 15 | - SCS Version: 16 | - Compiler: 17 | 18 | ## Description 19 | A clear and concise description of the problem. 20 | 21 | ## How to reproduce 22 | Ideally a minimal snippet of code that reproduces the problem if possible. 23 | 24 | ## Additional information 25 | Extra context. 26 | 27 | ## Output 28 | Entire SCS output including the entire stack trace if applicable. 29 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build and Test 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | long: [0, 1] 12 | lapack: [0, 1] 13 | 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - run: sudo apt-get install libopenblas-dev liblapack-dev 18 | - run: make DLONG=${{ matrix.long }} USE_LAPACK=${{ matrix.lapack }} 19 | - run: make test DLONG=${{ matrix.long }} USE_LAPACK=${{ matrix.lapack }} 20 | - run: out/run_tests_direct # test direct solver 21 | - run: out/run_tests_indirect # test indirect solver 22 | 23 | # runs-on: windows-latest 24 | # steps: 25 | # - uses: actions/checkout@v4 26 | # - run: choco install clapack 27 | # - run: make 28 | # - run: make test 29 | # - run: test/run_tests 30 | 31 | mac: 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | long: [0, 1] 36 | lapack: [0, 1] 37 | 38 | runs-on: macos-latest 39 | steps: 40 | - uses: actions/checkout@v4 41 | - run: brew install openblas lapack 42 | - run: make DLONG=${{ matrix.long }} USE_LAPACK=${{ matrix.lapack }} 43 | - run: make test DLONG=${{ matrix.long }} USE_LAPACK=${{ matrix.lapack }} 44 | - run: out/run_tests_direct # test direct solver 45 | - run: out/run_tests_indirect # test indirect solver 46 | -------------------------------------------------------------------------------- /.github/workflows/build_mkl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build and Test MKL 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | long: [0, 1] 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Intel Apt repository 17 | run: | 18 | wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 19 | sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 20 | rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 21 | echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list 22 | sudo apt-get update 23 | 24 | - name: Install Intel oneAPI 25 | run: sudo apt-get install intel-mkl 26 | 27 | - name: Setup Intel oneAPI environment 28 | run: | 29 | # TODO: hack to set MKLROOT for now 30 | echo "MKLROOT=/usr/lib/x86_64-linux-gnu" >> $GITHUB_ENV 31 | # source /opt/intel/mkl/bin/mklvars.sh 32 | 33 | - name: checkout project code 34 | uses: actions/checkout@v4 35 | 36 | - name: Build SCS MKL and test 37 | run: | 38 | make DLONG=${{ matrix.long }} mkl 39 | out/run_tests_mkl 40 | -------------------------------------------------------------------------------- /.github/workflows/build_openmp.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build and Test OpenMP 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | strategy: 9 | fail-fast: false 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: checkout project code 15 | uses: actions/checkout@v4 16 | 17 | - name: install deps 18 | run: sudo apt-get install libopenblas-dev liblapack-dev 19 | 20 | - name: Build SCS with OpenMP and test 21 | run: | 22 | make USE_OPENMP=1 test 23 | out/run_tests_direct 24 | out/run_tests_indirect 25 | -------------------------------------------------------------------------------- /.github/workflows/buildpp.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build C++ # test that we can compile SCS with C++ compiler 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - run: | 12 | sudo apt-get install libopenblas-dev liblapack-dev 13 | export CC=g++ 14 | echo $CC 15 | make 16 | make test 17 | out/run_tests_direct # test direct solver 18 | out/run_tests_indirect # test indirect solver 19 | 20 | # runs-on: windows-latest 21 | # steps: 22 | # - uses: actions/checkout@v4 23 | # - run: choco install clapack 24 | # - run: make 25 | # - run: make test 26 | # - run: test/run_tests 27 | 28 | mac: 29 | runs-on: macos-latest 30 | steps: 31 | - uses: actions/checkout@v4 32 | - run: | 33 | brew install openblas lapack 34 | export CC=clang++ 35 | echo $CC 36 | make 37 | make test 38 | out/run_tests_direct # test direct solver 39 | out/run_tests_indirect # test indirect solver 40 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CMake 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - run: | 12 | sudo apt-get install libopenblas-dev liblapack-dev 13 | mkdir out 14 | export INSTALL_DIR=$PWD/out 15 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_DIR/lib 16 | mkdir build 17 | cd build 18 | cmake -DBUILD_TESTING=ON -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR .. 19 | make 20 | make install 21 | ctest --output-on-failure 22 | cd ../docs/src/examples/ 23 | gcc -I$INSTALL_DIR/include/scs -L$INSTALL_DIR/lib/ qp.c -o qp.out -lscsdir 24 | ./qp.out 25 | 26 | mac: 27 | runs-on: macos-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | - run: | 31 | brew install openblas lapack 32 | mkdir out 33 | export INSTALL_DIR=$PWD/out 34 | export DYLD_FALLBACK_LIBRARY_PATH=$DYLD_FALLBACK_LIBRARY_PATH:$INSTALL_DIR/lib 35 | mkdir build 36 | cd build 37 | cmake -DBUILD_TESTING=ON -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR .. 38 | make 39 | make install 40 | ctest --output-on-failure 41 | cd ../docs/src/examples/ 42 | gcc -I$INSTALL_DIR/include/scs -L$INSTALL_DIR/lib/ qp.c -o qp.out -lscsdir 43 | ./qp.out 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/cmake_mkl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CMake MKL 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Intel Apt repository 11 | run: | 12 | wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 13 | sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 14 | rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB 15 | echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list 16 | sudo apt-get update 17 | 18 | - name: Install Intel oneAPI 19 | run: sudo apt-get install intel-mkl 20 | 21 | - name: Setup Intel oneAPI environment 22 | run: | 23 | # TODO: hack to set MKLROOT for now 24 | echo "MKLROOT=/usr/lib/x86_64-linux-gnu" >> $GITHUB_ENV 25 | # source /opt/intel/mkl/bin/mklvars.sh 26 | 27 | - name: checkout project code 28 | uses: actions/checkout@v4 29 | 30 | - name: Build SCS MKL and test 31 | run: | 32 | mkdir out 33 | export INSTALL_DIR=$PWD/out 34 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_DIR/lib 35 | mkdir build 36 | cd build 37 | cmake -DBUILD_TESTING=ON -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR .. 38 | make 39 | make install 40 | ctest --output-on-failure 41 | cd ../docs/src/examples/ 42 | gcc -I$INSTALL_DIR/include/scs -L$INSTALL_DIR/lib/ qp.c -o qp.out -lscsmkl 43 | ./qp.out 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/cmake_openmp.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CMake OpenMP 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - run: | 12 | sudo apt-get install libopenblas-dev liblapack-dev 13 | mkdir out 14 | export INSTALL_DIR=$PWD/out 15 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_DIR/lib 16 | mkdir build 17 | cd build 18 | cmake -DUSE_OPENMP=ON -DBUILD_TESTING=ON -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR .. 19 | make 20 | make install 21 | ctest --output-on-failure 22 | cd ../docs/src/examples/ 23 | gcc -I$INSTALL_DIR/include/scs -L$INSTALL_DIR/lib/ qp.c -o qp.out -lscsdir 24 | ./qp.out 25 | 26 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coveralls 2 | 3 | on: ["push", "pull_request"] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Check out 10 | uses: actions/checkout@v4 11 | with: 12 | submodules: 'recursive' 13 | 14 | - name: Set up 15 | run: sudo apt-get install -y libopenblas-dev liblapack-dev lcov 16 | 17 | - name: Make 18 | run: make test COVERAGE=1 19 | 20 | - name: Run tests 21 | run: out/run_tests_direct && out/run_tests_indirect 22 | 23 | - name: Process coverage 24 | uses: imciner2/run-lcov@v1 25 | with: 26 | input_directory: '${{ runner.workspace }}' 27 | exclude: '"$GITHUB_WORKSPACE/test/*" "$GITHUB_WORKSPACE/linsys/external/*" "/usr/include/x86_64-linux-gnu/bits/*"' 28 | output_file: '${{ runner.workspace }}/coverage.info' 29 | 30 | - name: Upload coverage 31 | uses: coverallsapp/github-action@master 32 | with: 33 | github-token: ${{ secrets.GITHUB_TOKEN }} 34 | path-to-lcov: '${{ runner.workspace }}/coverage.info' 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | - name: Install OS dependencies 15 | run: | 16 | sudo apt-get install doxygen 17 | - name: Setup Python 18 | uses: actions/setup-python@v5 19 | - name: Install Python dependencies 20 | run: | 21 | pip install sphinx sphinx-rtd-theme breathe docutils 22 | - name: Build docs 23 | run: | 24 | cd docs/src && make docs && touch ../.nojekyll 25 | - name: Deploy 26 | uses: JamesIves/github-pages-deploy-action@v4.7.3 27 | with: 28 | branch: gh-pages # The branch the action should deploy to. 29 | folder: docs # The folder the action should deploy. 30 | 31 | -------------------------------------------------------------------------------- /.github/workflows/gpu.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: GPU 3 | on: 4 | - push 5 | - pull_request 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: Jimver/cuda-toolkit@v0.2.23 12 | id: cuda-toolkit 13 | with: 14 | method: network 15 | non-cuda-sub-packages: '["libcublas", "libcusparse", "libcudart"]' 16 | - run: sudo apt-get install libopenblas-dev liblapack-dev 17 | - run: make gpu 18 | - run: make test_gpu 19 | # - run: out/run_tests_gpu_indirect # gpus not available yet 20 | -------------------------------------------------------------------------------- /.github/workflows/valgrind.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Valgrind 3 | 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | linux: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - run: sudo apt-get update 12 | - run: sudo apt-get install libopenblas-dev liblapack-dev valgrind 13 | - run: make 14 | - run: make test 15 | - run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --show-reachable=yes --error-exitcode=1 out/run_tests_direct 16 | - run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --show-reachable=yes --error-exitcode=1 out/run_tests_indirect 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gcno 2 | *.csv 3 | *.iml 4 | docs/* 5 | !docs/src 6 | examples/DIMACS/ 7 | local.mk 8 | sftp-config.json 9 | .settings 10 | .cproject 11 | .project 12 | .pydevproject 13 | .idea 14 | *.pyc 15 | *dSYM 16 | *demo_direct 17 | *demo_indirect 18 | python/flags.tmp 19 | python/.coverage 20 | python/build/ 21 | python/cover/ 22 | python_dist 23 | linsys_dense/out 24 | out 25 | .swo 26 | *.o 27 | *.a 28 | *.DS_Store 29 | *.out 30 | *.nav 31 | *.dvi 32 | *.ps 33 | *.pdf 34 | *.aux 35 | *.log 36 | *.bbl 37 | *.blg 38 | *.toc 39 | *.swp 40 | *.m~ 41 | *.mat 42 | *.mex* 43 | *.mexmaci 44 | *.mexa64 45 | *.mexmaci64 46 | *.dependencies 47 | *.classpath 48 | *.class 49 | *.dylib 50 | *.jar 51 | hs21_tiny_qp 52 | rob_gauss_cov_est 53 | build/ 54 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: "If you use this software, please cite it as below." 3 | authors: 4 | - family-names: "O'Donoghue" 5 | given-names: "Brendan" 6 | - family-names: "Chu" 7 | given-names: "Eric" 8 | - family-names: "Parikh" 9 | given-names: "Neal" 10 | - family-names: "Boyd" 11 | given-names: "Stephen" 12 | title: "SCS: Spltting Conic Solver" 13 | version: 3.2.7 14 | date-released: 2023 15 | url: "https://github.com/cvxgrp/scs" 16 | 17 | # Original SCS paper: 18 | preferred-citation: 19 | type: article 20 | authors: 21 | - family-names: "O'Donoghue" 22 | given-names: "Brendan" 23 | - family-names: "Chu" 24 | given-names: "Eric" 25 | - family-names: "Parikh" 26 | given-names: "Neal" 27 | - family-names: "Boyd" 28 | given-names: "Stephen" 29 | journal: "Journal of Optimization Theory and Applications" 30 | month: 6 31 | start: 1042 # Start pages 32 | end: 1068 # End pages 33 | title: "Conic Optimization via Operator Splitting and Homogeneous Self-Dual Embedding" 34 | issue: 3 35 | volume: 169 36 | year: 2016 37 | doi: 10.1007/s10957-016-0892-3 38 | url: https://dx.doi.org/10.1007/s10957-016-0892-3 39 | 40 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012 Brendan O'Donoghue (bodonoghue85@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Intersection of a cone and a polyhedron 3 |

4 | 5 | [![Build Status](https://github.com/cvxgrp/scs/actions/workflows/build.yml/badge.svg)](https://github.com/cvxgrp/scs/actions/workflows/build.yml) 6 | [![Documentation](https://img.shields.io/badge/docs-online-brightgreen?logo=read-the-docs&style=flat)](https://www.cvxgrp.org/scs/) 7 | [![Coverage Status](https://coveralls.io/repos/github/cvxgrp/scs/badge.svg?branch=master)](https://coveralls.io/github/cvxgrp/scs?branch=master) 8 | 9 | 10 | SCS (`splitting conic solver`) is a numerical optimization package for solving 11 | large-scale convex cone problems. The current version is `3.2.7`. 12 | 13 | The full documentation is available [here](https://www.cvxgrp.org/scs/). 14 | 15 | If you wish to cite SCS please cite the papers listed [here](https://www.cvxgrp.org/scs/citing). 16 | -------------------------------------------------------------------------------- /cmake/AddUninstallTarget.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # AddUninstallTarget 3 | # ------------------ 4 | # 5 | # Add the "uninstall" target for your project:: 6 | # 7 | # include(AddUninstallTarget) 8 | # 9 | # 10 | # will create a file cmake_uninstall.cmake in the build directory and add a 11 | # custom target uninstall that will remove the files installed by your package 12 | # (using install_manifest.txt) 13 | 14 | #============================================================================= 15 | # Copyright 2008-2013 Kitware, Inc. 16 | # Copyright 2013 Istituto Italiano di Tecnologia (IIT) 17 | # Authors: Daniele E. Domenichelli 18 | # 19 | # Distributed under the OSI-approved BSD License (the "License"); 20 | # see accompanying file Copyright.txt for details. 21 | # 22 | # This software is distributed WITHOUT ANY WARRANTY; without even the 23 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 24 | # See the License for more information. 25 | #============================================================================= 26 | # (To distribute this file outside of CMake, substitute the full 27 | # License text for the above reference.) 28 | 29 | 30 | if(DEFINED __ADD_UNINSTALL_TARGET_INCLUDED) 31 | return() 32 | endif() 33 | set(__ADD_UNINSTALL_TARGET_INCLUDED TRUE) 34 | 35 | 36 | set(_filename ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 37 | 38 | file(WRITE ${_filename} 39 | "if(NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\") 40 | message(WARNING \"Cannot find install manifest: \\\"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\\\"\") 41 | return() 42 | endif() 43 | 44 | file(READ \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\" files) 45 | string(STRIP \"\${files}\" files) 46 | string(REGEX REPLACE \"\\n\" \";\" files \"\${files}\") 47 | list(REVERSE files) 48 | foreach(file \${files}) 49 | message(STATUS \"Uninstalling: \$ENV{DESTDIR}\${file}\") 50 | if(EXISTS \"\$ENV{DESTDIR}\${file}\") 51 | execute_process( 52 | COMMAND \${CMAKE_COMMAND} -E remove \"\$ENV{DESTDIR}\${file}\" 53 | OUTPUT_VARIABLE rm_out 54 | RESULT_VARIABLE rm_retval) 55 | if(NOT \"\${rm_retval}\" EQUAL 0) 56 | message(FATAL_ERROR \"Problem when removing \\\"\$ENV{DESTDIR}\${file}\\\"\") 57 | endif() 58 | else() 59 | message(STATUS \"File \\\"\$ENV{DESTDIR}\${file}\\\" does not exist.\") 60 | endif() 61 | endforeach(file) 62 | ") 63 | 64 | if("${CMAKE_GENERATOR}" MATCHES "^(Visual Studio|Xcode)") 65 | set(_uninstall "UNINSTALL") 66 | else() 67 | set(_uninstall "uninstall") 68 | endif() 69 | add_custom_target(${_uninstall} COMMAND "${CMAKE_COMMAND}" -P "${_filename}") 70 | set_property(TARGET ${_uninstall} PROPERTY FOLDER "CMakePredefinedTargets") 71 | -------------------------------------------------------------------------------- /cmake/scs_types.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * GENERATED BY CMAKE 3 | */ 4 | 5 | /* 6 | * Pulic header including definitions of primitive types used in SCS. 7 | * Make sure this file and `scs.h` are somewhere appropriate and then use 8 | * `#include "scs.h"` to access the SCS public API. 9 | */ 10 | 11 | #ifndef SCS_TYPES_H_GUARD 12 | #define SCS_TYPES_H_GUARD 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef @SCS_INT_TYPE@ scs_int; 19 | typedef @SCS_FLOAT_TYPE@ scs_float; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | #endif 25 | -------------------------------------------------------------------------------- /docs/src/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 = . 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 | 22 | docs: 23 | @make html 24 | @cp -a _build/html/. .. 25 | @touch ../.nojekyll 26 | @rm -rf doxygen_out/* 27 | @make clean 28 | 29 | -------------------------------------------------------------------------------- /docs/src/_static/css/scs_theme.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600,600i,700,700i); 2 | 3 | h1, h2, h3, h4, h5, h6 { 4 | font-family: "Open Sans", sans-serif; 5 | font-weight: 600; 6 | } 7 | 8 | body { 9 | font-family: 'Open Sans', sans-serif; 10 | } 11 | 12 | /* no box shadow on buttons */ 13 | .btn { 14 | font-weight: normal; 15 | font-family: "Open Sans", sans-serif; 16 | box-shadow: none; 17 | } 18 | 19 | .wy-side-nav-search { 20 | background-color: rgb(245, 245, 245); 21 | } 22 | 23 | .wy-nav-side { 24 | background: rgb(245, 245, 245); 25 | } 26 | 27 | .wy-side-nav-search>div.version{ 28 | color: rgb(0, 0, 0); 29 | } 30 | 31 | .wy-nav-top { 32 | color: rgb(245, 245, 245); 33 | background-color: rgb(245, 245, 245); 34 | } 35 | 36 | .wy-nav-top i{ 37 | color: rgb(46, 118, 176); 38 | } 39 | 40 | /* Navigation bar text */ 41 | .wy-menu-vertical header, .wy-menu-vertical p.caption { 42 | color: rgb(255, 255, 255); /* White text*/ 43 | font-weight: 600; 44 | } 45 | 46 | .wy-menu-vertical a{ 47 | color: rgb(178, 188, 200); /* Grey */ 48 | } 49 | 50 | .wy-menu-vertical a:hover{ 51 | background: rgb(46, 118, 176); 52 | color: rgb(255, 255, 255); /* White text*/ 53 | } 54 | 55 | /* override table width restrictions */ 56 | .wy-table-responsive table td, .wy-table-responsive table th { 57 | white-space: normal; 58 | } 59 | 60 | .wy-table-responsive { 61 | margin-bottom: 24px; 62 | max-width: 100%; 63 | overflow: visible; 64 | } 65 | 66 | .wy-nav-content-wrap, .wy-menu li.current > a { 67 | background-color: rgb(245, 245, 245); 68 | /* font-weight: 600; */ 69 | } 70 | 71 | /* change page width */ 72 | /*.wy-nav-content { 73 | * max-width: none; 74 | *} 75 | */ 76 | 77 | /* Link Styling */ 78 | a,a:visited, a:focus { 79 | color: rgb(46, 118, 176); /* Light blue */ 80 | text-decoration: none; 81 | } 82 | a:hover, a:active { 83 | color: rgb(0, 32, 72); /* blue */ 84 | text-decoration: none; 85 | } 86 | 87 | .wy-side-nav-search>a{ 88 | color: rgb(0, 0, 0); 89 | } 90 | .wy-nav-top a{ 91 | color: rgb(0, 0, 0); 92 | } 93 | 94 | /* Navigation bar text */ 95 | .wy-menu-vertical header, .wy-menu-vertical p.caption { 96 | color: rgb(0, 0, 0); 97 | font-weight: 600; 98 | } 99 | 100 | .wy-menu-vertical a{ 101 | color: rgb(0, 0, 0); 102 | } 103 | 104 | -------------------------------------------------------------------------------- /docs/src/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/_static/favicon.ico -------------------------------------------------------------------------------- /docs/src/_static/scs_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/_static/scs_logo.png -------------------------------------------------------------------------------- /docs/src/_static/scs_logo_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/_static/scs_logo_transparent.png -------------------------------------------------------------------------------- /docs/src/algorithm/relaxation.rst: -------------------------------------------------------------------------------- 1 | .. _relaxation: 2 | 3 | Relaxation 4 | ========== 5 | 6 | The (unscaled, see :ref:`scaling`) SCS update equations are: 7 | 8 | .. math:: 9 | \begin{align} 10 | \tilde u^{k+1} &= (I + \mathcal{Q})^{-1} w^k \\ 11 | u^{k+1} &= (I + N_{\mathcal{C}_+})^{-1} (2 \tilde u^{k+1} - w^k) \\ 12 | w^{k+1} &= w^k + \alpha (u^{k+1} - \tilde u^{k+1}) \\ 13 | \end{align} 14 | 15 | where :math:`\alpha \in (0,2)` is the *relaxation* parameter. Vanilla 16 | Douglas-Rachford corresponds to setting :math:`\alpha = 1`. If :math:`\alpha < 17 | 1` it is referred to as under-relaxation, if :math:`\alpha > 1` it is 18 | over-relaxation. Typically values of :math:`\alpha \approx 1.5` work well. It 19 | is controlled by the :code:`alpha` :ref:`setting `. If :math:`\alpha 20 | = 2` the method reduces to Peaceman-Rachford splitting, which is not guaranteed 21 | to converge in general (but will if, for example, the operators in the problem 22 | are both maximal strongly monotone). 23 | 24 | Thankfully, there is no interaction between :math:`\alpha` and the scaling 25 | described in :ref:`scaling`, and they can be combined immediately. 26 | -------------------------------------------------------------------------------- /docs/src/algorithm/warm_start.rst: -------------------------------------------------------------------------------- 1 | .. _warm_start: 2 | 3 | Caching the workspace and warm-starts 4 | ------------------------------------- 5 | 6 | SCS supports reusing the workspace between solves so long as the data matrices 7 | :math:`A` and :math:`P` do not change. After an initial solve the workspace can 8 | be updated with new :math:`b` and :math:`c` vectors if desired. This can 9 | substantially speed up subsequent solve times since we can cache important 10 | quantities such as the matrix factorization and the data equilibration. 11 | Moreover, SCS supports warm-starting the solver with a guess of the solution, 12 | which can significantly reduce the total number of iterations required for 13 | convergence. 14 | 15 | Re-using the workspace and warm-starting can be useful, for example, when 16 | solving a sequence of related problems such as in :ref:`Model predictive control 17 | ` or solving for the entire regularization path in the :ref:`the Lasso 18 | `. 19 | 20 | In the :ref:`C API ` call :code:`scs_init` once to initialize the 21 | workspace, then use the :code:`scs_solve` in conjunction with 22 | :code:`scs_update` to solve a sequence of problems. Warm-starting can be done 23 | by setting the warm-start :ref:`setting ` to :code:`True` when calling 24 | :code:`scs_solve`, and then including the guess of the solution in the :code:`x, 25 | y, s` members of the :ref:`ScsSolution` struct, where those members correspond 26 | to the guess of the solution in the :ref:`standard form `. SCS will 27 | initialize the solver at those points and then overwrite the :ref:`ScsSolution` 28 | struct members with the real solution at termination. 29 | 30 | In other languages caching the workspace and warm-starting is documented in 31 | their respective :ref:`interfaces`. 32 | 33 | -------------------------------------------------------------------------------- /docs/src/api/c.rst: -------------------------------------------------------------------------------- 1 | .. _c_interface: 2 | 3 | C / C++ 4 | ======= 5 | 6 | 7 | .. _C_main_API: 8 | 9 | Main solver API 10 | --------------- 11 | 12 | The C API is imported from the header :code:`scs.h`, available `here 13 | `_. This file 14 | and :code:`scs_types.h` are the only public header files required 15 | for downstream applications. 16 | 17 | .. doxygenfunction:: scs_init 18 | .. doxygenfunction:: scs_solve 19 | .. doxygenfunction:: scs_update 20 | .. doxygenfunction:: scs_finish 21 | 22 | Helper functions 23 | ^^^^^^^^^^^^^^^^ 24 | 25 | This sets the :ref:`ScsSettings ` struct to the default values as 26 | specified in the :ref:`settings` page. 27 | 28 | .. doxygenfunction:: scs_set_default_settings 29 | 30 | If you only need to solve a single problem and not a series of related problems, 31 | then you can call the :code:`scs` function documented here, which simply calls 32 | the :code:`scs_init`, :code:`scs_solve`, :code:`scs_finish` sequence above. 33 | 34 | .. doxygenfunction:: scs 35 | 36 | 37 | .. 38 | Lower level 39 | ^^^^^^^^^^^ 40 | 41 | Under the hood the :code:`scs` function above simply calls the three functions 42 | below in series. It can be useful to call :code:`scs_solve` many times for the 43 | same call to :code:`scs_init`. If you want to do this, for example because you 44 | want to cache the matrix factorization for many solves, please `contact us 45 | `_, because currently that 46 | functionality is disabled. 47 | 48 | .. doxygenfunction:: scs_init 49 | 50 | .. doxygenfunction:: scs_solve 51 | 52 | .. doxygenfunction:: scs_finish 53 | 54 | 55 | Primitive types 56 | --------------- 57 | 58 | These are defined in header file :code:`scs_types.h`. 59 | 60 | * :code:`scs_int`: is :code:`long` if the :ref:`compiler flag ` :code:`DLONG` is set, otherwise it is :code:`int` 61 | * :code:`scs_float`: is :code:`float` if the :ref:`compiler flag ` :code:`SFLOAT` is set, otherwise it is :code:`double` 62 | 63 | 64 | Input Types 65 | ----------- 66 | 67 | The relevant input structs required by API are as follows. 68 | 69 | .. _ScsData: 70 | 71 | Data 72 | ^^^^ 73 | 74 | .. doxygenstruct:: ScsData 75 | :members: 76 | 77 | .. _ScsMatrix: 78 | 79 | Data Matrices 80 | ^^^^^^^^^^^^^ 81 | 82 | The matrices must be in `Compressed Sparse Column (CSC) format `_ using zero-based indexing. 83 | See :ref:`matrices` for more details on what SCS expects. 84 | 85 | .. doxygenstruct:: ScsMatrix 86 | :members: 87 | 88 | .. _ScsCone: 89 | 90 | Cone 91 | ^^^^ 92 | 93 | See :ref:`cones` for more details. 94 | 95 | .. doxygenstruct:: ScsCone 96 | :members: 97 | 98 | .. _ScsSettings: 99 | 100 | Settings 101 | ^^^^^^^^ 102 | 103 | See :ref:`settings` for details on each of these. 104 | 105 | .. doxygenstruct:: ScsSettings 106 | :members: 107 | 108 | Output Types 109 | ------------ 110 | 111 | The relevant output structs returned by SCS are as follows. 112 | 113 | .. _ScsSolution: 114 | 115 | Solution 116 | ^^^^^^^^ 117 | 118 | This will contain the solution as found by SCS *or* the certificate of primal or 119 | dual infeasibility (see :ref:`termination`). If the user wants to warm-start the 120 | solver, then the Solution struct is also used as an input to specify the 121 | warm-start points (see :ref:`warm_start`). 122 | 123 | 124 | .. doxygenstruct:: ScsSolution 125 | :members: 126 | 127 | .. _ScsInfo: 128 | 129 | Info 130 | ^^^^^ 131 | 132 | See :ref:`info` for details on each of these. 133 | 134 | .. doxygenstruct:: ScsInfo 135 | :members: 136 | 137 | Workspace 138 | --------- 139 | 140 | The user should not need to interact with the :code:`ScsWork` struct, 141 | which contains the internal workspace allocated and maintained by SCS. 142 | 143 | -------------------------------------------------------------------------------- /docs/src/api/compile_flags.rst: -------------------------------------------------------------------------------- 1 | .. _compile_flags: 2 | 3 | Compile flags 4 | ------------- 5 | 6 | Typically the user will not need to interact with these flags, but we document them 7 | here for completeness. Note this list is not exhaustive, others are not exposed 8 | but defined in :code:`include/glbopts.h`. The list below are defined in 9 | :code:`scs.mk` and can be overridden via the command line when compiling by 10 | executing, e.g., :code:`make DLONG=1`, to set the :code:`DLONG` flag to True. 11 | 12 | 13 | .. list-table:: 14 | :widths: 25 25 25 25 15 | :header-rows: 1 16 | 17 | * - Name 18 | - Description 19 | - Permitted values 20 | - Default 21 | * - :code:`DLONG` 22 | - If True use 64 bit integers, else 32 bit 23 | - True/False 24 | - 0 25 | * - :code:`SFLOAT` 26 | - If True use 32 bit floats, else 64 bit (WARNING: currently broken) 27 | - True/False 28 | - 0 29 | * - :code:`CTRLC` 30 | - Listen to CTRL-C interruptions 31 | - True/False 32 | - 1 33 | * - :code:`NO_TIMER` 34 | - Disables code timing 35 | - True/False 36 | - 0 37 | * - :code:`NO_VALIDATE` 38 | - Disables data validation 39 | - True/False 40 | - 0 41 | * - :code:`NO_PRINTING` 42 | - Disables all printing in compiled binary 43 | - True/False 44 | - 0 45 | * - :code:`NO_READ_WRITE` 46 | - Disables the read/write code 47 | - True/False 48 | - 0 49 | * - :code:`COPYAMATRIX` 50 | - Make a copy of A in memory 51 | - True/False 52 | - 1 53 | * - :code:`GPU_TRANSPOSE_MAT` 54 | - If on GPU store A transpose in memory 55 | - True/False 56 | - 1 57 | * - :code:`VALIDATE` 58 | - Whether to perform problem validation or not 59 | - True/False 60 | - 1 61 | * - :code:`VERBOSITY` 62 | - Verbosity level (for debugging) 63 | - :math:`\mathbf{N}` 64 | - 0 65 | * - :code:`USE_LAPACK` 66 | - Whether to link in :ref:`BLAS/LAPACK ` 67 | - True/False 68 | - 1 69 | * - :code:`USE_OPENMP` 70 | - Use openmp to parallelize some computation 71 | - True/False 72 | - 0 73 | * - :code:`BLAS64` 74 | - The BLAS library is 64 bits 75 | - True/False 76 | - 0 77 | * - :code:`NOBLASSUFFIX` 78 | - The BLAS library has no function name suffix 79 | - True/False 80 | - 0 81 | * - :code:`BLASSUFFIX` 82 | - The BLAS library uses this suffix 83 | - String 84 | - '_' 85 | * - :code:`MATLAB_MEX_FILE` 86 | - If compiling for use in MATLAB 87 | - True/False 88 | - 0 89 | * - :code:`PYTHON` 90 | - If compiling for use in python 91 | - True/False 92 | - 0 93 | * - :code:`USING_R` 94 | - If compiling for use in R 95 | - True/False 96 | - 0 97 | -------------------------------------------------------------------------------- /docs/src/api/exit_flags.rst: -------------------------------------------------------------------------------- 1 | .. _exit_flags: 2 | 3 | Exit flags 4 | ----------- 5 | The integer values that SCS can return are documented below and are defined 6 | in the :code:`'include/scs.h` file. 7 | 8 | .. list-table:: 9 | :widths: 50 10 40 10 | :header-rows: 1 11 | 12 | * - Status 13 | - Value 14 | - SCS constant name 15 | * - Solved to desired tolerance 16 | - 1 17 | - :code:`SCS_SOLVED` 18 | * - Did not reach desired accuracy, returning best guess of solution 19 | - 2 20 | - :code:`SCS_SOLVED_INACCURATE` 21 | * - Unfinished (never returned, only used internally) 22 | - 0 23 | - :code:`SCS_UNFINISHED` 24 | * - Primal unbounded / Dual infeasible (to desired tolerance) 25 | - -1 26 | - :code:`SCS_UNBOUNDED` 27 | * - Primal infeasible / Dual unbounded (to desired tolerance) 28 | - -2 29 | - :code:`SCS_INFEASIBLE` 30 | * - Indeterminate (numerical errors when recovering solution) DEPRECATED 31 | - -3 32 | - :code:`SCS_INDETERMINATE` 33 | * - Failed (usually a data input error) 34 | - -4 35 | - :code:`SCS_FAILED` 36 | * - Interrupted (received SIGINT) 37 | - -5 38 | - :code:`SCS_SIGINT` 39 | * - Did not reach desired accuracy, returning best guess of certificate of primal unboundedness 40 | - -6 41 | - :code:`SCS_UNBOUNDED_INACCURATE` 42 | * - Did not reach desired accuracy, returning best guess of certificate of primal infeasibility 43 | - -7 44 | - :code:`SCS_INFEASIBLE_INACCURATE` 45 | 46 | -------------------------------------------------------------------------------- /docs/src/api/index.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API 4 | === 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :hidden: 9 | 10 | cones.rst 11 | matrices.rst 12 | settings.rst 13 | info.rst 14 | exit_flags.rst 15 | compile_flags.rst 16 | 17 | Loosely speaking, SCS takes data :math:`P, A, b, c, \mathcal{K}` and produces 18 | primal-dual :ref:`optimal ` points :math:`(x^\star, y^\star, 19 | s^\star)` or a certificate of primal or dual :ref:`infeasibility`. The 20 | supported cones are documented :ref:`here `. The input format for the 21 | data matrices is documented :ref:`here `. The behavior of SCS is 22 | controlled by the :ref:`settings `. As well as the :ref:`solution 23 | `, SCS also returns :ref:`information ` about the solve 24 | process and a status :ref:`exit flag `. 25 | 26 | .. _interfaces: 27 | 28 | Interfaces 29 | ---------- 30 | 31 | SCS is written in raw C code, with interfaces for several other languages. 32 | 33 | :ref:`C/C++ ` 34 | 35 | :ref:`Python ` 36 | 37 | :ref:`MATLAB ` 38 | 39 | :ref:`Julia ` 40 | 41 | :ref:`R ` 42 | 43 | :ref:`Ruby ` 44 | 45 | :ref:`JavaScript / WebAssembly ` 46 | 47 | .. toctree:: 48 | :maxdepth: 2 49 | :hidden: 50 | 51 | c.rst 52 | python.rst 53 | matlab.rst 54 | julia.rst 55 | r.rst 56 | ruby.rst 57 | javascript.rst 58 | -------------------------------------------------------------------------------- /docs/src/api/info.rst: -------------------------------------------------------------------------------- 1 | .. _info: 2 | 3 | Return information 4 | ------------------ 5 | When SCS terminates it will return an :ref:`ScsInfo ` struct containing 6 | the following fields. 7 | 8 | 9 | .. list-table:: 10 | :widths: 15 15 70 11 | :header-rows: 1 12 | 13 | * - Name 14 | - Type 15 | - Description 16 | * - :code:`iter` 17 | - :code:`scs_int` 18 | - Number of iterations taken 19 | * - :code:`status` 20 | - :code:`char *` 21 | - Status string (e.g., 'solved') 22 | * - :code:`lin_sys_solver` 23 | - :code:`char *` 24 | - Linear system solver used 25 | * - :code:`status_val` 26 | - :code:`scs_int` 27 | - Status integer :ref:`exit flag ` 28 | * - :code:`scale_updates` 29 | - :code:`scs_int` 30 | - Number of updates to the scale parameter (see :ref:`updating_scale`) 31 | * - :code:`pobj` 32 | - :code:`scs_float` 33 | - Primal objective 34 | * - :code:`dobj` 35 | - :code:`scs_float` 36 | - Dual objective 37 | * - :code:`res_pri` 38 | - :code:`scs_float` 39 | - Primal residual (see :ref:`termination conditions `) 40 | * - :code:`res_dual` 41 | - :code:`scs_float` 42 | - Dual residual (see :ref:`termination conditions `) 43 | * - :code:`gap` 44 | - :code:`scs_float` 45 | - Absolute duality gap (see :ref:`termination conditions `) 46 | * - :code:`res_infeas` 47 | - :code:`scs_float` 48 | - Primal infeasibility residual (see :ref:`termination conditions `) 49 | * - :code:`res_unbdd_a` 50 | - :code:`scs_float` 51 | - Dual infeasibility residual involving :math:`A` (see :ref:`termination conditions `) 52 | * - :code:`res_unbdd_p` 53 | - :code:`scs_float` 54 | - Dual infeasibility residual involving :math:`P` (see :ref:`termination conditions `) 55 | * - :code:`comp_slack` 56 | - :code:`scs_float` 57 | - Complementary slackness (:math:`s^\top y`), should be very close to zero 58 | * - :code:`setup_time` 59 | - :code:`scs_float` 60 | - Time taken for setup (milliseconds) 61 | * - :code:`solve_time` 62 | - :code:`scs_float` 63 | - Time taken for solve (milliseconds) 64 | * - :code:`scale` 65 | - :code:`scs_float` 66 | - Final scale parameter, useful for initializing next solve (see :ref:`updating_scale`) 67 | * - :code:`rejected_accel_steps` 68 | - :code:`scs_int` 69 | - Number of times an AA update was rejected by the safeguarding check (see :ref:`acceleration`) 70 | * - :code:`accepted_accel_steps` 71 | - :code:`scs_int` 72 | - Number of times an AA update was accepted by the safeguarding check (see :ref:`acceleration`) 73 | * - :code:`lin_sys_time` 74 | - :code:`scs_float` 75 | - Total time (milliseconds) spent in the :ref:`linear system solver ` 76 | * - :code:`cone_time` 77 | - :code:`scs_float` 78 | - Total time (milliseconds) spent in the :ref:`cone projection ` 79 | * - :code:`accel_time` 80 | - :code:`scs_float` 81 | - Total time (milliseconds) spent in the :ref:`aceleration routine ` 82 | 83 | -------------------------------------------------------------------------------- /docs/src/api/julia.rst: -------------------------------------------------------------------------------- 1 | .. _julia_interface: 2 | 3 | Julia 4 | ===== 5 | 6 | The recommended way to use `SCS.jl `_ is via 7 | `Convex.jl `_ or 8 | `JuMP `_. 9 | 10 | Read the `SCS.jl README `_ for more details. 11 | -------------------------------------------------------------------------------- /docs/src/api/matlab.rst: -------------------------------------------------------------------------------- 1 | .. _matlab_interface: 2 | 3 | MATLAB 4 | ====== 5 | 6 | After :ref:`installing ` you can call 7 | 8 | .. code:: matlab 9 | 10 | [x, y, s, info] = scs(data, cones, settings) 11 | 12 | where :code:`data` is a struct containing :code:`P, A, b, c`, :code:`P, A` must 13 | be sparse matrices, :code:`settings` is a struct containing solver 14 | :ref:`settings` (missing settings are set to the defaults), and :code:`cones` is 15 | a struct that contains the :ref:`cones` information. The :code:`cone` struct 16 | contains members corresponding to the cone type and values corresponding to either 17 | the cone length or the array that defines the cone (see the third column in 18 | :ref:`cones` for the keys and what the corresponding values represent). At 19 | termination :code:`x, y, s` contains the primal-dual :ref:`solution 20 | ` or the :ref:`certificate of infeasibility `, and 21 | info is a struct containing the solve :ref:`info`. 22 | 23 | Warm-starting 24 | ------------- 25 | 26 | Warm-starting SCS with a guess of the primal-dual solution can reduce the total 27 | solve time. This is useful, for example, when solving several similar problems 28 | sequentially. To do this add to the :code:`data` struct passed to :code:`scs` 29 | the additional fields :code:`x`, :code:`y`, and :code:`s` (or any subset 30 | thereof) where :code:`x` and :code:`s` correspond to the primal solution guesses 31 | and :code:`y` corresponds to the dual solution guess. 32 | -------------------------------------------------------------------------------- /docs/src/api/matrices.rst: -------------------------------------------------------------------------------- 1 | .. _matrices: 2 | 3 | Data matrices 4 | ============= 5 | 6 | * Both matrices :math:`A` and :math:`P` must be in `Compressed Sparse Column (CSC) format `_ using zero-based indexing. 7 | 8 | * The order of the rows of :math:`A` must be in the order that the cones appear in the :ref:`cones table `. 9 | 10 | * The rows of :math:`A` corresponding to semidefinite cones (as well as the rows of :math:`b`) must be handled carefully, as described in :ref:`sdcone`. 11 | 12 | * The matrix :math:`P` must be symmetric positive semidefinite and only the **upper triangular** part of :math:`P` should be passed in. 13 | 14 | * If :math:`P = 0` for your problem then you can set the :code:`P` entry to NULL in the :ref:`ScsData` struct. :math:`A` must always be non-NULL. 15 | 16 | See the :ref:`ScsMatrix struct ` for the concrete implementation in 17 | the C api. 18 | 19 | -------------------------------------------------------------------------------- /docs/src/api/python.rst: -------------------------------------------------------------------------------- 1 | .. _python_interface: 2 | 3 | Python 4 | ====== 5 | 6 | After :ref:`installing ` you can import SCS using 7 | 8 | .. code:: python 9 | 10 | import scs 11 | 12 | This module provides the :code:`SCS` class which is initialized using: 13 | 14 | .. code:: python 15 | 16 | solver = scs.SCS(data, 17 | cone, 18 | use_indirect=False, 19 | mkl=False, 20 | gpu=False, 21 | verbose=True, 22 | normalize=True, 23 | max_iters=int(1e5), 24 | scale=0.1, 25 | adaptive_scale=True, 26 | eps_abs=1e-4, 27 | eps_rel=1e-4, 28 | eps_infeas=1e-7, 29 | alpha=1.5, 30 | rho_x=1e-6, 31 | acceleration_lookback=10, 32 | acceleration_interval=10, 33 | time_limit_secs=0, 34 | write_data_filename=None, 35 | log_csv_filename=None) 36 | 37 | where :code:`data` is a dict containing :code:`P, A, b, c`, and :code:`cone` is 38 | a dict that contains the :ref:`cones` information. The :code:`cone` dict 39 | contains keys corresponding to the cone type and values corresponding to either 40 | the cone length or the array that defines the cone (see the third column in 41 | :ref:`cones` for the keys and what the corresponding values represent). The 42 | :code:`b`, and :code:`c` entries must be 1d numpy arrays and the :code:`P` and 43 | :code:`A` entries must be scipy sparse matrices in CSC format; if they are not 44 | of the proper format, SCS will attempt to convert them. The 45 | :code:`use_indirect` setting switches between the sparse direct 46 | :ref:`linear_solver` (the default) or the sparse indirect solver. If the MKL 47 | Pardiso direct solver for SCS is :ref:`installed ` then it can 48 | be used by setting :code:`mkl=True`. If the GPU indirect solver for SCS is 49 | :ref:`installed ` and a GPU is available then it can be used by 50 | setting :code:`gpu=True`. The remaining fields are explained in 51 | :ref:`settings`. 52 | 53 | Then to solve the problem call: 54 | 55 | .. code:: python 56 | 57 | sol = solver.solve(warm_start=True, x=None, y=None, s=None) 58 | 59 | where :code:`warm_start` indicates whether the solve will reuse the previous 60 | solution as a warm-start (if this is the first solve it initializes at zero). 61 | A good warm-start can reduce the overall number of iterations required to solve 62 | a problem. 1d Numpy arrays :code:`x,y,s` are (optional) warm-start overrides if 63 | you wish to set these manually rather than use solution to the last problem as 64 | the warm-start. 65 | 66 | At termination :code:`sol` is a dict with fields :code:`x, y, s, info` where 67 | :code:`x, y, s` contains the primal-dual :ref:`solution ` or the 68 | :ref:`certificate of infeasibility `, and :code:`info` is a dict 69 | containing the solve :ref:`info`. 70 | 71 | To re-use the workspace and solve a similar problem with new :code:`b` 72 | and / or :code:`c` data, we can update the solver using: 73 | 74 | .. code:: python 75 | 76 | solver.update(b=new_b, c=new_c) # update b and c vectors (can be None) 77 | solver.solve() # solve new problem with updated b and c 78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/src/api/r.rst: -------------------------------------------------------------------------------- 1 | .. _r_interface: 2 | 3 | R 4 | = 5 | 6 | R interface source code available `here `_. 7 | After :ref:`installing ` you can load SCS using 8 | 9 | .. code:: r 10 | 11 | library("scs") 12 | 13 | 14 | Usage 15 | ----- 16 | 17 | Use function `scs` to solve a given optimization problem. Additional information 18 | about the arguments can be found in the `R-Manual `_ 19 | or the :ref:`matrices ` of the homepage. 20 | 21 | .. code-block:: r 22 | 23 | scs(A, 24 | b, 25 | obj, 26 | P = NULL, 27 | cone, 28 | initial = NULL, 29 | control = scs_control()) 30 | 31 | 32 | The `scs_control` is used to define additional settings, additional information 33 | can be found in the R-Manual or the :ref:`settings ` section of the 34 | homepage. 35 | 36 | .. code-block:: r 37 | 38 | scs_control(max_iters = 100000L, 39 | eps_rel = 1e-04, 40 | eps_abs = 1e-04, 41 | eps_infeas = 1e-07, 42 | alpha = 1.5, 43 | rho_x = 1e-06, 44 | scale = 0.1, 45 | verbose = FALSE, 46 | normalize = TRUE, 47 | warm_start = FALSE, 48 | acceleration_lookback = 0L, 49 | acceleration_interval = 1L, 50 | adaptive_scale = TRUE, 51 | write_data_filename = NULL, 52 | log_csv_filename = NULL, 53 | time_limit_secs = 0) 54 | 55 | -------------------------------------------------------------------------------- /docs/src/api/ruby.rst: -------------------------------------------------------------------------------- 1 | .. _ruby_interface: 2 | 3 | Ruby 4 | ==== 5 | 6 | See documentation `here `_. 7 | 8 | -------------------------------------------------------------------------------- /docs/src/api/settings.rst: -------------------------------------------------------------------------------- 1 | .. _settings: 2 | 3 | Settings 4 | -------- 5 | 6 | These settings control how SCS behaves during a solve. 7 | They are set in the :ref:`ScsSettings ` struct. 8 | 9 | .. list-table:: 10 | :widths: 20 20 20 20 20 11 | :header-rows: 1 12 | 13 | * - Name 14 | - Type 15 | - Description 16 | - Permitted values 17 | - Default 18 | * - :code:`normalize` 19 | - :code:`scs_int` 20 | - Whether to perform heuristic data rescaling. See :ref:`equilibration`. 21 | - True/False 22 | - 1 23 | * - :code:`scale` 24 | - :code:`scs_float` 25 | - Initial dual scale factor, updated if :code:`adaptive_scale` is True. See :ref:`scaling`. 26 | - :math:`(0, \infty)` 27 | - 0.1 28 | * - :code:`adaptive_scale` 29 | - :code:`scs_int` 30 | - Whether to heuristically adapt dual :code:`scale` through the solve. See :ref:`scaling`. 31 | - True/False 32 | - 1 33 | * - :code:`rho_x` 34 | - :code:`scs_float` 35 | - Primal scale factor. See :ref:`scaling`. 36 | - :math:`(0, \infty)` 37 | - 1e-6 38 | * - :code:`max_iters` 39 | - :code:`scs_int` 40 | - Maximum number of iterations to run. 41 | - :math:`\mathbf{N}` 42 | - 1e5 43 | * - :code:`eps_abs` 44 | - :code:`scs_float` 45 | - Absolute feasibility tolerance, see :ref:`termination`. 46 | - :math:`(0, \infty)` 47 | - 1e-4 48 | * - :code:`eps_rel` 49 | - :code:`scs_float` 50 | - Relative feasibility tolerance, see :ref:`termination`. 51 | - :math:`(0, \infty)` 52 | - 1e-4 53 | * - :code:`eps_infeas` 54 | - :code:`scs_float` 55 | - Infeasibility tolerance (primal and dual), see :ref:`infeasibility`. 56 | - :math:`(0, \infty)` 57 | - 1e-7 58 | * - :code:`alpha` 59 | - :code:`scs_float` 60 | - Douglas-Rachford relaxation parameter. See :ref:`relaxation`. 61 | - :math:`(0, 2)` 62 | - 1.5 63 | * - :code:`time_limit_secs` 64 | - :code:`scs_float` 65 | - Time limit for solve run in seconds (can be fractional). :code:`0` is interpreted as no limit. 66 | - :math:`[0, \infty)` 67 | - 0 68 | * - :code:`verbose` 69 | - :code:`scs_int` 70 | - Whether to print solver output to stdout. 71 | - True/False 72 | - 1 73 | * - :code:`warm_start` 74 | - :code:`scs_int` 75 | - Set to True if you initialize the solver with a guess of the solution. See :ref:`warm_start`. This is overridden by the argument passed to :code:`scs_solve`. 76 | - True/False 77 | - 0 78 | * - :code:`acceleration_lookback` 79 | - :code:`scs_int` 80 | - How much memory to use for Anderson acceleration. More memory requires more time to compute but can give more reliable steps. :code:`0` disables it. See :ref:`acceleration`. 81 | - :math:`\mathbf{N}` 82 | - 10 83 | * - :code:`acceleration_interval` 84 | - :code:`scs_int` 85 | - Run Anderson acceleration every :code:`acceleration_interval` iterations. See :ref:`acceleration`. 86 | - :math:`\mathbf{N}` 87 | - 10 88 | * - :code:`write_data_filename` 89 | - :code:`char *` 90 | - If this is set the problem data is dumped to this filename. 91 | - Any filename 92 | - NULL 93 | * - :code:`log_csv_filename` 94 | - :code:`char *` 95 | - If this is set SCS will write csv logs of various quantities through the solver (makes the solver much slower). 96 | - Any filename 97 | - NULL 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/src/blas_lapack/index.rst: -------------------------------------------------------------------------------- 1 | .. _blas_lapack: 2 | 3 | BLAS and LAPACK 4 | =============== 5 | BLAS and LAPACK are dense numerical linear algebra packages. SCS uses these 6 | libraries in two places: 7 | 8 | * To compute the eigen-decomposition for the semidefinite :ref:`cone ` projection 9 | * To solve the linear system in :ref:`Anderson acceleration ` 10 | 11 | Therefore compiling with BLAS / LAPACK **is optional**. If you are 12 | not interested in solving SDPs or using acceleration then there is no need to 13 | use these libraries. To compile without these libraries you can set the 14 | :ref:`compiler flag ` :code:`USE_LAPACK` to :code:`0`, e.g., if 15 | :ref:`installing ` using :code:`make`: 16 | 17 | .. code:: bash 18 | 19 | make USE_LAPACK=0 20 | 21 | If you do want to solve SDPs or use Anderson acceleration, then you will need 22 | to install BLAS and LAPACK libraries (these are pre-installed in most machines). 23 | If calling SCS from another language (Python, MATLAB etc.) then these libraries 24 | should be pre-installed and SCS will try to link against them. Otherwise 25 | you may need to install a copy yourself. A good library to start with is 26 | `OpenBLAS `_, which contains both BLAS and LAPACK. 27 | 28 | There are many different BLAS and LAPACK libraries that conform to the same API. 29 | Finding one that is optimized for your machine can make a big difference to 30 | the speed of the operations in practice. If the speed of the SDP projection 31 | or the acceleration step is a bottleneck you can experiment with faster 32 | libraries like `MKL `_ 33 | or `ATLAS `_. 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/src/citing/index.rst: -------------------------------------------------------------------------------- 1 | .. _citing : 2 | 3 | Citing SCS 4 | =========== 5 | 6 | If you wish to cite SCS, please use any of the following: 7 | 8 | .. glossary:: 9 | 10 | Original paper 11 | Main algorithm description, derivation, and initial numerical results `paper `__. 12 | 13 | .. code:: latex 14 | 15 | @article{ocpb:16, 16 | author = {Brendan O'Donoghue and Eric Chu and Neal Parikh and Stephen Boyd}, 17 | title = {Conic Optimization via Operator Splitting and Homogeneous Self-Dual Embedding}, 18 | journal = {Journal of Optimization Theory and Applications}, 19 | month = {June}, 20 | year = {2016}, 21 | volume = {169}, 22 | number = {3}, 23 | pages = {1042-1068}, 24 | url = {http://stanford.edu/~boyd/papers/scs.html}, 25 | } 26 | 27 | Latest extension 28 | The paper that derived the extension to quadratics and describes the latest version of the algorithm is available `here `__. 29 | 30 | .. code:: latex 31 | 32 | @article{odonoghue:21, 33 | author = {Brendan O'Donoghue}, 34 | title = {Operator Splitting for a Homogeneous Embedding of the Linear Complementarity Problem}, 35 | journal = {{SIAM} Journal on Optimization}, 36 | month = {August}, 37 | year = {2021}, 38 | volume = {31}, 39 | issue = {3}, 40 | pages = {1999-2023}, 41 | } 42 | 43 | Software 44 | If you need to cite a particular version of the SCS software (e.g., for replication purposes) the latest version can be cited as: 45 | 46 | 47 | .. code:: latex 48 | 49 | @misc{scs, 50 | author = {Brendan O'Donoghue and Eric Chu and Neal Parikh and Stephen Boyd}, 51 | title = {{SCS}: Splitting Conic Solver, version 3.2.7}, 52 | howpublished = {\url{https://github.com/cvxgrp/scs}}, 53 | month = nov, 54 | year = 2023 55 | } 56 | 57 | Anderson Acceleration 58 | The acceleration scheme we use is described in the `paper `__. 59 | 60 | .. code:: latex 61 | 62 | @article{aa2020, 63 | title={Globally Convergent {type--I} {A}nderson Acceleration for Non-Smooth Fixed-Point Iterations}, 64 | author={Junzi Zhang and Brendan O'Donoghue and Stephen Boyd}, 65 | journal={{SIAM} Journal on Optimization}, 66 | volume={30}, 67 | number={4}, 68 | pages={3170--3197}, 69 | year={2020} 70 | } 71 | 72 | -------------------------------------------------------------------------------- /docs/src/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 os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | import subprocess 18 | import sphinx_rtd_theme 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = "SCS" 23 | copyright = "2021, Brendan O'Donoghue" 24 | author = "Brendan O'Donoghue" 25 | 26 | # The full version, including alpha/beta/rc tags 27 | __version__ = "3.2.7" 28 | 29 | release = __version__ 30 | version = __version__ 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be 35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 36 | # ones. 37 | extensions = ["sphinx.ext.mathjax", "breathe", "sphinx_rtd_theme"] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ["_templates"] 41 | 42 | # List of patterns, relative to source directory, that match files and 43 | # directories to ignore when looking for source files. 44 | # This pattern also affects html_static_path and html_extra_path. 45 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 46 | 47 | # sphinx pygments style uses ugly green boxes for code blocks 48 | # pygments_style = 'sphinx' 49 | pygments_style = "default" 50 | 51 | # html_sidebars = { 52 | # '**': [ 53 | # 'about.html', 'navigation.html', 'searchbox.html', 54 | # ] 55 | # } 56 | 57 | # -- Options for HTML output ------------------------------------------------- 58 | 59 | # The theme to use for HTML and HTML Help pages. See the documentation for 60 | # a list of builtin themes. 61 | 62 | # html_theme = 'alabaster' 63 | html_theme = "sphinx_rtd_theme" 64 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 65 | 66 | 67 | def setup(app): 68 | app.add_css_file("css/scs_theme.css") 69 | 70 | 71 | html_logo = "_static/scs_logo_transparent.png" 72 | html_favicon = "_static/favicon.ico" 73 | html_theme_options = { 74 | "logo_only": True, 75 | "display_version": True, 76 | #'github_banner': True, 77 | #'github_user': 'cvxgrp', 78 | #'github_repo': 'scs', 79 | #'logo': 'scs_logo_transparent.png', 80 | #'logo_name': False, 81 | #'github_button': False, 82 | #'github_type': 'star', 83 | "analytics_id": "G-9CY7R8S5N2", 84 | } 85 | 86 | rst_epilog = ".. |version| replace:: %s" % __version__ 87 | 88 | # Breathe docs 89 | subprocess.call("doxygen Doxyfile", shell=True) 90 | 91 | breathe_projects = {"scs": "doxygen_out/xml/"} 92 | breathe_default_project = "scs" 93 | 94 | # Add any paths that contain custom static files (such as style sheets) here, 95 | # relative to this directory. They are copied after the builtin static files, 96 | # so a file named "default.css" will overwrite the builtin "default.css". 97 | html_static_path = ["_static"] 98 | -------------------------------------------------------------------------------- /docs/src/contributing/index.rst: -------------------------------------------------------------------------------- 1 | .. _contributing: 2 | 3 | Contributing 4 | =============== 5 | There are many ways you can contribute to SCS, and we welcome all help! 6 | Here are some ideas (of varying difficulty): 7 | 8 | * Answer an open `GitHub issue `_ 9 | * Improve the documentation (the website or in the code) 10 | * Add more :ref:`examples` to the docs 11 | * Improve the test coverage 12 | * Improve the :ref:`Anderson acceleration ` stability 13 | * Improve the :ref:`data equilibration ` 14 | * Improve the :ref:`heuristic re-scaling ` 15 | * Determine how to select the :code:`TAU_FACTOR` :ref:`term ` 16 | * Implement a :ref:`GPU direct linear system solver ` 17 | * Add other new :ref:`linear system solvers ` 18 | * Refactor the :ref:`linear solvers ` to only compile a single binary with all solvers 19 | * Add :ref:`interfaces for other languages ` (or improve the current interfaces) 20 | 21 | If you are interested in helping out, please start by opening a `GitHub issue 22 | `_ so we can track progress and ensure 23 | that our priorities align. 24 | -------------------------------------------------------------------------------- /docs/src/examples/.gitignore: -------------------------------------------------------------------------------- 1 | qp.out 2 | -------------------------------------------------------------------------------- /docs/src/examples/c.rst: -------------------------------------------------------------------------------- 1 | .. _c_example: 2 | 3 | C/C++ 4 | ===== 5 | 6 | .. include:: qp.prob 7 | 8 | C code to solve this is below. 9 | 10 | .. literalinclude:: qp.c 11 | :language: c 12 | 13 | After following the CMake :ref:`install instructions `, we can 14 | compile the code (assuming the library was installed in :code:`/usr/local/` and 15 | the :code:`gcc` compiler is available) using: 16 | 17 | .. code:: 18 | 19 | gcc -I/usr/local/include/scs -L/usr/local/lib/ qp.c -o qp.out -lscsdir 20 | 21 | .. ./qp.out > qp.c.out 22 | 23 | Then running the binary yields output: 24 | 25 | .. literalinclude:: qp.c.out 26 | :language: none 27 | 28 | -------------------------------------------------------------------------------- /docs/src/examples/index.rst: -------------------------------------------------------------------------------- 1 | .. _examples: 2 | 3 | Examples 4 | =============== 5 | 6 | Here we present a few simple examples of calling SCS from different languages. 7 | 8 | :ref:`C/C++ ` 9 | 10 | :ref:`Python ` 11 | 12 | :ref:`MATLAB ` 13 | 14 | :ref:`Julia ` 15 | 16 | :ref:`R ` 17 | 18 | :ref:`Ruby ` 19 | 20 | :ref:`JavaScript / WebAssembly ` 21 | 22 | .. toctree:: 23 | :maxdepth: 2 24 | :hidden: 25 | 26 | c.rst 27 | python.rst 28 | matlab.rst 29 | julia.rst 30 | r.rst 31 | ruby.rst 32 | javascript.rst 33 | 34 | -------------------------------------------------------------------------------- /docs/src/examples/julia.rst: -------------------------------------------------------------------------------- 1 | .. _julia_example: 2 | 3 | Julia 4 | ====== 5 | 6 | The easiest way to use SCS in Julia is via JuMP: 7 | 8 | .. code:: julia 9 | 10 | using JuMP, SCS 11 | items = [:Gold, :Silver, :Bronze] 12 | values = Dict(:Gold => 5.0, :Silver => 3.0, :Bronze => 1.0) 13 | weight = Dict(:Gold => 2.0, :Silver => 1.5, :Bronze => 0.3) 14 | model = Model(SCS.Optimizer) 15 | @variable(model, 0 <= take[items] <= 1) # Define a variable for each item 16 | @objective(model, Max, sum(values[item] * take[item] for item in items)) 17 | @constraint(model, sum(weight[item] * take[item] for item in items) <= 3) 18 | optimize!(model) 19 | println(value.(take)) 20 | # 1-dimensional DenseAxisArray{Float64,1,...} with index sets: 21 | # Dimension 1, Symbol[:Gold, :Silver, :Bronze] 22 | # And data, a 3-element Vector{Float64}: 23 | # 1.0000002002226671 24 | # 0.4666659513182934 25 | # 1.0000007732744878 26 | 27 | Read the `JuMP documentation `_ and the 28 | `SCS.jl README `_ for more details. 29 | -------------------------------------------------------------------------------- /docs/src/examples/matlab.rst: -------------------------------------------------------------------------------- 1 | .. _matlab_example: 2 | 3 | MATLAB 4 | ====== 5 | 6 | .. include:: qp.prob 7 | 8 | Matlab code to solve this is below. 9 | 10 | .. literalinclude:: qp.m 11 | :language: matlab 12 | 13 | After following the matlab :ref:`install instructions `, we can 14 | run the code yielding output: 15 | 16 | .. /Applications/MATLAB_R2021a.app/bin/matlab -nodesktop -nojvm -nosplash \ 17 | -nodisplay -r "run ~/git/scs/docs/src/examples/qp.m;exit" > qp.m.out 18 | 19 | .. literalinclude:: qp.m.out 20 | :language: none 21 | 22 | -------------------------------------------------------------------------------- /docs/src/examples/python.rst: -------------------------------------------------------------------------------- 1 | .. _python_example: 2 | 3 | Python 4 | ====== 5 | 6 | :ref:`Basic QP ` 7 | 8 | :ref:`Lasso ` 9 | 10 | :ref:`Low-rank matrix completion ` 11 | 12 | :ref:`Maximum entropy ` 13 | 14 | :ref:`Model predictive control ` 15 | 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :hidden: 20 | 21 | python/basic_qp.rst 22 | python/lasso.rst 23 | python/mat_completion.rst 24 | python/entropy.rst 25 | python/mpc.rst 26 | -------------------------------------------------------------------------------- /docs/src/examples/python/basic_qp.rst: -------------------------------------------------------------------------------- 1 | .. _py_basic_qp: 2 | 3 | Basic QP 4 | ======== 5 | 6 | .. include:: ../qp.prob 7 | 8 | Python code to solve this is below. 9 | 10 | .. literalinclude:: qp.py 11 | :language: python 12 | 13 | After following the python :ref:`install instructions `, we can 14 | run the code yielding output: 15 | 16 | .. python qp.py > qp.py.out 17 | 18 | .. literalinclude:: qp.py.out 19 | :language: none 20 | -------------------------------------------------------------------------------- /docs/src/examples/python/entropy.py: -------------------------------------------------------------------------------- 1 | import scs 2 | import numpy as np 3 | from scipy import sparse 4 | 5 | # Generate problem data 6 | np.random.seed(1) 7 | 8 | # Matrix size parameters 9 | n = 50 # Number of variables 10 | p = 20 # Number of constraints 11 | 12 | # Generate random problem data 13 | tmp = np.random.rand(n) 14 | tmp /= np.sum(tmp) 15 | Ad = np.random.randn(p, n) 16 | bd = 0.5 * Ad.dot(tmp) + 0.01 * np.random.rand(p) 17 | 18 | # Build the A, b rows corresponding to the exponential cone 19 | A_exp = sparse.lil_matrix((3 * n, 2 * n)) 20 | b_exp = np.zeros(3 * n) 21 | for i in range(n): 22 | A_exp[i * 3, i] = -1 # t 23 | A_exp[i * 3 + 1, i + n] = -1 # x 24 | b_exp[i * 3 + 2] = 1 25 | 26 | A = sparse.vstack( 27 | [ 28 | # zero cone 29 | sparse.hstack([sparse.csc_matrix((1, n)), np.ones((1, n))]), 30 | # positive cone 31 | sparse.hstack([sparse.csc_matrix((p, n)), -Ad]), 32 | # exponential cones 33 | A_exp, 34 | ], 35 | format="csc", 36 | ) 37 | b = np.hstack([1, -bd, b_exp]) 38 | c = np.hstack([-np.ones(n), np.zeros(n)]) 39 | 40 | # SCS data 41 | data = dict(A=A, b=b, c=c) 42 | # ep is exponential cone (primal), with n triples 43 | cone = dict(z=1, l=p, ep=n) 44 | 45 | # Setup workspace 46 | solver = scs.SCS( 47 | data, 48 | cone, 49 | ) 50 | sol = solver.solve() 51 | x_scs = sol["x"][-n:] 52 | 53 | # Verify solution with CVXPY 54 | try: 55 | import cvxpy as cp 56 | except ModuleNotFoundError: 57 | print("This example requires CVXPY installed to run.") 58 | raise 59 | 60 | x = cp.Variable(shape=n) 61 | obj = cp.Maximize(cp.sum(cp.entr(x))) 62 | constraints = [cp.sum(x) == 1, Ad @ x >= bd] 63 | prob = cp.Problem(obj, constraints) 64 | prob.solve(solver=cp.ECOS) 65 | x_cvxpy = x.value 66 | 67 | print(f"CVXPY optimal value is:", prob.value) 68 | print(f"Solution norm difference: {np.linalg.norm(x_scs - x_cvxpy, np.inf)}") 69 | -------------------------------------------------------------------------------- /docs/src/examples/python/entropy.py.out: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ 2 | SCS v3.1.1 - Splitting Conic Solver 3 | (c) Brendan O'Donoghue, Stanford University, 2012 4 | ------------------------------------------------------------------ 5 | problem: variables n: 100, constraints m: 171 6 | cones: z: primal zero / dual free vars: 1 7 | l: linear vars: 20 8 | e: exp vars: 150, dual exp vars: 0 9 | settings: eps_abs: 1.0e-04, eps_rel: 1.0e-04, eps_infeas: 1.0e-07 10 | alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1 11 | max_iters: 100000, normalize: 1, rho_x: 1.00e-06 12 | acceleration_lookback: 10, acceleration_interval: 10 13 | lin-sys: sparse-direct 14 | nnz(A): 1150, nnz(P): 0 15 | ------------------------------------------------------------------ 16 | iter | pri res | dua res | gap | obj | scale | time (s) 17 | ------------------------------------------------------------------ 18 | 0| 1.11e+01 6.95e-01 5.59e+02 -3.06e+02 1.00e-01 9.02e-04 19 | 225| 8.91e-06 1.30e-05 3.24e-05 -3.89e+00 5.45e+00 1.43e-01 20 | ------------------------------------------------------------------ 21 | status: solved 22 | timings: total: 1.44e-01s = setup: 5.53e-04s + solve: 1.43e-01s 23 | lin-sys: 1.06e-03s, cones: 1.42e-01s, accel: 4.26e-05s 24 | ------------------------------------------------------------------ 25 | objective = -3.888803 26 | ------------------------------------------------------------------ 27 | CVXPY optimal value is: 3.888784623785257 28 | Solution norm difference: 2.241074541050464e-06 29 | -------------------------------------------------------------------------------- /docs/src/examples/python/entropy.rst: -------------------------------------------------------------------------------- 1 | .. _py_entropy: 2 | 3 | Maximum Entropy 4 | =============== 5 | 6 | This example demonstrates an instance of using the exponential :ref:`cone 7 | `. In this problem we want find the maximum entropy point inside a 8 | convex polytope, ie, to solve 9 | 10 | .. math:: 11 | 12 | \begin{array}{ll} 13 | \mbox{maximize} & -\sum_i^n x_i \log x_i \\ 14 | \mbox{subhect to} & {\bf 1}^T x = 1 \\ 15 | & Ax - b \geq 0 16 | \end{array} 17 | 18 | 19 | over variable :math:`x \in \mathbf{R}^{n}`, where :math:`A \in 20 | \mathbf{R}^{m \times n}` and :math:`b \in \mathbf{R}^m` are data. The problem 21 | has the following equivalent form, 22 | 23 | .. math:: 24 | 25 | \begin{array}{ll} 26 | \mbox{minimize} & -{\bf 1}^T t \\ 27 | \mbox{subject to} & {\bf 1}^T x = 1 \\ 28 | & Ax - b \geq 0 \\ 29 | & \begin{bmatrix} t_i \\ x_i \\ 1 \end{bmatrix} \in \mathcal{K}_\mathrm{exp}, \quad i=1,\ldots,n, 30 | \end{array} 31 | 32 | over variables :math:`x \in \mathbf{R}^{n}`, :math:`t \in \mathbf{R}^{n}` and 33 | where :math:`\mathcal{K}_\mathrm{exp} \subset \mathbf{R}^3` denotes the 34 | exponential cone. 35 | 36 | Python code to solve this is below. 37 | 38 | .. literalinclude:: entropy.py 39 | :language: python 40 | 41 | After following the python :ref:`install instructions `, we can 42 | run the code yielding output: 43 | 44 | .. python entropy.py > entropy.py.out 45 | 46 | .. literalinclude:: entropy.py.out 47 | :language: none 48 | -------------------------------------------------------------------------------- /docs/src/examples/python/lasso.py: -------------------------------------------------------------------------------- 1 | import scs 2 | import numpy as np 3 | import scipy as sp 4 | from scipy import sparse 5 | 6 | # Generate problem data 7 | sp.random.seed(1) 8 | np.random.seed(1) 9 | 10 | n = 200 # Variables 11 | m = 100 # Measurements 12 | Ad = sparse.random(m, n, density=0.5) # Measurement matrix 13 | x_true = sparse.random(n, 1, density=0.1) # True sparse vector 14 | x_true = np.array(x_true.todense()).squeeze() 15 | 16 | measurements = Ad @ x_true + 0.1 * np.random.randn(m) 17 | measurements = np.array(measurements).squeeze() 18 | 19 | # The smallest value of lambda with solution all-zeros 20 | lambda_max = np.linalg.norm(Ad.T @ measurements, np.inf) 21 | 22 | # Auxiliary data 23 | In = sparse.eye(n) 24 | Im = sparse.eye(m) 25 | On = sparse.csc_matrix((n, n)) 26 | Onm = sparse.csc_matrix((n, m)) 27 | 28 | # SCS data 29 | P = sparse.block_diag([On, sparse.eye(m), On], format="csc") 30 | q = np.zeros(2 * n + m) 31 | A = sparse.vstack( 32 | [ 33 | # zero cone 34 | sparse.hstack([Ad, -Im, Onm.T]), 35 | # positive cones 36 | sparse.hstack([In, Onm, -In]), 37 | sparse.hstack([-In, Onm, -In]), 38 | ], 39 | format="csc", 40 | ) 41 | b = np.hstack([measurements, np.zeros(n), np.zeros(n)]) 42 | c = np.zeros(2 * n + m) 43 | 44 | data = dict(P=P, A=A, b=b, c=c) 45 | cone = dict(z=m, l=2 * n) 46 | 47 | print(f"Solving for lambda = 0") 48 | # Setup workspace 49 | solver = scs.SCS( 50 | data, 51 | cone, 52 | eps_abs=1e-6, 53 | eps_rel=1e-6, 54 | ) 55 | sol = solver.solve() # lambda = 0 56 | x = sol["x"][:n] 57 | print(f"Error : {np.linalg.norm(x_true - x) / np.linalg.norm(x_true)}") 58 | 59 | # Solve for different values of lambda 60 | lambdas = np.logspace(-2, np.log10(lambda_max), 11) 61 | for lam in lambdas: 62 | print(f"Solving for lambda = {lam}") 63 | # Re-use workspace, just update the `c` vector 64 | c_new = np.hstack([np.zeros(n + m), lam * np.ones(n)]) 65 | solver.update(c=c_new) 66 | # Solve updated problem 67 | sol = solver.solve() # will warm-start automatically 68 | x = sol["x"][:n] 69 | # What is the norm error? 70 | print(f"Error : {np.linalg.norm(x_true - x) / np.linalg.norm(x_true)}") 71 | -------------------------------------------------------------------------------- /docs/src/examples/python/lasso.rst: -------------------------------------------------------------------------------- 1 | .. _py_lasso: 2 | 3 | Lasso 4 | ===== 5 | This example demonstrates quadratic objectives, as well as reusing a 6 | :ref:`cached workspace and using warm-starting `. 7 | 8 | In the lasso the goal is to find a sparse vector that fits some measurements. 9 | The :math:`\ell_1` norm is used as a convex surrogate for sparsity, and 10 | a regularization parameter :math:`\lambda \geq 0` trades off sparsity and 11 | quality of fit. Concretely the lasso solves 12 | 13 | .. math:: 14 | 15 | \begin{array}{ll} 16 | \mbox{minimize} & \frac{1}{2} \| Ax - b \|_2^2 + \lambda \| x \|_1 17 | \end{array} 18 | 19 | 20 | over variable :math:`x \in \mathbf{R}^{n}`, with data :math:`A \in 21 | \mathbf{R}^{m \times n}` and :math:`b \in \mathbf{R}^n`. The problem has the 22 | following equivalent form, 23 | 24 | .. math:: 25 | 26 | \begin{array}{ll} 27 | \mbox{minimize} & \frac{1}{2} y^T y + \lambda {\bf 1}^T t \\ 28 | \mbox{subject to} & y = Ax - b \\ 29 | & -t \le x \le t 30 | \end{array} 31 | 32 | over variables :math:`x \in \mathbf{R}^{n}`, :math:`t \in \mathbf{R}^{n}`, 33 | :math:`y \in \mathbf{R}^{m}`. From this formulation it is straightforward to 34 | convert it into the standard form accepted by SCS. The regularization parameter 35 | :math:`\lambda \geq 0` trades off the sparsity of the solution and the quality 36 | of the fit, and so we solve the problem for many choices of :math:`\lambda`. 37 | Since :math:`\lambda` enters only in the linear part of the objective function, 38 | we can reuse the matrix factorization and use warm starting to reduce the 39 | computation time. 40 | 41 | Python code to solve this is below. 42 | 43 | .. literalinclude:: lasso.py 44 | :language: python 45 | 46 | After following the python :ref:`install instructions `, we can 47 | run the code yielding output: 48 | 49 | .. python lasso.py > lasso.py.out 50 | 51 | .. literalinclude:: lasso.py.out 52 | :language: none 53 | -------------------------------------------------------------------------------- /docs/src/examples/python/mat_completion.py: -------------------------------------------------------------------------------- 1 | import scs 2 | import numpy as np 3 | import scipy as sp 4 | from scipy import sparse 5 | 6 | np.random.seed(1) 7 | 8 | # The vec function as documented in api/cones 9 | def vec(S): 10 | n = S.shape[0] 11 | S = np.copy(S) 12 | S *= np.sqrt(2) 13 | S[range(n), range(n)] /= np.sqrt(2) 14 | return S[np.triu_indices(n)] 15 | 16 | 17 | # The mat function as documented in api/cones 18 | def mat(s): 19 | n = int((np.sqrt(8 * len(s) + 1) - 1) / 2) 20 | S = np.zeros((n, n)) 21 | S[np.triu_indices(n)] = s / np.sqrt(2) 22 | S = S + S.T 23 | S[range(n), range(n)] /= np.sqrt(2) 24 | return S 25 | 26 | 27 | dim = 15 # dim x dim matrix 28 | vlen = int(dim * (dim + 1) / 2) # length of vector x = vec(X) 29 | 30 | # Generate true matrix 31 | rank = dim // 5 # low rank 32 | X = np.random.randn(dim, rank) 33 | X = X @ X.T 34 | 35 | ############################################################################# 36 | 37 | # Let's first do some basic sanity checks to ensure that mat, vec are working: 38 | 39 | # mat(vec( . )) should be identity 40 | print(f"Should be ~ 0: {np.linalg.norm(X - mat(vec(X)))}") 41 | 42 | # Trace( . ) should be vec(I)' vec( . ) 43 | print(f"Should be ~ 0: {np.trace(X) - vec(np.eye(dim)) @ vec(X)}") 44 | 45 | ############################################################################# 46 | 47 | num_measurements = vlen // 2 # how many measurements are revealed 48 | 49 | # Generate random measurement indices 50 | measurement_idxs = np.random.choice( 51 | np.arange(vlen), size=num_measurements, replace=False 52 | ) 53 | 54 | # Create A matrix 55 | Ad = np.zeros((num_measurements, vlen)) 56 | for i in range(num_measurements): 57 | Ad[i, measurement_idxs[i]] = 1.0 58 | 59 | # Noisy measurements of X 60 | measurements = Ad @ vec(X) + 0.01 * np.random.randn(num_measurements) # + noise 61 | 62 | # Auxiliary data 63 | In = sparse.eye(vlen) 64 | Im = sparse.eye(num_measurements) 65 | On = sparse.csc_matrix((vlen, vlen)) 66 | Onm = sparse.csc_matrix((vlen, num_measurements)) 67 | 68 | # SCS data 69 | P = sparse.block_diag([On, sparse.eye(num_measurements)], format="csc") 70 | A = sparse.vstack( 71 | [ 72 | # zero cone 73 | sparse.hstack([Ad, -Im]), 74 | # positive semidefinite cone 75 | sparse.hstack([-In, Onm]), 76 | ], 77 | format="csc", 78 | ) 79 | b = np.hstack([measurements, np.zeros(vlen)]) 80 | c = np.hstack([np.zeros(vlen + num_measurements)]) 81 | 82 | data = dict(P=P, A=A, b=b, c=c) 83 | cone = dict(z=num_measurements, s=dim) 84 | # Setup workspace 85 | solver = scs.SCS(data, cone, eps_abs=1e-6, eps_rel=1e-6) 86 | print(f"Solving for lambda = 0") 87 | sol = solver.solve() # lambda = 0 88 | X_hat = mat(sol["x"][:vlen]) 89 | print(f"Error: {np.linalg.norm(X_hat - X) / np.linalg.norm(X)}") 90 | 91 | # Solve for different values of lambda 92 | lambdas = np.logspace(-6, 1, 11) 93 | for lam in lambdas: 94 | print(f"Solving for lambda = {lam}") 95 | # Re-use workspace, just update the `c` vector 96 | c_new = np.hstack([lam * vec(np.eye(dim)), np.zeros(num_measurements)]) 97 | solver.update(c=c_new) 98 | # Solve updated problem 99 | sol = solver.solve() # will warm-start automatically 100 | X_hat = mat(sol["x"][:vlen]) 101 | # What is the norm error? 102 | print(f"Error : {np.linalg.norm(X_hat - X) / np.linalg.norm(X)}") 103 | -------------------------------------------------------------------------------- /docs/src/examples/python/mat_completion.rst: -------------------------------------------------------------------------------- 1 | .. _py_mat_completion: 2 | 3 | Low-Rank Matrix Completion 4 | ========================== 5 | 6 | This example demonstrates how to use the :ref:`positive semidefinite cone 7 | `, as well as reusing a :ref:`cached workspace and using warm-starting 8 | `. 9 | 10 | Matrix completion is the problem of filling in missing data into a partially 11 | observed matrix where the measurements we are given have been corrupted by 12 | Gaussian noise. In low-rank matrix completion we have the additional prior 13 | knowledge that the matrix we are completing is low-rank. For simplicity we 14 | shall also assume that the matrix we are reconstructing is symmetric positive 15 | definite. A famous instance of this problem is the `Netflix prize 16 | `__. 17 | 18 | Concretely, we denote by :math:`\hat X \in \mathbf{R}^{n \times n}` the true 19 | matrix corrupted by noise, and denote by :math:`\mathcal{I}` the set of indices 20 | (row and column pairs) from which we receive noisy observations. We shall use 21 | the nuclear norm, denoted :math:`\| \cdot \|_*`, as a convex surrogate for rank, 22 | which we shall trade off against the observations using regularization parameter 23 | :math:`\lambda \geq 0`. The low-rank matrix completion problem is given by 24 | 25 | .. math:: 26 | 27 | \begin{array}{ll} 28 | \mbox{minimize} & \frac{1}{2} \sum_{i,j \in \mathcal{I_n}} (X_{ij} - \hat X_{ij})^2 + \lambda \|X \|_* \\ 29 | \mbox{subject to} & X \succeq 0 30 | \end{array} 31 | 32 | over variable :math:`X \in \mathbf{R}^{n \times n}` (we use :math:`\cdot \succeq 33 | 0` to indicate membership in the symmetric positive semidefinite cone). 34 | 35 | We can convert this into a more standard form. First, let :math:`x = 36 | \mathrm{vec}(X)` be the semidefinite vectorization of :math:`X` described in 37 | :ref:`cones ` (and concretely implemented in the code that follows). 38 | Further, let :math:`A` be the linear operator that extracts the elements of 39 | :math:`x` for which we have (noisy) observations, and let :math:`b = A 40 | \mathrm{vec}(\hat X)`. Since the nuclear norm of a positive semidefinite matrix 41 | is given by its trace we obtain 42 | 43 | .. math:: 44 | 45 | \begin{array}{ll} 46 | \mbox{minimize} & \frac{1}{2} y^T y + \lambda \mathrm{vec}(I_n)^\top x \\ 47 | \mbox{subject to} & y = Ax - b \\ 48 | & \mathrm{mat}(x) \succeq 0 49 | \end{array} 50 | 51 | over variable :math:`x \in \mathbf{R}^{n(n+1) /2}` and :math:`y \in 52 | \mathbf{R}^{|\mathcal{I}|}`, where :math:`I_n` is the :math:`n \times n` 53 | identity matrix. From this formulation it is straightforward to convert it into 54 | the standard form accepted by SCS. The regularization parameter :math:`\lambda 55 | \geq 0` trades off the rank of the solution and the quality of the fit, and so 56 | we solve the problem for many choices of :math:`\lambda`. Since :math:`\lambda` 57 | enters only in the linear part of the objective function, we can reuse the 58 | matrix factorization and use warm starting to reduce the computation time. 59 | 60 | Python code to solve this is below. 61 | 62 | .. literalinclude:: mat_completion.py 63 | :language: python 64 | 65 | After following the python :ref:`install instructions `, we can 66 | run the code yielding output: 67 | 68 | .. python mat_completion.py > mat_completion.py.out 69 | 70 | .. literalinclude:: mat_completion.py.out 71 | :language: none 72 | -------------------------------------------------------------------------------- /docs/src/examples/python/mpc.py: -------------------------------------------------------------------------------- 1 | import scs 2 | import numpy as np 3 | import scipy as sp 4 | from scipy import sparse 5 | 6 | np.random.seed(1) 7 | 8 | 9 | class MPC(object): 10 | """Model Predictive Contoller using SCS.""" 11 | 12 | def __init__(self, Ad, Bd, Q, R, q, QT, qT, xmin, xmax, umin, umax, T): 13 | # State and action dimension 14 | self.nx, self.nu = Bd.shape 15 | 16 | # Stack variables as follows: 17 | # [x_0, x_1, ..., x_{T-1}, x_T, u_0, u_1, ..., u_{T-1}] 18 | 19 | # Quadratic objective 20 | P = sparse.block_diag( 21 | [sparse.kron(sparse.eye(T), Q), QT, sparse.kron(sparse.eye(T), R)], 22 | format="csc", 23 | ) 24 | # Linear objective 25 | c = np.hstack([np.kron(np.ones(T), q), qT, np.zeros(T * self.nu)]) 26 | # Linear dynamics 27 | Ax = sparse.kron(sparse.eye(T + 1), -sparse.eye(self.nx)) + sparse.kron( 28 | sparse.eye(T + 1, k=-1), Ad 29 | ) 30 | Bu = sparse.kron( 31 | sparse.vstack([sparse.csc_matrix((1, T)), sparse.eye(T)]), Bd 32 | ) 33 | Aeq = sparse.hstack([Ax, Bu]) 34 | 35 | # Will update this later with initial state 36 | beq = np.zeros((T + 1) * self.nx) 37 | 38 | # Box constraints on state and action 39 | Aineq = sparse.eye((T + 1) * self.nx + T * self.nu) 40 | 41 | box_lower = np.hstack( 42 | [np.kron(np.ones(T + 1), xmin), np.kron(np.ones(T), umin)] 43 | ) 44 | box_upper = np.hstack( 45 | [np.kron(np.ones(T + 1), xmax), np.kron(np.ones(T), umax)] 46 | ) 47 | 48 | A = sparse.vstack( 49 | [ 50 | # zero cone 51 | Aeq, 52 | # Box cone {(t, s) | -t l <= s <= t u } 53 | sparse.csc_matrix((1, (T + 1) * self.nx + T * self.nu)), 54 | -Aineq, 55 | ], 56 | format="csc", 57 | ) 58 | 59 | # Box cone add constraint t=1 60 | self.b = np.hstack([beq, 1, np.zeros((T + 1) * self.nx + T * self.nu)]) 61 | 62 | data = dict(P=P, A=A, b=self.b, c=c) 63 | cone = dict(z=(T + 1) * self.nx, bu=box_upper, bl=box_lower) 64 | # Create an SCS object 65 | self.solver = scs.SCS(data, cone, eps_abs=1e-5, eps_rel=1e-5) 66 | 67 | def control(self, x0): 68 | # Overwrite b with new initial state 69 | self.b[: self.nx] = -x0 70 | # Update b 71 | self.solver.update(b=self.b) 72 | sol = self.solver.solve() # will warm-start automatically 73 | if sol["info"]["status"] != "solved": 74 | raise ValueError("SCS failed to solve the problem.") 75 | 76 | # Return first action 77 | return sol["x"][-T * self.nu : -(T - 1) * self.nu] 78 | 79 | 80 | # States dimension 81 | nx = 20 82 | # Control dimension 83 | nu = 5 84 | 85 | # State dynamics matrices 86 | Ad = 0.1 * np.random.randn(nx, nx) # State -> State 87 | Bd = np.random.randn(nx, nu) # Control -> State 88 | 89 | # Cost matrices 90 | Q = sparse.eye(nx) # State 91 | QT = 10 * Q # Terminal State 92 | R = 0.1 * sparse.eye(nu) # Control 93 | 94 | # Linear cost vector 95 | q = 0.1 * np.random.randn(nx) 96 | qT = q 97 | 98 | # Initial state 99 | x0 = 10 * np.random.randn(nx) 100 | 101 | # Prediction horizon 102 | T = 30 103 | 104 | # Bounds on state 105 | xmax = np.inf * np.ones(nx) 106 | xmin = -np.inf * np.ones(nx) 107 | 108 | # Bounds on control 109 | umax = np.ones(nu) 110 | umin = -np.ones(nu) 111 | 112 | # Initialize Model Predictive Controller 113 | mpc = MPC(Ad, Bd, Q, R, q, QT, qT, xmin, xmax, umin, umax, T) 114 | 115 | # Simulate in closed loop 116 | nsteps = 10 # Number of steps 117 | for i in range(nsteps): 118 | # Get control action 119 | u = mpc.control(x0) 120 | print(f"Control action: {u}") 121 | 122 | # Apply first control input and update to next state 123 | x0 = Ad @ x0 + Bd @ u + 0.01 * np.random.normal(nx, 1) # + noise 124 | x0 = np.maximum(np.minimum(x0, xmax), xmin) # Bound to xmin, xmax 125 | -------------------------------------------------------------------------------- /docs/src/examples/python/mpc.rst: -------------------------------------------------------------------------------- 1 | .. _py_mpc: 2 | 3 | Model Predictive Control 4 | ======================== 5 | 6 | In this example we shall demonstrate an instance of using the box :ref:`cone 7 | `, as well as reusing a :ref:`cached workspace and using warm-starting 8 | `. 9 | 10 | In model predictive control (MPC) the control action at each time-step is 11 | obtained by solving an optimization problem that simulates the dynamical system 12 | over some time horizon. Here, we consider the problem of controlling a linear, 13 | time-invariant dynamical systems with quadratic stage costs and box constraints 14 | on the state and action: 15 | 16 | .. math:: 17 | \begin{array}{ll} 18 | \mbox{minimize} & x_T^T Q_T x_T + q_T^\top x_T + \sum_{t=0}^{T-1}\left( x_t^T Q x_t + u_t^T R u_t + q^\top x_t \right) \\ 19 | \mbox{subject to} & x_{t+1} = A x_t + B u_t, \quad t = 0, \ldots T-1\\ 20 | & x_{\rm min} \le x_t \le x_{\rm max}, \quad t = 0, \ldots T\\ 21 | & u_{\rm min} \le u_t \le u_{\rm max}, \quad t = 0, \ldots T-1\\ 22 | & x_0 = \bar{x} 23 | \end{array} 24 | 25 | over variables corresponding to the states :math:`x_t \in \mathbf{R}^{n}`, 26 | :math:`t=0,\ldots,T`, and the inputs :math:`u_t \in \mathbf{R}^{m}`, 27 | :math:`t=0,\ldots,T-1`, where :math:`A \in \mathbf{R}^{n \times n}`, :math:`B 28 | \in \mathbf{R}^{n \times m}` correspond to the linear dynamics and :math:`Q \in 29 | \mathbf{R}^{n \times n}`, :math:`R \in \mathbf{R}^{m \times m}`, :math:`q \in 30 | \mathbf{R}^{n}` correspond to the positive semidefinite quadratic cost functions 31 | with terminal cost defined by :math:`Q_T \in \mathbf{R}^{n \times n}` and 32 | :math:`q_T \in \mathbf{R}^{n}`. 33 | 34 | The problem is solved repeatedly for varying initial state :math:`\bar{x} \in 35 | \mathbf{R}^{n}`. The upper and lower bound constraints can be expressed in 36 | SCS using the box :ref:`cone `. 37 | 38 | Python code to solve this is below. 39 | 40 | .. literalinclude:: mpc.py 41 | :language: python 42 | 43 | After following the python :ref:`install instructions `, we can 44 | run the code yielding output: 45 | 46 | .. python mpc.py > mpc.py.out 47 | 48 | .. literalinclude:: mpc.py.out 49 | :language: none 50 | -------------------------------------------------------------------------------- /docs/src/examples/python/qp.py: -------------------------------------------------------------------------------- 1 | import scipy 2 | import scs 3 | import numpy as np 4 | 5 | # Set up the problem data 6 | P = scipy.sparse.csc_matrix([[3.0, -1.0], [-1.0, 2.0]]) 7 | A = scipy.sparse.csc_matrix([[-1.0, 1.0], [1.0, 0.0], [0.0, 1.0]]) 8 | b = np.array([-1, 0.3, -0.5]) 9 | c = np.array([-1.0, -1.0]) 10 | 11 | # Populate dicts with data to pass into SCS 12 | data = dict(P=P, A=A, b=b, c=c) 13 | cone = dict(z=1, l=2) 14 | 15 | # Initialize solver 16 | solver = scs.SCS(data, cone, eps_abs=1e-9, eps_rel=1e-9) 17 | # Solve! 18 | sol = solver.solve() 19 | 20 | print(f"SCS took {sol['info']['iter']} iters") 21 | print("Optimal solution vector x*:") 22 | print(sol["x"]) 23 | 24 | print("Optimal dual vector y*:") 25 | print(sol["y"]) 26 | -------------------------------------------------------------------------------- /docs/src/examples/python/qp.py.out: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ 2 | SCS v3.2.0 - Splitting Conic Solver 3 | (c) Brendan O'Donoghue, Stanford University, 2012 4 | ------------------------------------------------------------------ 5 | problem: variables n: 2, constraints m: 3 6 | cones: z: primal zero / dual free vars: 1 7 | l: linear vars: 2 8 | settings: eps_abs: 1.0e-09, eps_rel: 1.0e-09, eps_infeas: 1.0e-07 9 | alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1 10 | max_iters: 100000, normalize: 1, rho_x: 1.00e-06 11 | acceleration_lookback: 10, acceleration_interval: 10 12 | lin-sys: sparse-direct 13 | nnz(A): 4, nnz(P): 3 14 | ------------------------------------------------------------------ 15 | iter | pri res | dua res | gap | obj | scale | time (s) 16 | ------------------------------------------------------------------ 17 | 0| 1.51e+00 1.00e+00 4.91e+00 1.14e+00 1.00e-01 8.39e-05 18 | 75| 4.09e-10 7.93e-10 1.07e-09 1.24e+00 1.00e-01 3.93e-04 19 | ------------------------------------------------------------------ 20 | status: solved 21 | timings: total: 5.30e-04s = setup: 1.31e-04s + solve: 3.98e-04s 22 | lin-sys: 1.55e-05s, cones: 4.71e-06s, accel: 2.72e-04s 23 | ------------------------------------------------------------------ 24 | objective = 1.235000 25 | ------------------------------------------------------------------ 26 | SCS took 75 iters 27 | Optimal solution vector x*: 28 | [ 0.3 -0.7] 29 | Optimal dual vector y*: 30 | [2.7 2.1 0. ] 31 | -------------------------------------------------------------------------------- /docs/src/examples/qp.c: -------------------------------------------------------------------------------- 1 | #include "scs.h" /* SCS API */ 2 | #include /* printf */ 3 | #include /* memory allocation */ 4 | 5 | /* Set up and solve basic qp */ 6 | int main(int argc, char **argv) { 7 | /* Set up the problem data */ 8 | /* A and P must be in compressed sparse column format */ 9 | double P_x[3] = {3., -1., 2.}; /* Upper triangular of P only */ 10 | int P_i[3] = {0, 0, 1}; 11 | int P_p[3] = {0, 1, 3}; 12 | double A_x[4] = {-1., 1., 1., 1.}; 13 | int A_i[4] = {0, 1, 0, 2}; 14 | int A_p[3] = {0, 2, 4}; 15 | double b[3] = {-1., 0.3, -0.5}; 16 | double c[2] = {-1., -1.}; 17 | /* data shapes */ 18 | int n = 2; /* number of variables */ 19 | int m = 3; /* number of constraints */ 20 | 21 | /* Allocate SCS structs */ 22 | ScsCone *k = (ScsCone *)calloc(1, sizeof(ScsCone)); 23 | ScsData *d = (ScsData *)calloc(1, sizeof(ScsData)); 24 | ScsSettings *stgs = (ScsSettings *)calloc(1, sizeof(ScsSettings)); 25 | ScsSolution *sol = (ScsSolution *)calloc(1, sizeof(ScsSolution)); 26 | ScsInfo *info = (ScsInfo *)calloc(1, sizeof(ScsInfo)); 27 | 28 | /* Fill in data struct */ 29 | d->m = m; 30 | d->n = n; 31 | d->b = b; 32 | d->c = c; 33 | d->A = &(ScsMatrix){A_x, A_i, A_p, m, n}; 34 | d->P = &(ScsMatrix){P_x, P_i, P_p, n, n}; 35 | 36 | /* Cone */ 37 | k->z = 1; 38 | k->l = 2; 39 | 40 | /* Utility to set default settings */ 41 | scs_set_default_settings(stgs); 42 | 43 | /* Modify tolerances */ 44 | stgs->eps_abs = 1e-9; 45 | stgs->eps_rel = 1e-9; 46 | 47 | /* Initialize SCS workspace */ 48 | ScsWork *scs_work = scs_init(d, k, stgs); 49 | 50 | /* Solve! */ 51 | int exitflag = scs_solve(scs_work, sol, info, 0); 52 | 53 | /* 54 | * If we wanted to solve many related problems with different 55 | * b / c vectors we could update the SCS workspace as follows: 56 | * 57 | * int success = scs_update(scs_work, new_b, new_c) 58 | * int new_exitflag = scs_solve(scs_work, sol, info, 1); 59 | * 60 | */ 61 | 62 | /* Free SCS workspace */ 63 | scs_finish(scs_work); 64 | 65 | /* Verify that SCS solved the problem */ 66 | printf("SCS solved successfully: %i\n", exitflag == SCS_SOLVED); 67 | 68 | /* Print some info about the solve */ 69 | printf("SCS took %i iters, using the %s linear solver.\n", info->iter, 70 | info->lin_sys_solver); 71 | 72 | /* Print solution x */ 73 | printf("Optimal solution vector x*:\n"); 74 | for (int i = 0; i < n; ++i) { 75 | printf("x[%i] = %4f\n", i, sol->x[i]); 76 | } 77 | 78 | /* Print dual solution y */ 79 | printf("Optimal dual vector y*:\n"); 80 | for (int i = 0; i < m; ++i) { 81 | printf("y[%i] = %4f\n", i, sol->y[i]); 82 | } 83 | 84 | /* Free allocated memory */ 85 | free(k); 86 | free(d); 87 | free(stgs); 88 | free(info); 89 | /* SCS allocates sol->x,y,s if NULL on entry, need to be freed */ 90 | free(sol->x); 91 | free(sol->y); 92 | free(sol->s); 93 | free(sol); 94 | return 0; /* returning exitflag will set bash exit code to 1 */ 95 | } 96 | -------------------------------------------------------------------------------- /docs/src/examples/qp.c.out: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ 2 | SCS v3.2.1 - Splitting Conic Solver 3 | (c) Brendan O'Donoghue, Stanford University, 2012 4 | ------------------------------------------------------------------ 5 | problem: variables n: 2, constraints m: 3 6 | cones: z: primal zero / dual free vars: 1 7 | l: linear vars: 2 8 | settings: eps_abs: 1.0e-09, eps_rel: 1.0e-09, eps_infeas: 1.0e-07 9 | alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1 10 | max_iters: 100000, normalize: 1, rho_x: 1.00e-06 11 | acceleration_lookback: 10, acceleration_interval: 10 12 | lin-sys: sparse-direct-amd-qdldl 13 | nnz(A): 4, nnz(P): 3 14 | ------------------------------------------------------------------ 15 | iter | pri res | dua res | gap | obj | scale | time (s) 16 | ------------------------------------------------------------------ 17 | 0| 1.51e+00 1.00e+00 4.91e+00 1.14e+00 1.00e-01 1.19e-04 18 | 75| 4.09e-10 7.93e-10 1.07e-09 1.24e+00 1.00e-01 2.10e-04 19 | ------------------------------------------------------------------ 20 | status: solved 21 | timings: total: 2.11e-04s = setup: 9.88e-05s + solve: 1.13e-04s 22 | lin-sys: 1.48e-05s, cones: 3.92e-06s, accel: 5.06e-05s 23 | ------------------------------------------------------------------ 24 | objective = 1.235000 25 | ------------------------------------------------------------------ 26 | SCS solved successfully: 1 27 | SCS took 75 iters, using the sparse-direct-amd-qdldl linear solver. 28 | Optimal solution vector x*: 29 | x[0] = 0.300000 30 | x[1] = -0.700000 31 | Optimal dual vector y*: 32 | y[0] = 2.700000 33 | y[1] = 2.100000 34 | y[2] = 0.000000 35 | -------------------------------------------------------------------------------- /docs/src/examples/qp.m: -------------------------------------------------------------------------------- 1 | % First, make sure SCS is in the path so MATLAB can call it 2 | addpath("/Users/bodonoghue/git/scs-matlab") 3 | 4 | % Set up data 5 | data.P = sparse([3., -1.; -1., 2.]); 6 | data.A = sparse([-1., 1.; 1., 0.; 0., 1.]); 7 | data.b = [-1; 0.3; -0.5]; 8 | data.c = [-1.; -1.]; 9 | cone.z = 1; 10 | cone.l = 2; 11 | 12 | % Optional solver settings 13 | settings = struct('eps_abs', 1e-9, 'eps_rel', 1e-9); 14 | 15 | % Solve! 16 | [x, y, s, info] = scs(data, cone, settings); 17 | 18 | disp(sprintf("SCS took %i iters", info.iter)) 19 | disp("Optimal solution vector x*:"); 20 | disp(x) 21 | disp("Optimal dual vector y*:"); 22 | disp(y) 23 | -------------------------------------------------------------------------------- /docs/src/examples/qp.m.out: -------------------------------------------------------------------------------- 1 | < M A T L A B (R) > 2 | Copyright 1984-2021 The MathWorks, Inc. 3 | R2021a Update 3 (9.10.0.1684407) 64-bit (maci64) 4 | May 27, 2021 5 | 6 | 7 | For online documentation, see https://www.mathworks.com/support 8 | For product information, visit www.mathworks.com. 9 | 10 | ------------------------------------------------------------------ 11 | SCS v3.0.0 - Splitting Conic Solver 12 | (c) Brendan O'Donoghue, Stanford University, 2012 13 | ------------------------------------------------------------------ 14 | problem: variables n: 2, constraints m: 3 15 | cones: z: primal zero / dual free vars: 1 16 | l: linear vars: 2 17 | settings: eps_abs: 1.0e-09, eps_rel: 1.0e-09, eps_infeas: 1.0e-07 18 | alpha: 1.50, scale: 1.00e-01, adaptive_scale: 1 19 | max_iters: 100000, normalize: 1, warm_start: 0 20 | acceleration_lookback: 10, acceleration_interval: 10 21 | lin-sys: sparse-direct 22 | nnz(A): 4, nnz(P): 3 23 | ------------------------------------------------------------------ 24 | iter | pri res | dua res | gap | obj | scale | time (s) 25 | ------------------------------------------------------------------ 26 | 0| 1.53e+00 1.00e+00 4.87e+00 1.10e+00 1.00e-01 1.53e-04 27 | 100| 6.18e-11 1.56e-12 1.30e-10 1.23e+00 1.00e-01 3.37e-04 28 | ------------------------------------------------------------------ 29 | status: solved 30 | timings: total: 5.26e-03s = setup: 4.89e-03s + solve: 3.74e-04s 31 | lin-sys: 1.96e-05s, cones: 7.60e-06s, accel: 9.94e-05s 32 | ------------------------------------------------------------------ 33 | objective = 1.235000 34 | ------------------------------------------------------------------ 35 | SCS took 100 iters 36 | Optimal solution vector x*: 37 | 0.3000 38 | -0.7000 39 | 40 | Optimal dual vector y*: 41 | 2.7000 42 | 2.1000 43 | 0 44 | 45 | -------------------------------------------------------------------------------- /docs/src/examples/qp.prob: -------------------------------------------------------------------------------- 1 | 2 | In this example we shall solve the following small quadratic program: 3 | 4 | .. math:: 5 | \begin{array}{ll} 6 | \mbox{minimize} & (1/2) x^T \begin{bmatrix}3 & -1\\ -1 & 2 \end{bmatrix} 7 | x + \begin{bmatrix}-1 \\ -1\end{bmatrix}^T x \\ 8 | \mbox{subject to} & \begin{bmatrix} -1 \\ 1 \end{bmatrix}^T x = -1 \\ 9 | & \begin{bmatrix} 1 & 0\\ 0 & 1\end{bmatrix} x \leq \begin{bmatrix}0.3 \\ -0.5\end{bmatrix} 10 | \end{array} 11 | 12 | over variable :math:`x \in \mathbf{R}^2`. This problem corresponds to data: 13 | 14 | .. math:: 15 | \begin{array}{cccc} 16 | P = \begin{bmatrix}3 & -1\\ -1 & 2 \end{bmatrix}, & 17 | A = \begin{bmatrix}-1 & 1\\ 1 & 0\\ 0 & 1\end{bmatrix}, & 18 | b = \begin{bmatrix}-1 \\ 0.3 \\ -0.5\end{bmatrix}, & 19 | c = \begin{bmatrix}-1 \\ -1\end{bmatrix}. 20 | \end{array} 21 | 22 | And the cone :math:`\mathcal{K}` consists of a zero cone (:code:`z`) of length 1 23 | and a positive cone (:code:`l`) of dimension 2. Note that the order of the 24 | rows in :math:`A` and :math:`b` corresponds to the order in :ref:`cones`, so 25 | the row corresponding to the zero cone comes first, followed by the rows for the 26 | positive cone. 27 | -------------------------------------------------------------------------------- /docs/src/examples/r.rst: -------------------------------------------------------------------------------- 1 | .. _r_example: 2 | 3 | R 4 | = 5 | 6 | .. code:: r 7 | 8 | library("scs") 9 | 10 | 11 | Second-order cone programming 12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 13 | 14 | .. math:: 15 | \begin{array}{rr} 16 | \underset{x}{\text{maximize}} 17 | & x + y \\ 18 | \text{subject to} 19 | & \sqrt{x^2 + y^2} \leq \sqrt{2} \\ 20 | & x, y \geq 0 21 | \end{array} 22 | 23 | 24 | .. code:: r 25 | 26 | obj <- c(-1, -1) 27 | A <- rbind(c(-1, 0), # x >= 0 28 | c( 0, -1), # y >= 0 29 | c( 0, 0), 30 | c(-1, 0), 31 | c( 0, -1)) 32 | b <- c(0, 0, sqrt(2), 0, 0) 33 | cone <- list(z = 0, l = 2, q = 3) 34 | 35 | solution <- scs(A, b, obj, cone = cone) 36 | str(solution) 37 | #R> List of 4 38 | #R> $ x : num [1:2] 1 1 39 | #R> $ y : num [1:5] 0 0 1.41 -1 -1 40 | #R> $ s : num [1:5] 1 1 1.41 1 1 41 | #R> $ info:List of 21 42 | #R> ..$ iter : int 50 43 | #R> ..$ status : chr "solved" 44 | #R> ..$ status_val : int 1 45 | #R> ..$ scale_updates : int 0 46 | #R> ..$ pobj : num -2 47 | #R> ..$ dobj : num -2 48 | #R> ..$ res_pri : num 4.86e-05 49 | #R> ..$ res_dual : num 1.98e-06 50 | #R> ..$ gap : num 0.000141 51 | #R> ..$ res_infeas : num NaN 52 | #R> ..$ res_unbdd_a : num 0.707 53 | #R> ..$ res_unbdd_p : num 0 54 | #R> ..$ setup_time : num 0.0236 55 | #R> ..$ solve_time : num 0.0237 56 | #R> ..$ scale : num 0.1 57 | #R> ..$ comp_slack : num 1.34e-14 58 | #R> ..$ rejected_accel_steps: int 0 59 | #R> ..$ accepted_accel_steps: int 0 60 | #R> ..$ lin_sys_time : num 0.00668 61 | #R> ..$ cone_time : num 0.00439 62 | #R> ..$ accel_time : num 0 63 | 64 | 65 | 66 | Primal exponential cone 67 | ^^^^^^^^^^^^^^^^^^^^^^^ 68 | 69 | .. math:: 70 | \begin{array}{rr} 71 | \underset{x}{\text{maximize}} & x + y + z \\ 72 | \text{subject to} & y e^{\frac{x}{y}} \leq z \\ 73 | & x \geq 0, y > 0, z \in [0, e] 74 | \end{array} 75 | 76 | 77 | .. code:: r 78 | 79 | obj <- c(-1, -1, -1) 80 | A <- rbind(-diag(3), # x, z >= 0, y >= 1e-12 81 | c(0, 0, 1), # z <= e 82 | -diag(3)) # K_exp 83 | b <- c(0, -1e-12, 0, exp(1), double(3)) 84 | cone <- list(z = 0L, l = 4L, ep = 1L) 85 | solution <- scs(A, b, obj, cone = cone) 86 | str(solution) 87 | #R> List of 4 88 | #R> $ x : num [1:3] 8.46e-05 2.72 2.72 89 | #R> $ y : num [1:7] 1.17e-05 0.00 0.00 2.00 -1.00 ... 90 | #R> $ s : num [1:7] 0.00 2.72 2.72 0.00 5.68e-05 ... 91 | #R> $ info:List of 21 92 | #R> ..$ iter : int 75 93 | #R> ..$ status : chr "solved" 94 | #R> ..$ status_val : int 1 95 | #R> ..$ scale_updates : int 0 96 | #R> ..$ pobj : num -5.44 97 | #R> ..$ dobj : num -5.44 98 | #R> ..$ res_pri : num 0.000273 99 | #R> ..$ res_dual : num 2.02e-05 100 | #R> ..$ gap : num 0.000583 101 | #R> ..$ res_infeas : num NaN 102 | #R> ..$ res_unbdd_a : num 0.5 103 | #R> ..$ res_unbdd_p : num 0 104 | #R> ..$ setup_time : num 0.0273 105 | #R> ..$ solve_time : num 0.273 106 | #R> ..$ scale : num 0.1 107 | #R> ..$ comp_slack : num 8.54e-09 108 | #R> ..$ rejected_accel_steps: int 0 109 | #R> ..$ accepted_accel_steps: int 0 110 | #R> ..$ lin_sys_time : num 0.0118 111 | #R> ..$ cone_time : num 0.242 112 | #R> ..$ accel_time : num 0 113 | -------------------------------------------------------------------------------- /docs/src/examples/ruby.rst: -------------------------------------------------------------------------------- 1 | .. _ruby_example: 2 | 3 | Ruby 4 | ==== 5 | 6 | See examples `here `_. 7 | 8 | -------------------------------------------------------------------------------- /docs/src/files/qp_solvers_benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/files/qp_solvers_benchmark.png -------------------------------------------------------------------------------- /docs/src/files/windows1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/files/windows1.png -------------------------------------------------------------------------------- /docs/src/files/windows2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/files/windows2.png -------------------------------------------------------------------------------- /docs/src/files/windows3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/docs/src/files/windows3.png -------------------------------------------------------------------------------- /docs/src/help/index.rst: -------------------------------------------------------------------------------- 1 | .. _help: 2 | 3 | Help 4 | ==== 5 | 6 | Currently the easiest way to get support is to file a `GitHub issue 7 | `_ or to `email us 8 | `_ (which may be slower). 9 | 10 | If you are have a problem that SCS struggles to solve you can set the 11 | :code:`write_data_filename` field in the :ref:`settings ` and SCS will 12 | dump a file containing the problem data to disk under that filename. Zip the 13 | file and `email it to us `_ or attach 14 | it to a GitHub issue. This makes it much easier for us to reproduce the problem. 15 | 16 | A common cause of issues is not linking :ref:`BLAS/LAPACK libraries 17 | ` correctly. If you are having this issue please search for 18 | resources on installing and linking these libraries first. You can try `OpenBLAS 19 | `_ if you need a BLAS library. 20 | 21 | -------------------------------------------------------------------------------- /docs/src/install/index.rst: -------------------------------------------------------------------------------- 1 | .. _install: 2 | 3 | Install 4 | ======= 5 | 6 | Follow the links below for install instructions for each language. 7 | 8 | :ref:`C/C++ ` 9 | 10 | :ref:`Python ` 11 | 12 | :ref:`MATLAB ` 13 | 14 | :ref:`Julia ` 15 | 16 | :ref:`R ` 17 | 18 | :ref:`Ruby ` 19 | 20 | :ref:`JavaScript / WebAssembly ` 21 | 22 | .. toctree:: 23 | :maxdepth: 2 24 | :hidden: 25 | 26 | c.rst 27 | python.rst 28 | matlab.rst 29 | julia.rst 30 | r.rst 31 | ruby.rst 32 | javascript.rst 33 | -------------------------------------------------------------------------------- /docs/src/install/javascript.rst: -------------------------------------------------------------------------------- 1 | .. _javascript_install: 2 | 3 | JavaScript / WebAssembly 4 | ======================== 5 | 6 | SCS is available in `a WebAssembly version 7 | `_ that can be used with JavaScript. 8 | Note that the JavaScript version does not support compiling with BLAS 9 | and LAPACK, so it does not support solving SDPs. 10 | 11 | For building the WebAssembly version from source, see the `scs.wasm 12 | `_ repository. 13 | 14 | The page on the :ref:`JS interface ` provides more 15 | information on how to use SCS in JavaScript environments once loaded or installed. 16 | 17 | Install with npm 18 | ---------------- 19 | 20 | The package can be installed using `npm `_: 21 | 22 | .. code:: bash 23 | 24 | npm install scs-solver 25 | 26 | It can be used in Node.js and in the browser. 27 | 28 | Loading from a CDN in the browser 29 | --------------------------------- 30 | 31 | The package can also directly be included in a webpage using a CDN, by 32 | using one of the following script tags: 33 | 34 | .. code:: html 35 | 36 | 37 | 38 | 39 | It can also be imported in JavaScript code using ES6 modules: 40 | 41 | .. code:: html 42 | 43 | 47 | 48 | You can also host the files yourself, by `downloading the files 49 | `_, and putting ``scs.js`` (or 50 | ``scs.mjs``) and ``scs.wasm`` in the same directory. -------------------------------------------------------------------------------- /docs/src/install/julia.rst: -------------------------------------------------------------------------------- 1 | .. _julia_install: 2 | 3 | Julia 4 | ===== 5 | 6 | Install SCS via the Julia package manager: 7 | 8 | .. code:: julia 9 | 10 | import Pkg 11 | Pkg.add("SCS") 12 | 13 | This will install the `SCS.jl `_ 14 | package, along with the necessary SCS binary for your system. 15 | 16 | For instructions on how to use a custom version of SCS, consult the 17 | `SCS.jl README `_. 18 | 19 | Note that SCS.jl is a third-party package maintained by the 20 | `JuMP-dev community `_. 21 | -------------------------------------------------------------------------------- /docs/src/install/matlab.rst: -------------------------------------------------------------------------------- 1 | .. _matlab_install: 2 | 3 | MATLAB 4 | ====== 5 | 6 | To install SCS in Matlab from source: 7 | 8 | .. code:: bash 9 | 10 | git clone --recursive https://github.com/bodono/scs-matlab.git 11 | 12 | Then in a Matlab session 13 | 14 | .. code:: matlab 15 | 16 | cd 17 | make_scs 18 | 19 | Remember to include the scs-matlab directory in your Matlab path if you wish to 20 | use the mex file in your Matlab code. 21 | 22 | .. code:: matlab 23 | 24 | addpath(pwd) 25 | savepath 26 | 27 | See :ref:`here ` for the API. 28 | 29 | -------------------------------------------------------------------------------- /docs/src/install/python.rst: -------------------------------------------------------------------------------- 1 | .. _python_install: 2 | 3 | Python 4 | ====== 5 | 6 | The easiest way to install the python version is using `pip `_: 7 | 8 | .. code:: bash 9 | 10 | pip install scs 11 | 12 | You can also install directly from source 13 | 14 | .. code:: bash 15 | 16 | git clone --recursive https://github.com/bodono/scs-python.git 17 | cd scs-python 18 | python -m pip install --verbose . 19 | 20 | If you have MKL, you can install the MKL Pardiso interface using 21 | 22 | .. code:: bash 23 | 24 | python -m pip install --verbose -Csetup-args=-Dlink_mkl=true . 25 | 26 | See :ref:`here ` for how to enable MKL when solving. MKL is typically 27 | faster than the built-in linear system solver. 28 | 29 | To test that SCS installed correctly, and you have pytest installed, run 30 | 31 | .. code:: bash 32 | 33 | python -m pytest . 34 | 35 | See :ref:`here ` for the full SCS python API. 36 | 37 | Legacy options 38 | -------------- 39 | 40 | You can install with OpenMP parallelization support using 41 | 42 | .. code:: bash 43 | 44 | python legacy_setup.py install --scs --openmp 45 | 46 | You can install the GPU interface using (the GPU solver is no longer recommended) 47 | 48 | .. code:: bash 49 | 50 | python legacy_setup.py install --scs --gpu 51 | 52 | -------------------------------------------------------------------------------- /docs/src/install/r.rst: -------------------------------------------------------------------------------- 1 | .. _r_install: 2 | 3 | R 4 | = 5 | 6 | Since the **R** interface is available on **CRAN**, the package can 7 | be installed by running the following code in **R**. 8 | 9 | .. code:: r 10 | 11 | install.packages("scs") 12 | -------------------------------------------------------------------------------- /docs/src/install/ruby.rst: -------------------------------------------------------------------------------- 1 | .. _ruby_install: 2 | 3 | Ruby 4 | ==== 5 | 6 | See instructions `here `_. 7 | 8 | -------------------------------------------------------------------------------- /docs/src/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=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 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/src/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-rtd-theme 3 | alabaster 4 | breathe 5 | -------------------------------------------------------------------------------- /include/aa.h: -------------------------------------------------------------------------------- 1 | #ifndef AA_H_GUARD 2 | #define AA_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include 10 | #include 11 | #include 12 | 13 | typedef scs_float aa_float; 14 | typedef scs_int aa_int; 15 | 16 | typedef struct ACCEL_WORK AaWork; 17 | 18 | /** 19 | * Initialize Anderson Acceleration, allocates memory. 20 | * 21 | * @param dim the dimension of the variable for AA 22 | * @param mem the memory (number of past iterations used) for AA 23 | * @param type1 if True use type 1 AA, otherwise use type 2 24 | * @param regularization type-I and type-II different, for type-I: 1e-8 works 25 | * well, type-II: more stable can use 1e-12 often 26 | * @param relaxation float in [0,2], mixing parameter (1.0 is vanilla) 27 | * @param safeguard_factor factor that controls safeguarding checks 28 | * larger is more aggressive but less stable 29 | * @param max_weight_norm float, maximum norm of AA weights 30 | * @param verbosity if greater than 0 prints out various info 31 | * 32 | * @return pointer to AA workspace 33 | * 34 | */ 35 | AaWork *aa_init(aa_int dim, aa_int mem, aa_int type1, aa_float regularization, 36 | aa_float relaxation, aa_float safeguard_factor, 37 | aa_float max_weight_norm, aa_int verbosity); 38 | /** 39 | * Apply Anderson Acceleration. The usage pattern should be as follows: 40 | * 41 | * - for i = 0 .. N: 42 | * - if (i > 0): aa_apply(x, x_prev, a) 43 | * - x_prev = x.copy() 44 | * - x = F(x) 45 | * - aa_safeguard(x, x_prev, a) // optional but helps stability 46 | * 47 | * Here F is the map we are trying to find the fixed point for. We put the AA 48 | * before the map so that any properties of the map are maintained at the end. 49 | * Eg if the map contains a projection onto a set then the output is guaranteed 50 | * to be in the set. 51 | * 52 | * 53 | * @param f output of map at current iteration, overwritten with AA output 54 | * @param x input to map at current iteration 55 | * @param a workspace from aa_init 56 | * 57 | * @return (+ or -) norm of AA weights vector. If positive then update 58 | * was accepted and f contains new point, if negative then update was 59 | * rejected and f is unchanged 60 | * 61 | */ 62 | aa_float aa_apply(aa_float *f, const aa_float *x, AaWork *a); 63 | 64 | /** 65 | * Apply safeguarding. 66 | * 67 | * This step is optional but can improve stability. 68 | * 69 | * @param f_new output of map after AA step 70 | * @param x_new AA output that is input to the map 71 | * @param a workspace from aa_init 72 | * 73 | * @returns 0 if AA step is accepted otherwise -1, if AA step is rejected then 74 | * this overwrites f_new and x_new with previous values 75 | * 76 | */ 77 | aa_int aa_safeguard(aa_float *f_new, aa_float *x_new, AaWork *a); 78 | 79 | /** 80 | * Finish Anderson Acceleration, clears memory. 81 | * 82 | * @param a AA workspace from aa_init 83 | * 84 | */ 85 | void aa_finish(AaWork *a); 86 | 87 | /** 88 | * Reset Anderson Acceleration. 89 | * 90 | * Resets AA as if at the first iteration, reuses original memory allocations. 91 | * 92 | * @param a AA workspace from aa_init 93 | * 94 | */ 95 | void aa_reset(AaWork *a); 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | #endif 101 | -------------------------------------------------------------------------------- /include/cones.h: -------------------------------------------------------------------------------- 1 | #ifndef CONES_H_GUARD 2 | #define CONES_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include "scs.h" 10 | #include "scs_blas.h" 11 | #include "scs_work.h" 12 | #include 13 | 14 | /* private data to help cone projection step */ 15 | struct SCS_CONE_WORK { 16 | /* 17 | * cone_boundaries will contain array of indices of rows of A corresponding to 18 | * cone boundaries, boundaries[0] is starting index for cones of size larger 19 | * than 1 20 | */ 21 | ScsCone *k; /* original cone information */ 22 | scs_int *cone_boundaries; 23 | scs_int cone_boundaries_len; 24 | scs_int scaled_cones; /* boolean, whether the cones have been scaled */ 25 | scs_float *s; /* used for Moreau decomposition in projection */ 26 | scs_int m; /* total length of cone */ 27 | /* box cone quantities */ 28 | scs_float box_t_warm_start; 29 | #ifdef USE_LAPACK 30 | /* workspace for eigenvector decompositions: */ 31 | scs_float *Xs, *Z, *e, *work; 32 | blas_int lwork; 33 | #endif 34 | }; 35 | 36 | void SCS(free_cone)(ScsCone *k); 37 | void SCS(deep_copy_cone)(ScsCone *dest, const ScsCone *src); 38 | ScsConeWork *SCS(init_cone)(ScsCone *k, scs_int m); 39 | char *SCS(get_cone_header)(const ScsCone *k); 40 | scs_int SCS(validate_cones)(const ScsData *d, const ScsCone *k); 41 | scs_int SCS(proj_dual_cone)(scs_float *x, ScsConeWork *c, ScsScaling *scal, 42 | scs_float *r_y); 43 | void SCS(finish_cone)(ScsConeWork *c); 44 | void SCS(set_r_y)(const ScsConeWork *c, scs_float scale, scs_float *r_y); 45 | void SCS(enforce_cone_boundaries)(const ScsConeWork *c, scs_float *vec, 46 | scs_float (*f)(const scs_float *, scs_int)); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | #endif 52 | -------------------------------------------------------------------------------- /include/ctrlc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Interface for SCS signal handling. 3 | */ 4 | 5 | #ifndef CTRLC_H_GUARD 6 | #define CTRLC_H_GUARD 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #if CTRLC > 0 13 | 14 | void scs_start_interrupt_listener(void); 15 | void scs_end_interrupt_listener(void); 16 | int scs_is_interrupted(void); 17 | 18 | #else /* CTRLC = 0 */ 19 | 20 | /* Simply to suppress empty translation unit warnings. */ 21 | typedef int scs_make_iso_compilers_happy; 22 | 23 | /* No signal handling. */ 24 | #define scs_start_interrupt_listener() 25 | #define scs_end_interrupt_listener() 26 | #define scs_is_interrupted() 0 27 | 28 | #endif /* END IF CTRLC > 0 */ 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | #endif 34 | -------------------------------------------------------------------------------- /include/linalg.h: -------------------------------------------------------------------------------- 1 | #ifndef LINALG_H_GUARD 2 | #define LINALG_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include 10 | 11 | void SCS(scale_array)(scs_float *a, const scs_float b, scs_int len); 12 | scs_float SCS(dot)(const scs_float *x, const scs_float *y, scs_int len); 13 | scs_float SCS(norm_sq)(const scs_float *v, scs_int len); 14 | scs_float SCS(norm_2)(const scs_float *v, scs_int len); 15 | scs_float SCS(norm_inf)(const scs_float *a, scs_int l); 16 | void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int n, 17 | const scs_float sc); 18 | scs_float SCS(norm_diff)(const scs_float *a, const scs_float *b, scs_int l); 19 | scs_float SCS(norm_inf_diff)(const scs_float *a, const scs_float *b, scs_int l); 20 | scs_float SCS(mean)(const scs_float *x, scs_int l); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | #endif 26 | -------------------------------------------------------------------------------- /include/linsys.h: -------------------------------------------------------------------------------- 1 | #ifndef LINSYS_H_GUARD 2 | #define LINSYS_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include "scs.h" 10 | 11 | /* This is the API that any new linear system solver must implement */ 12 | 13 | /* Struct containing linear system workspace. Implemented by linear solver. */ 14 | /* This typedef is in scs.h */ 15 | /* typedef struct SCS_LIN_SYS_WORK ScsLinSysWork; */ 16 | 17 | /** 18 | * Initialize `ScsLinSysWork` structure and perform any necessary preprocessing. 19 | * 20 | * @param A `A` data matrix, `m x n`. 21 | * @param P `P` data matrix, `n x n`. 22 | * @param diag_r `R > 0` diagonal entries of length `m + n`. 23 | * @return Linear system solver workspace. 24 | * 25 | */ 26 | ScsLinSysWork *scs_init_lin_sys_work(const ScsMatrix *A, const ScsMatrix *P, 27 | const scs_float *diag_r); 28 | 29 | /** 30 | * Frees `ScsLinSysWork` structure and associated allocated memory. 31 | * 32 | * @param w Linear system private workspace. 33 | */ 34 | void scs_free_lin_sys_work(ScsLinSysWork *w); 35 | 36 | /** 37 | * Solves the linear system as required by SCS at each iteration: 38 | * \f[ 39 | * \begin{bmatrix} 40 | * (R_x + P) & A^\top \\ 41 | * A & -R_y \\ 42 | * \end{bmatrix} x = b 43 | * \f] 44 | * 45 | * for `x`, where `diag(R_x, R_y) = R`. Overwrites `b` with result. 46 | * 47 | * @param w Linear system private workspace. 48 | * @param b Right hand side, contains solution at the end. 49 | * @param s Contains warm-start (may be NULL). 50 | * @param tol Tolerance required for the system solve. 51 | * @return status != 0 indicates failure. 52 | * 53 | */ 54 | scs_int scs_solve_lin_sys(ScsLinSysWork *w, scs_float *b, const scs_float *s, 55 | scs_float tol); 56 | /** 57 | * Update the linsys workspace when `R` is changed. For example, a 58 | * direct method for solving the linear system might need to update the 59 | * factorization of the matrix. 60 | * 61 | * @param w Linear system private workspace. 62 | * @param new_diag_r Updated `diag_r`, diagonal entries of R. 63 | * 64 | */ 65 | void scs_update_lin_sys_diag_r(ScsLinSysWork *w, const scs_float *new_diag_r); 66 | 67 | /** 68 | * Name of the linear solver. 69 | * 70 | * @return name of method. 71 | */ 72 | const char *scs_get_lin_sys_method(void); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /include/normalize.h: -------------------------------------------------------------------------------- 1 | #ifndef NORMALIZE_H_GUARD 2 | #define NORMALIZE_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include "scs_work.h" 10 | 11 | void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c); 12 | void SCS(normalize_sol)(ScsScaling *scal, ScsSolution *sol); 13 | void SCS(un_normalize_sol)(ScsScaling *scal, ScsSolution *sol); 14 | void SCS(un_normalize_primal)(ScsScaling *scal, scs_float *r); 15 | void SCS(un_normalize_dual)(ScsScaling *scal, scs_float *r); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | #endif 21 | -------------------------------------------------------------------------------- /include/rw.h: -------------------------------------------------------------------------------- 1 | #ifndef RW_H_GUARD 2 | #define RW_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include "scs.h" 10 | #include "util.h" 11 | 12 | void SCS(write_data)(const ScsData *d, const ScsCone *k, 13 | const ScsSettings *stgs); 14 | scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k, 15 | ScsSettings **stgs); 16 | void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs, 17 | const ScsWork *w, scs_int iter, 18 | SCS(timer) * solve_timer); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | #endif 24 | -------------------------------------------------------------------------------- /include/scs_blas.h: -------------------------------------------------------------------------------- 1 | #ifndef SCS_BLAS_H_GUARD 2 | #define SCS_BLAS_H_GUARD 3 | 4 | #ifdef USE_LAPACK 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* Default to underscore for blas / lapack */ 11 | #ifndef BLASSUFFIX 12 | #define BLASSUFFIX _ 13 | #endif 14 | 15 | /* annoying hack because some preprocessors can't handle empty macros */ 16 | #if defined(NOBLASSUFFIX) && NOBLASSUFFIX > 0 17 | /* single or double precision */ 18 | #ifndef SFLOAT 19 | #define BLAS(x) d##x 20 | #define BLASI(x) id##x 21 | #else 22 | #define BLAS(x) s##x 23 | #define BLASI(x) is##x 24 | #endif 25 | #else 26 | /* this extra indirection is needed for BLASSUFFIX to work correctly as a 27 | * variable */ 28 | #define stitch_(pre, x, post) pre##x##post 29 | #define stitch__(pre, x, post) stitch_(pre, x, post) 30 | /* single or double precision */ 31 | #ifndef SFLOAT 32 | #define BLAS(x) stitch__(d, x, BLASSUFFIX) 33 | #define BLASI(x) stitch__(id, x, BLASSUFFIX) 34 | #else 35 | #define BLAS(x) stitch__(s, x, BLASSUFFIX) 36 | #define BLASI(x) stitch__(is, x, BLASSUFFIX) 37 | #endif 38 | #endif 39 | 40 | #ifdef MATLAB_MEX_FILE 41 | typedef ptrdiff_t blas_int; 42 | #elif defined BLAS64 43 | #include 44 | typedef int64_t blas_int; 45 | #else 46 | typedef int blas_int; 47 | #endif 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* USE_LAPACK */ 54 | 55 | #endif /* SCS_BLAS_H_GUARD */ 56 | -------------------------------------------------------------------------------- /include/scs_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Pulic header including definitions of primitive types used in SCS. 3 | * Make sure this file and `scs.h` are somewhere appropriate and then use 4 | * `#include "scs.h"` to access the SCS public API. 5 | */ 6 | 7 | #ifndef SCS_TYPES_H_GUARD 8 | #define SCS_TYPES_H_GUARD 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #ifdef DLONG 15 | /*#ifdef _WIN64 16 | #include 17 | typedef int64_t scs_int; 18 | #else 19 | typedef long scs_int; 20 | #endif 21 | */ 22 | typedef long long scs_int; 23 | #else 24 | typedef int scs_int; 25 | #endif 26 | 27 | #ifndef SFLOAT 28 | typedef double scs_float; 29 | #else 30 | typedef float scs_float; 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | #endif 37 | -------------------------------------------------------------------------------- /include/scs_work.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Define ScsWork and related internal-only structs (not part of external API). 3 | */ 4 | 5 | #ifndef SCS_WORK_H_GUARD 6 | #define SCS_WORK_H_GUARD 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include "scs.h" 13 | 14 | /** Contains normalization variables. */ 15 | typedef struct { 16 | scs_float *D, *E; /* for normalization */ 17 | scs_int m; /* Length of D */ 18 | scs_int n; /* Length of E */ 19 | scs_float primal_scale, dual_scale; 20 | } ScsScaling; 21 | 22 | /** Holds residual information. */ 23 | typedef struct { 24 | scs_int last_iter; 25 | scs_float xt_p_x; /* x' P x */ 26 | scs_float xt_p_x_tau; /* x'Px * tau^2 *not* divided out */ 27 | scs_float ctx; 28 | scs_float ctx_tau; /* tau *not* divided out */ 29 | scs_float bty; 30 | scs_float bty_tau; /* tau *not* divided out */ 31 | scs_float pobj; /* primal objective */ 32 | scs_float dobj; /* dual objective */ 33 | scs_float gap; /* pobj - dobj */ 34 | scs_float tau; 35 | scs_float kap; 36 | scs_float res_pri; 37 | scs_float res_dual; 38 | scs_float res_infeas; 39 | scs_float res_unbdd_p; 40 | scs_float res_unbdd_a; 41 | /* tau NOT divided out */ 42 | scs_float *ax, *ax_s, *px, *aty, *ax_s_btau, *px_aty_ctau; 43 | } ScsResiduals; 44 | 45 | /** Workspace for SCS. */ 46 | struct SCS_WORK { 47 | /* x_prev = x from previous iteration */ 48 | scs_float setup_time; /* time taken for setup phase (milliseconds) */ 49 | scs_int time_limit_reached; /* boolean, if the time-limit is reached */ 50 | scs_float *u, *u_t; 51 | scs_float *v, *v_prev; 52 | scs_float *rsk; /* rsk [ r; s; kappa ] */ 53 | scs_float *h; /* h = [c; b] */ 54 | scs_float *g; /* g = (I + M)^{-1} h */ 55 | scs_float *lin_sys_warm_start; /* linear system warm-start (indirect only) */ 56 | scs_float *diag_r; /* vector of R matrix diagonals (affects cone proj) */ 57 | scs_float *b_orig, *c_orig; /* original unnormalized b and c vectors */ 58 | scs_float nm_b_orig, nm_c_orig; /* unnormalized NORM(b), NORM(c) */ 59 | AaWork *accel; /* struct for acceleration workspace */ 60 | ScsData *d; /* Problem data deep copy NORMALIZED */ 61 | ScsCone *k; /* Problem cone deep copy */ 62 | ScsSettings *stgs; /* contains solver settings specified by user */ 63 | ScsLinSysWork *p; /* struct populated by linear system solver */ 64 | ScsScaling *scal; /* contains the re-scaling data */ 65 | ScsConeWork *cone_work; /* workspace for the cone projection step */ 66 | /* normalized and unnormalized residuals */ 67 | ScsResiduals *r_orig, *r_normalized; 68 | /* track x,y,s as alg progresses, tau *not* divided out */ 69 | ScsSolution *xys_orig, *xys_normalized; 70 | /* Scale updating workspace */ 71 | scs_float sum_log_scale_factor; 72 | scs_int last_scale_update_iter, n_log_scale_factor, scale_updates; 73 | /* AA stats */ 74 | scs_float aa_norm; 75 | scs_int rejected_accel_steps, accepted_accel_steps; 76 | }; 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | #endif 82 | -------------------------------------------------------------------------------- /include/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H_GUARD 2 | #define UTIL_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "cones.h" 9 | #include "scs.h" 10 | #include 11 | #include 12 | 13 | /* timing code courtesy of A. Domahidi */ 14 | #if (defined NO_TIMER) 15 | typedef void *SCS(timer); 16 | #elif (defined _WIN32 || defined _WIN64 || defined _WINDLL) 17 | /* Use Windows QueryPerformanceCounter for timing */ 18 | #include 19 | typedef struct SCS(timer) { 20 | LARGE_INTEGER tic; 21 | LARGE_INTEGER toc; 22 | LARGE_INTEGER freq; 23 | } SCS(timer); 24 | 25 | #elif (defined __APPLE__) 26 | /* Use MAC OSX mach_time for timing */ 27 | #include 28 | typedef struct SCS(timer) { 29 | uint64_t tic; 30 | uint64_t toc; 31 | mach_timebase_info_data_t tinfo; 32 | } SCS(timer); 33 | 34 | #else 35 | /* Use POSIX clock_gettime() for timing on other machines */ 36 | #include 37 | typedef struct SCS(timer) { 38 | struct timespec tic; 39 | struct timespec toc; 40 | } SCS(timer); 41 | 42 | #endif 43 | 44 | /* these all return milli-seconds */ 45 | void SCS(tic)(SCS(timer) * t); 46 | scs_float SCS(tocq)(SCS(timer) * t); 47 | void SCS(free_sol)(ScsSolution *sol); 48 | void SCS(deep_copy_data)(ScsData *dest, const ScsData *src); 49 | void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src); 50 | void SCS(free_data)(ScsData *d); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | #endif 56 | -------------------------------------------------------------------------------- /linsys/cpu/direct/private.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIV_H_GUARD 2 | #define PRIV_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "csparse.h" 9 | #include "external/amd/amd.h" 10 | #include "external/qdldl/qdldl.h" 11 | #include "glbopts.h" 12 | #include "linsys.h" 13 | #include "scs_matrix.h" 14 | 15 | struct SCS_LIN_SYS_WORK { 16 | scs_int m, n; /* linear system dimensions */ 17 | ScsMatrix *kkt, *L; /* KKT, and factorization matrix L resp. */ 18 | scs_float *Dinv; /* inverse diagonal matrix of factorization */ 19 | scs_int *perm; /* permutation of KKT matrix for factorization */ 20 | scs_float *bp; /* workspace memory for solves */ 21 | scs_int *diag_r_idxs; 22 | scs_int factorizations; 23 | /* ldl factorization workspace */ 24 | scs_float *D, *fwork; 25 | scs_int *etree, *iwork, *Lnz, *bwork; 26 | scs_float *diag_p; 27 | }; 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | #endif 33 | -------------------------------------------------------------------------------- /linsys/cpu/indirect/private.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIV_H_GUARD 2 | #define PRIV_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "csparse.h" 9 | #include "glbopts.h" 10 | #include "linalg.h" 11 | #include "linsys.h" 12 | #include "scs_matrix.h" 13 | #include "util.h" /* timer */ 14 | #include 15 | 16 | struct SCS_LIN_SYS_WORK { 17 | scs_int n, m; /* linear system dimensions */ 18 | scs_float *p; /* cg iterate */ 19 | scs_float *r; /* cg residual */ 20 | scs_float *Gp; 21 | scs_float *tmp; 22 | const ScsMatrix *A; /* does *not* own this memory */ 23 | const ScsMatrix *P; /* does *not* own this memory */ 24 | ScsMatrix *At; /* does own this memory */ 25 | /* preconditioning */ 26 | scs_float *z; 27 | scs_float *M; 28 | /* reporting */ 29 | scs_int tot_cg_its; 30 | const scs_float *diag_r; 31 | }; 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | #endif 37 | -------------------------------------------------------------------------------- /linsys/csparse.h: -------------------------------------------------------------------------------- 1 | /* Routines modified from CSparse, T. Davis et al */ 2 | 3 | #ifndef CS_H_GUARD 4 | #define CS_H_GUARD 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "glbopts.h" 11 | #include "scs.h" 12 | 13 | ScsMatrix *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values, 14 | scs_int triplet); 15 | ScsMatrix *SCS(cs_done)(ScsMatrix *C, void *w, void *x, scs_int ok); 16 | ScsMatrix *SCS(cs_compress)(const ScsMatrix *T, scs_int nz, 17 | scs_int *idx_mapping); 18 | ScsMatrix *SCS(cs_spfree)(ScsMatrix *A); 19 | scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n); 20 | /* Forms KKT matrix */ 21 | ScsMatrix *SCS(form_kkt)(const ScsMatrix *A, const ScsMatrix *P, 22 | scs_float *diag_p, const scs_float *diag_r, 23 | scs_int *diag_r_idxs, scs_int upper); 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | #endif 28 | -------------------------------------------------------------------------------- /linsys/external/amd/LICENSE.txt: -------------------------------------------------------------------------------- 1 | ==> AMD/Doc/License.txt <== 2 | 3 | AMD, Copyright (c), 1996-2015, Timothy A. Davis, 4 | Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. 5 | 6 | Availability: 7 | 8 | http://www.suitesparse.com 9 | 10 | ------------------------------------------------------------------------------- 11 | AMD License: BSD 3-clause: 12 | ------------------------------------------------------------------------------- 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are met: 16 | * Redistributions of source code must retain the above copyright 17 | notice, this list of conditions and the following disclaimer. 18 | * Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | * Neither the name of the organizations to which the authors are 22 | affiliated, nor the names of its contributors may be used to endorse 23 | or promote products derived from this software without specific prior 24 | written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 36 | DAMAGE. 37 | 38 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_control.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === AMD_control ========================================================= */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* User-callable. Prints the control parameters for AMD. See amd.h 12 | * for details. If the Control array is not present, the defaults are 13 | * printed instead. 14 | */ 15 | 16 | #include "amd_internal.h" 17 | 18 | GLOBAL void AMD_control 19 | ( 20 | scs_float Control [ ] 21 | ) 22 | { 23 | scs_float alpha ; 24 | Int aggressive ; 25 | 26 | if (Control != (scs_float *) NULL) 27 | { 28 | alpha = Control [AMD_DENSE] ; 29 | aggressive = Control [AMD_AGGRESSIVE] != 0 ; 30 | } 31 | else 32 | { 33 | alpha = AMD_DEFAULT_DENSE ; 34 | aggressive = AMD_DEFAULT_AGGRESSIVE ; 35 | } 36 | 37 | SUITESPARSE_PRINTF (( 38 | "\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n" 39 | " dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, 40 | AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ; 41 | 42 | if (alpha < 0) 43 | { 44 | SUITESPARSE_PRINTF ((" no rows treated as dense\n")) ; 45 | } 46 | else 47 | { 48 | SUITESPARSE_PRINTF (( 49 | " (rows with more than max (%g * sqrt (n), 16) entries are\n" 50 | " considered \"dense\", and placed last in output permutation)\n", 51 | alpha)) ; 52 | } 53 | 54 | if (aggressive) 55 | { 56 | SUITESPARSE_PRINTF ((" aggressive absorption: yes\n")) ; 57 | } 58 | else 59 | { 60 | SUITESPARSE_PRINTF ((" aggressive absorption: no\n")) ; 61 | } 62 | 63 | SUITESPARSE_PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ; 64 | } 65 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_defaults.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === AMD_defaults ======================================================== */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* User-callable. Sets default control parameters for AMD. See amd.h 12 | * for details. 13 | */ 14 | 15 | #include "amd_internal.h" 16 | 17 | /* ========================================================================= */ 18 | /* === AMD defaults ======================================================== */ 19 | /* ========================================================================= */ 20 | 21 | GLOBAL void AMD_defaults 22 | ( 23 | scs_float Control [ ] 24 | ) 25 | { 26 | Int i ; 27 | 28 | if (Control != (scs_float *) NULL) 29 | { 30 | for (i = 0 ; i < AMD_CONTROL ; i++) 31 | { 32 | Control [i] = 0 ; 33 | } 34 | Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; 35 | Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_global.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === amd_global ========================================================== */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* In prior versions of AMD, this file declared the amd_malloc, amd_free, 12 | amd_realloc, amd_calloc, and amd_printf functions. They are now replaced 13 | by functions defined in SuiteSparse_config/SuiteSparse_config.c. 14 | */ 15 | /* Simply to suppress empty translation unit warnings. */ 16 | typedef int scs_amd_make_iso_compilers_happy; 17 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_post_tree.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === AMD_post_tree ======================================================= */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* Post-ordering of a supernodal elimination tree. */ 12 | 13 | #include "amd_internal.h" 14 | 15 | GLOBAL Int AMD_post_tree 16 | ( 17 | Int root, /* root of the tree */ 18 | Int k, /* start numbering at k */ 19 | Int Child [ ], /* input argument of size nn, undefined on 20 | * output. Child [i] is the head of a link 21 | * list of all nodes that are children of node 22 | * i in the tree. */ 23 | const Int Sibling [ ], /* input argument of size nn, not modified. 24 | * If f is a node in the link list of the 25 | * children of node i, then Sibling [f] is the 26 | * next child of node i. 27 | */ 28 | Int Order [ ], /* output order, of size nn. Order [i] = k 29 | * if node i is the kth node of the reordered 30 | * tree. */ 31 | Int Stack [ ] /* workspace of size nn */ 32 | #ifndef NDEBUG 33 | , Int nn /* nodes are in the range 0..nn-1. */ 34 | #endif 35 | ) 36 | { 37 | Int f, head, h, i ; 38 | 39 | #if 0 40 | /* --------------------------------------------------------------------- */ 41 | /* recursive version (Stack [ ] is not used): */ 42 | /* --------------------------------------------------------------------- */ 43 | 44 | /* this is simple, but can caouse stack overflow if nn is large */ 45 | i = root ; 46 | for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 47 | { 48 | k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; 49 | } 50 | Order [i] = k++ ; 51 | return (k) ; 52 | #endif 53 | 54 | /* --------------------------------------------------------------------- */ 55 | /* non-recursive version, using an explicit stack */ 56 | /* --------------------------------------------------------------------- */ 57 | 58 | /* push root on the stack */ 59 | head = 0 ; 60 | Stack [0] = root ; 61 | 62 | while (head >= 0) 63 | { 64 | /* get head of stack */ 65 | ASSERT (head < nn) ; 66 | i = Stack [head] ; 67 | AMD_DEBUG1 (("head of stack "ID" \n", i)) ; 68 | ASSERT (i >= 0 && i < nn) ; 69 | 70 | if (Child [i] != EMPTY) 71 | { 72 | /* the children of i are not yet ordered */ 73 | /* push each child onto the stack in reverse order */ 74 | /* so that small ones at the head of the list get popped first */ 75 | /* and the biggest one at the end of the list gets popped last */ 76 | for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 77 | { 78 | head++ ; 79 | ASSERT (head < nn) ; 80 | ASSERT (f >= 0 && f < nn) ; 81 | } 82 | h = head ; 83 | ASSERT (head < nn) ; 84 | for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 85 | { 86 | ASSERT (h > 0) ; 87 | Stack [h--] = f ; 88 | AMD_DEBUG1 (("push "ID" on stack\n", f)) ; 89 | ASSERT (f >= 0 && f < nn) ; 90 | } 91 | ASSERT (Stack [h] == i) ; 92 | 93 | /* delete child list so that i gets ordered next time we see it */ 94 | Child [i] = EMPTY ; 95 | } 96 | else 97 | { 98 | /* the children of i (if there were any) are already ordered */ 99 | /* remove i from the stack and order it. Front i is kth front */ 100 | head-- ; 101 | AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; 102 | Order [i] = k++ ; 103 | ASSERT (k <= nn) ; 104 | } 105 | 106 | #ifndef NDEBUG 107 | AMD_DEBUG1 (("\nStack:")) ; 108 | for (h = head ; h >= 0 ; h--) 109 | { 110 | Int j = Stack [h] ; 111 | AMD_DEBUG1 ((" "ID, j)) ; 112 | ASSERT (j >= 0 && j < nn) ; 113 | } 114 | AMD_DEBUG1 (("\n\n")) ; 115 | ASSERT (head < nn) ; 116 | #endif 117 | 118 | } 119 | return (k) ; 120 | } 121 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_preprocess.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === AMD_preprocess ====================================================== */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* Sorts, removes duplicate entries, and transposes from the nonzero pattern of 12 | * a column-form matrix A, to obtain the matrix R. The input matrix can have 13 | * duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be 14 | * AMD_INVALID). 15 | * 16 | * This input condition is NOT checked. This routine is not user-callable. 17 | */ 18 | 19 | #include "amd_internal.h" 20 | 21 | /* ========================================================================= */ 22 | /* === AMD_preprocess ====================================================== */ 23 | /* ========================================================================= */ 24 | 25 | /* AMD_preprocess does not check its input for errors or allocate workspace. 26 | * On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold. 27 | */ 28 | 29 | GLOBAL void AMD_preprocess 30 | ( 31 | Int n, /* input matrix: A is n-by-n */ 32 | const Int Ap [ ], /* size n+1 */ 33 | const Int Ai [ ], /* size nz = Ap [n] */ 34 | 35 | /* output matrix R: */ 36 | Int Rp [ ], /* size n+1 */ 37 | Int Ri [ ], /* size nz (or less, if duplicates present) */ 38 | 39 | Int W [ ], /* workspace of size n */ 40 | Int Flag [ ] /* workspace of size n */ 41 | ) 42 | { 43 | 44 | /* --------------------------------------------------------------------- */ 45 | /* local variables */ 46 | /* --------------------------------------------------------------------- */ 47 | 48 | Int i, j, p, p2 ; 49 | 50 | ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ; 51 | 52 | /* --------------------------------------------------------------------- */ 53 | /* count the entries in each row of A (excluding duplicates) */ 54 | /* --------------------------------------------------------------------- */ 55 | 56 | for (i = 0 ; i < n ; i++) 57 | { 58 | W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ 59 | Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ 60 | } 61 | for (j = 0 ; j < n ; j++) 62 | { 63 | p2 = Ap [j+1] ; 64 | for (p = Ap [j] ; p < p2 ; p++) 65 | { 66 | i = Ai [p] ; 67 | if (Flag [i] != j) 68 | { 69 | /* row index i has not yet appeared in column j */ 70 | W [i]++ ; /* one more entry in row i */ 71 | Flag [i] = j ; /* flag row index i as appearing in col j*/ 72 | } 73 | } 74 | } 75 | 76 | /* --------------------------------------------------------------------- */ 77 | /* compute the row pointers for R */ 78 | /* --------------------------------------------------------------------- */ 79 | 80 | Rp [0] = 0 ; 81 | for (i = 0 ; i < n ; i++) 82 | { 83 | Rp [i+1] = Rp [i] + W [i] ; 84 | } 85 | for (i = 0 ; i < n ; i++) 86 | { 87 | W [i] = Rp [i] ; 88 | Flag [i] = EMPTY ; 89 | } 90 | 91 | /* --------------------------------------------------------------------- */ 92 | /* construct the row form matrix R */ 93 | /* --------------------------------------------------------------------- */ 94 | 95 | /* R = row form of pattern of A */ 96 | for (j = 0 ; j < n ; j++) 97 | { 98 | p2 = Ap [j+1] ; 99 | for (p = Ap [j] ; p < p2 ; p++) 100 | { 101 | i = Ai [p] ; 102 | if (Flag [i] != j) 103 | { 104 | /* row index i has not yet appeared in column j */ 105 | Ri [W [i]++] = j ; /* put col j in row i */ 106 | Flag [i] = j ; /* flag row index i as appearing in col j*/ 107 | } 108 | } 109 | } 110 | 111 | #ifndef NDEBUG 112 | ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ; 113 | for (j = 0 ; j < n ; j++) 114 | { 115 | ASSERT (W [j] == Rp [j+1]) ; 116 | } 117 | #endif 118 | } 119 | -------------------------------------------------------------------------------- /linsys/external/amd/amd_valid.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= */ 2 | /* === AMD_valid =========================================================== */ 3 | /* ========================================================================= */ 4 | 5 | /* ------------------------------------------------------------------------- */ 6 | /* AMD, Copyright (c) Timothy A. Davis, */ 7 | /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 | /* email: DrTimothyAldenDavis@gmail.com */ 9 | /* ------------------------------------------------------------------------- */ 10 | 11 | /* Check if a column-form matrix is valid or not. The matrix A is 12 | * n_row-by-n_col. The row indices of entries in column j are in 13 | * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: 14 | * 15 | * n_row >= 0 16 | * n_col >= 0 17 | * nz = Ap [n_col] >= 0 number of entries in the matrix 18 | * Ap [0] == 0 19 | * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. 20 | * Ai [0 ... nz-1] must be in the range 0 to n_row-1. 21 | * 22 | * If any of the above conditions hold, AMD_INVALID is returned. If the 23 | * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning, 24 | * not an error): 25 | * 26 | * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending 27 | * order, and/or duplicate entries exist. 28 | * 29 | * Otherwise, AMD_OK is returned. 30 | * 31 | * In v1.2 and earlier, this function returned TRUE if the matrix was valid 32 | * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or 33 | * AMD_OK_BUT_JUMBLED). 34 | */ 35 | 36 | #include "amd_internal.h" 37 | 38 | GLOBAL Int AMD_valid 39 | ( 40 | /* inputs, not modified on output: */ 41 | Int n_row, /* A is n_row-by-n_col */ 42 | Int n_col, 43 | const Int Ap [ ], /* column pointers of A, of size n_col+1 */ 44 | const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ 45 | ) 46 | { 47 | Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ; 48 | 49 | if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) 50 | { 51 | return (AMD_INVALID) ; 52 | } 53 | nz = Ap [n_col] ; 54 | if (Ap [0] != 0 || nz < 0) 55 | { 56 | /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ 57 | AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; 58 | return (AMD_INVALID) ; 59 | } 60 | for (j = 0 ; j < n_col ; j++) 61 | { 62 | p1 = Ap [j] ; 63 | p2 = Ap [j+1] ; 64 | AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; 65 | if (p1 > p2) 66 | { 67 | /* column pointers must be ascending */ 68 | AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; 69 | return (AMD_INVALID) ; 70 | } 71 | ilast = EMPTY ; 72 | for (p = p1 ; p < p2 ; p++) 73 | { 74 | i = Ai [p] ; 75 | AMD_DEBUG3 (("row: "ID"\n", i)) ; 76 | if (i < 0 || i >= n_row) 77 | { 78 | /* row index out of range */ 79 | AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); 80 | return (AMD_INVALID) ; 81 | } 82 | if (i <= ilast) 83 | { 84 | /* row index unsorted, or duplicate entry present */ 85 | AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); 86 | result = AMD_OK_BUT_JUMBLED ; 87 | } 88 | ilast = i ; 89 | } 90 | } 91 | return (result) ; 92 | } 93 | -------------------------------------------------------------------------------- /linsys/external/amd/changes: -------------------------------------------------------------------------------- 1 | Flatten out all .c and .h to single dir. 2 | All files: double -> scs_float. 3 | git grep -l 'double' | xargs sed -i 's/double/scs_float/g' 4 | SuiteSparse_config.h: add '#include "scs.h"' 5 | add '#include "ctrlc.h"' 6 | add '#define SuiteSparse_long scs_int' 7 | disable timer #define NTIMER 8 | SuiteSparse_config.c: replace *alloc and printf in 2 structs. 9 | amd_internal.h: remove all refs to long version, int -> scs_int 10 | amd_global.c: add typedef to rm warning 11 | amd.h: int -> scs_int.h 12 | -------------------------------------------------------------------------------- /linsys/external/qdldl/changes: -------------------------------------------------------------------------------- 1 | Last qdldl commit: a00d500906621fbf014b39e42a3304d1143eb65f 2 | 3 | flatten into one dir 4 | create qdldl_types.h from template file 5 | add 'include "glbopts.h"' to qdldl_types.h 6 | manually insert scs types into qdldl_types.h 7 | -------------------------------------------------------------------------------- /linsys/external/qdldl/qdldl_types.h: -------------------------------------------------------------------------------- 1 | #ifndef QDLDL_TYPES_H 2 | # define QDLDL_TYPES_H 3 | 4 | # ifdef __cplusplus 5 | extern "C" { 6 | # endif /* ifdef __cplusplus */ 7 | 8 | #include "glbopts.h" 9 | #include //for the QDLDL_INT_TYPE_MAX 10 | 11 | /* QDLDL integer and float types */ 12 | 13 | #define QDLDL_int scs_int 14 | #define QDLDL_float scs_float 15 | #define QDLDL_bool scs_int 16 | 17 | /* Maximum value of the signed type QDLDL_int */ 18 | #ifdef DLONG 19 | #define QDLDL_INT_MAX LLONG_MAX 20 | #else 21 | #define QDLDL_INT_MAX INT_MAX 22 | #endif 23 | 24 | # ifdef __cplusplus 25 | } 26 | # endif /* ifdef __cplusplus */ 27 | 28 | #endif /* ifndef QDLDL_TYPES_H */ 29 | 30 | -------------------------------------------------------------------------------- /linsys/gpu/gpu.c: -------------------------------------------------------------------------------- 1 | #include "gpu.h" 2 | 3 | void SCS(accum_by_atrans_gpu)(const ScsGpuMatrix *Ag, 4 | const cusparseDnVecDescr_t x, 5 | cusparseDnVecDescr_t y, 6 | cusparseHandle_t cusparse_handle, 7 | size_t *buffer_size, void **buffer) { 8 | /* y += A'*x 9 | x and y MUST be on GPU already 10 | */ 11 | const scs_float onef = 1.0; 12 | size_t new_buffer_size = 0; 13 | 14 | CUSPARSE_GEN(SpMV_bufferSize) 15 | (cusparse_handle, CUSPARSE_OPERATION_NON_TRANSPOSE, &onef, Ag->descr, x, 16 | &onef, y, SCS_CUDA_FLOAT, SCS_CSRMV_ALG, &new_buffer_size); 17 | 18 | if (new_buffer_size > *buffer_size) { 19 | if (*buffer != SCS_NULL) { 20 | cudaFree(*buffer); 21 | } 22 | cudaMalloc(buffer, new_buffer_size); 23 | *buffer_size = new_buffer_size; 24 | } 25 | 26 | CUSPARSE_GEN(SpMV) 27 | (cusparse_handle, CUSPARSE_OPERATION_NON_TRANSPOSE, &onef, Ag->descr, x, 28 | &onef, y, SCS_CUDA_FLOAT, SCS_CSRMV_ALG, *buffer); 29 | } 30 | 31 | /* this is slow, use trans routine if possible */ 32 | void SCS(accum_by_a_gpu)(const ScsGpuMatrix *Ag, const cusparseDnVecDescr_t x, 33 | cusparseDnVecDescr_t y, 34 | cusparseHandle_t cusparse_handle, size_t *buffer_size, 35 | void **buffer) { 36 | /* y += A*x 37 | x and y MUST be on GPU already 38 | */ 39 | const scs_float onef = 1.0; 40 | size_t new_buffer_size = 0; 41 | 42 | /* The A matrix idx pointers must be ORDERED */ 43 | CUSPARSE_GEN(SpMV_bufferSize) 44 | (cusparse_handle, CUSPARSE_OPERATION_TRANSPOSE, &onef, Ag->descr, x, &onef, y, 45 | SCS_CUDA_FLOAT, SCS_CSRMV_ALG, &new_buffer_size); 46 | 47 | if (new_buffer_size > *buffer_size) { 48 | if (*buffer != SCS_NULL) { 49 | cudaFree(*buffer); 50 | } 51 | cudaMalloc(buffer, new_buffer_size); 52 | *buffer_size = new_buffer_size; 53 | } 54 | 55 | CUSPARSE_GEN(SpMV) 56 | (cusparse_handle, CUSPARSE_OPERATION_TRANSPOSE, &onef, Ag->descr, x, &onef, y, 57 | SCS_CUDA_FLOAT, SCS_CSRMV_ALG, *buffer); 58 | } 59 | 60 | /* This assumes that P has been made full (ie not triangular) and uses the 61 | * fact that the GPU is faster for general sparse matrices than for symmetric 62 | */ 63 | /* y += P*x 64 | x and y MUST be on GPU already 65 | */ 66 | void SCS(accum_by_p_gpu)(const ScsGpuMatrix *Pg, const cusparseDnVecDescr_t x, 67 | cusparseDnVecDescr_t y, 68 | cusparseHandle_t cusparse_handle, size_t *buffer_size, 69 | void **buffer) { 70 | SCS(accum_by_atrans_gpu)(Pg, x, y, cusparse_handle, buffer_size, buffer); 71 | } 72 | 73 | void SCS(free_gpu_matrix)(ScsGpuMatrix *A) { 74 | cudaFree(A->x); 75 | cudaFree(A->i); 76 | cudaFree(A->p); 77 | cusparseDestroySpMat(A->descr); 78 | } 79 | -------------------------------------------------------------------------------- /linsys/gpu/gpu.h: -------------------------------------------------------------------------------- 1 | #ifndef SCS_GPU_H_GUARD 2 | #define SCS_GPU_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* TODO: Do we need this? 9 | 10 | #include 11 | 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "glbopts.h" 19 | #include "linalg.h" 20 | #include "linsys.h" 21 | #include "scs.h" 22 | #include "scs_matrix.h" 23 | #include "util.h" 24 | 25 | #define CUDA_CHECK_ERR \ 26 | do { \ 27 | cudaDeviceSynchronize(); \ 28 | cudaError_t err = cudaGetLastError(); \ 29 | if (err != cudaSuccess) { \ 30 | scs_printf("%s:%d:%s\n ERROR_CUDA (#): %s\n", __FILE__, __LINE__, \ 31 | __func__, cudaGetErrorString(err)); \ 32 | } \ 33 | } while (0) 34 | 35 | #if VERBOSITY == 0 36 | #ifndef SFLOAT 37 | #define CUBLAS(x) cublasD##x 38 | #define CUBLASI(x) cublasId##x 39 | #else 40 | #define CUBLAS(x) cublasS##x 41 | #define CUBLASI(x) cublasIs##x 42 | #endif 43 | #define CUSPARSE_GEN(x) cusparse##x 44 | #else 45 | #ifndef SFLOAT 46 | #define CUBLAS(x) \ 47 | CUDA_CHECK_ERR; \ 48 | cublasD##x 49 | #define CUBLASI(x) \ 50 | CUDA_CHECK_ERR; \ 51 | cublasId##x 52 | #else 53 | #define CUBLAS(x) \ 54 | CUDA_CHECK_ERR; \ 55 | cublasS##x 56 | #define CUBLASI(x) \ 57 | CUDA_CHECK_ERR; \ 58 | cublasIs##x 59 | #endif 60 | #define CUSPARSE_GEN(x) \ 61 | CUDA_CHECK_ERR; \ 62 | cusparse##x 63 | #endif 64 | 65 | #ifndef SFLOAT 66 | #define SCS_CUDA_FLOAT CUDA_R_64F 67 | #else 68 | #define SCS_CUDA_FLOAT CUDA_R_32F 69 | #endif 70 | 71 | #ifndef DLONG 72 | #define SCS_CUSPARSE_INDEX CUSPARSE_INDEX_32I 73 | #else 74 | #define SCS_CUSPARSE_INDEX CUSPARSE_INDEX_64I 75 | #endif 76 | 77 | #define SCS_CSRMV_ALG CUSPARSE_SPMV_CSR_ALG1 78 | #define SCS_CSR2CSC_ALG CUSPARSE_CSR2CSC_ALG1 79 | 80 | /* 81 | CUDA matrix routines only for CSR, not CSC matrices: 82 | CSC CSR GPU Mult 83 | A (m x n) A' (n x m) Ag accum_by_a_trans_gpu 84 | A'(n x m) A (m x n) Agt accum_by_a_gpu 85 | */ 86 | 87 | /* this struct defines the data matrix on GPU */ 88 | typedef struct SCS_GPU_DATA_MATRIX { 89 | /* A is supplied in column compressed format */ 90 | scs_float *x; /* values, size: NNZ */ 91 | scs_int *i; /* row index, size: NNZ */ 92 | scs_int *p; /* column pointer, size: n+1 */ 93 | scs_int m, n; /* m rows, n cols */ 94 | scs_int nnz; /* num non-zeros in matrix */ 95 | /* CUDA */ 96 | cusparseSpMatDescr_t descr; 97 | } ScsGpuMatrix; 98 | 99 | void SCS(accum_by_atrans_gpu)(const ScsGpuMatrix *A, 100 | const cusparseDnVecDescr_t x, 101 | cusparseDnVecDescr_t y, 102 | cusparseHandle_t cusparse_handle, 103 | size_t *buffer_size, void **buffer); 104 | 105 | void SCS(accum_by_a_gpu)(const ScsGpuMatrix *A, const cusparseDnVecDescr_t x, 106 | cusparseDnVecDescr_t y, 107 | cusparseHandle_t cusparse_handle, size_t *buffer_size, 108 | void **buffer); 109 | 110 | void SCS(accum_by_p_gpu)(const ScsGpuMatrix *P, const cusparseDnVecDescr_t x, 111 | cusparseDnVecDescr_t y, 112 | cusparseHandle_t cusparse_handle, size_t *buffer_size, 113 | void **buffer); 114 | 115 | void SCS(free_gpu_matrix)(ScsGpuMatrix *A); 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | #endif 121 | -------------------------------------------------------------------------------- /linsys/gpu/indirect/private.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIV_H_GUARD 2 | #define PRIV_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "csparse.h" 9 | #include "glbopts.h" 10 | #include "gpu.h" 11 | #include "linalg.h" 12 | #include "scs.h" 13 | 14 | struct SCS_LIN_SYS_WORK { 15 | scs_int n, m; /* linear system dimensions */ 16 | /* reporting */ 17 | scs_int tot_cg_its; 18 | scs_float *M; /* preconditioner on cpu */ 19 | /* ALL BELOW HOSTED ON THE GPU */ 20 | scs_float *p; /* cg iterate, n */ 21 | scs_float *r; /* cg residual, n */ 22 | scs_float *Gp; /* G * p, n */ 23 | scs_float *bg; /* b, n */ 24 | scs_float *tmp_m; /* m, used in mat_vec */ 25 | scs_float *z; /* preconditioned */ 26 | scs_float *M_gpu; /* preconditioner */ 27 | const ScsMatrix *A; /* does *not* own this memory */ 28 | const ScsMatrix *P; /* does *not* own this memory */ 29 | ScsGpuMatrix *Ag; /* A matrix on GPU */ 30 | ScsGpuMatrix *Agt; /* A trans matrix on GPU */ 31 | ScsGpuMatrix *Pg; /* P matrix on GPU */ 32 | /* CUDA */ 33 | cublasHandle_t cublas_handle; 34 | cusparseHandle_t cusparse_handle; 35 | /* CUSPARSE */ 36 | size_t buffer_size; 37 | void *buffer; 38 | cusparseDnVecDescr_t dn_vec_m; /* Dense vector of length m */ 39 | cusparseDnVecDescr_t dn_vec_n; /* Dense vector of length n */ 40 | cusparseDnVecDescr_t dn_vec_n_p; /* Dense vector of length n */ 41 | 42 | /* rho terms */ 43 | scs_float *r_x_gpu; 44 | scs_float *inv_r_y; /* inverse R_y */ 45 | scs_float *inv_r_y_gpu; /* inverse R_y on GPU */ 46 | }; 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | #endif 52 | -------------------------------------------------------------------------------- /linsys/mkl/direct/private.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIV_H_GUARD 2 | #define PRIV_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "csparse.h" 9 | #include "linsys.h" 10 | 11 | struct SCS_LIN_SYS_WORK { 12 | ScsMatrix *kkt; /* Upper triangular KKT matrix (in CSR format) */ 13 | scs_float *sol; /* solution to the KKT system */ 14 | scs_int n; /* number of QP variables */ 15 | scs_int m; /* number of QP constraints */ 16 | 17 | /* Pardiso variables */ 18 | void *pt[64]; /* internal solver memory pointer pt */ 19 | scs_int iparm[64]; /* Pardiso control parameters */ 20 | scs_int n_plus_m; /* dimension of the linear system */ 21 | scs_int mtype; /* matrix type (-2 for real and symmetric indefinite) */ 22 | scs_int nrhs; /* number of right-hand sides (1) */ 23 | scs_int maxfct; /* maximum number of factors (1) */ 24 | scs_int mnum; /* indicates matrix for the solution phase (1) */ 25 | scs_int phase; /* control the execution phases of the solver */ 26 | scs_int error; /* the error indicator (0 for no error) */ 27 | scs_int msglvl; /* Message level information (0 for no output) */ 28 | 29 | /* These are required for matrix updates */ 30 | scs_int *diag_r_idxs; /* indices where R appears */ 31 | scs_float *diag_p; /* Diagonal values of P */ 32 | }; 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /linsys/scs_matrix.h: -------------------------------------------------------------------------------- 1 | #ifndef SCS_MATRIX_H_GUARD 2 | #define SCS_MATRIX_H_GUARD 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "glbopts.h" 9 | #include "scs.h" 10 | #include "scs_work.h" 11 | 12 | /* Normalization routines, used if d->NORMALIZE is true */ 13 | /* normalizes A matrix, sets scal->E and scal->D diagonal scaling matrices, 14 | * A -> D*A*E. D and E must be all positive entries, D must satisfy cone 15 | * boundaries */ 16 | ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, ScsConeWork *cone); 17 | 18 | /* unnormalizes A matrix, unnormalizes by w->D and w->E */ 19 | /* void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling 20 | * *scal); 21 | */ 22 | 23 | /* to free the memory allocated in a ScsMatrix (called on A and P at finish) */ 24 | void SCS(free_scs_matrix)(ScsMatrix *A); 25 | 26 | /* copies A (instead of in-place normalization), returns 0 for failure, 27 | * allocates memory for dstp */ 28 | scs_int SCS(copy_matrix)(ScsMatrix **dstp, const ScsMatrix *src); 29 | 30 | scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n); 31 | 32 | /** 33 | * Validate the linear system inputs, returns < 0 if not valid inputs. 34 | * 35 | * @param A A data matrix 36 | * @param P P data matrix 37 | * @return status < 0 indicates failure 38 | */ 39 | scs_int SCS(validate_lin_sys)(const ScsMatrix *A, const ScsMatrix *P); 40 | 41 | /** 42 | * Forms y += A^T * x 43 | * 44 | * @param A A data matrix 45 | * @param x Input 46 | * @param y Output 47 | */ 48 | void SCS(accum_by_atrans)(const ScsMatrix *A, const scs_float *x, scs_float *y); 49 | 50 | /** 51 | * Forms y += A * x 52 | * 53 | * @param A Data matrix 54 | * @param x Input 55 | * @param y Output 56 | */ 57 | void SCS(accum_by_a)(const ScsMatrix *A, const scs_float *x, scs_float *y); 58 | 59 | /** 60 | * Forms y += P * x 61 | * 62 | * @param P P data matrix 63 | * @param x Input 64 | * @param y Output 65 | */ 66 | void SCS(accum_by_p)(const ScsMatrix *P, const scs_float *x, scs_float *y); 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | #endif 72 | -------------------------------------------------------------------------------- /src/ctrlc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Implements signal handling (ctrl-c) for SCS. 3 | * 4 | * Under Windows, we use SetConsoleCtrlHandler. 5 | * Under Unix systems, we use sigaction. 6 | * For Mex files, we use utSetInterruptEnabled/utIsInterruptPending. 7 | * 8 | */ 9 | 10 | #include "ctrlc.h" 11 | 12 | #if CTRLC > 0 13 | 14 | #ifdef MATLAB_MEX_FILE 15 | #include 16 | 17 | extern bool utIsInterruptPending(void); 18 | extern bool utSetInterruptEnabled(bool); 19 | 20 | static int istate; 21 | void scs_start_interrupt_listener(void) { 22 | istate = (int)utSetInterruptEnabled(true); 23 | } 24 | 25 | void scs_end_interrupt_listener(void) { 26 | utSetInterruptEnabled((bool)istate); 27 | } 28 | 29 | int scs_is_interrupted(void) { 30 | return (int)utIsInterruptPending(); 31 | } 32 | 33 | #elif (defined _WIN32 || _WIN64 || defined _WINDLL) 34 | #include 35 | 36 | static int int_detected; 37 | static BOOL WINAPI scs_handle_ctrlc(DWORD dwCtrlType) { 38 | if (dwCtrlType != CTRL_C_EVENT) { 39 | return FALSE; 40 | } 41 | int_detected = 1; 42 | return TRUE; 43 | } 44 | 45 | void scs_start_interrupt_listener(void) { 46 | int_detected = 0; 47 | SetConsoleCtrlHandler(scs_handle_ctrlc, TRUE); 48 | } 49 | 50 | void scs_end_interrupt_listener(void) { 51 | SetConsoleCtrlHandler(scs_handle_ctrlc, FALSE); 52 | } 53 | 54 | int scs_is_interrupted(void) { 55 | return int_detected; 56 | } 57 | 58 | #else /* Unix */ 59 | 60 | #include 61 | static int int_detected; 62 | struct sigaction oact; 63 | static void scs_handle_ctrlc(int dummy) { 64 | int_detected = dummy ? dummy : -1; 65 | } 66 | 67 | void scs_start_interrupt_listener(void) { 68 | struct sigaction act; 69 | int_detected = 0; 70 | act.sa_flags = 0; 71 | sigemptyset(&act.sa_mask); 72 | act.sa_handler = scs_handle_ctrlc; 73 | sigaction(SIGINT, &act, &oact); 74 | } 75 | 76 | void scs_end_interrupt_listener(void) { 77 | struct sigaction act; 78 | sigaction(SIGINT, &oact, &act); 79 | } 80 | 81 | int scs_is_interrupted(void) { 82 | return int_detected; 83 | } 84 | 85 | #endif /* END IF MATLAB_MEX_FILE / WIN32 */ 86 | 87 | #endif /* END IF CTRLC > 0 */ 88 | -------------------------------------------------------------------------------- /src/normalize.c: -------------------------------------------------------------------------------- 1 | #include "normalize.h" 2 | 3 | #include "linalg.h" 4 | #include "scs.h" 5 | 6 | /* copied from linsys/scs_matrix.c */ 7 | #define MIN_NORMALIZATION_FACTOR (1e-4) 8 | #define MAX_NORMALIZATION_FACTOR (1e4) 9 | 10 | /* Given D, E in scaling normalize b, c and compute primal / dual scales. 11 | * 12 | * Recall that the normalization routine is performing: 13 | * 14 | * [P A' c] with [E 0 0] on both sides (D, E diagonal) 15 | * [A 0 b] [0 D 0] 16 | * [c' b' 0] [0 0 s] 17 | * 18 | * which results in: 19 | * 20 | * [ EPE EA'D sEc ] 21 | * [ DAE 0 sDb ] 22 | * [ sc'E sb'D 0 ] 23 | * 24 | * `s` is incorporated into dual_scale and primal_scale 25 | * 26 | */ 27 | void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) { 28 | scs_int i; 29 | scs_float sigma, nm_c, nm_b; 30 | 31 | /* scale c */ 32 | for (i = 0; i < scal->n; ++i) { 33 | c[i] *= scal->E[i]; 34 | } 35 | /* scale b */ 36 | for (i = 0; i < scal->m; ++i) { 37 | b[i] *= scal->D[i]; 38 | } 39 | 40 | /* calculate primal and dual scales */ 41 | nm_c = SCS(norm_inf)(c, scal->n); 42 | nm_b = SCS(norm_inf)(b, scal->m); 43 | sigma = MAX(nm_c, nm_b); 44 | sigma = sigma < MIN_NORMALIZATION_FACTOR ? 1.0 : sigma; 45 | sigma = sigma > MAX_NORMALIZATION_FACTOR ? MAX_NORMALIZATION_FACTOR : sigma; 46 | sigma = SAFEDIV_POS(1.0, sigma); 47 | 48 | /* Scale b, c */ 49 | SCS(scale_array)(c, sigma, scal->n); 50 | SCS(scale_array)(b, sigma, scal->m); 51 | 52 | /* We assume that primal_scale = dual_scale, otherwise need to refactorize */ 53 | scal->primal_scale = sigma; 54 | scal->dual_scale = sigma; 55 | } 56 | 57 | /* needed for normalizing the warm-start */ 58 | void SCS(normalize_sol)(ScsScaling *scal, ScsSolution *sol) { 59 | scs_int i; 60 | scs_float *D = scal->D; 61 | scs_float *E = scal->E; 62 | for (i = 0; i < scal->n; ++i) { 63 | sol->x[i] /= (E[i] / scal->dual_scale); 64 | } 65 | for (i = 0; i < scal->m; ++i) { 66 | sol->y[i] /= (D[i] / scal->primal_scale); 67 | } 68 | for (i = 0; i < scal->m; ++i) { 69 | sol->s[i] *= (D[i] * scal->dual_scale); 70 | } 71 | } 72 | 73 | void SCS(un_normalize_sol)(ScsScaling *scal, ScsSolution *sol) { 74 | scs_int i; 75 | scs_float *D = scal->D; 76 | scs_float *E = scal->E; 77 | for (i = 0; i < scal->n; ++i) { 78 | sol->x[i] *= (E[i] / scal->dual_scale); 79 | } 80 | for (i = 0; i < scal->m; ++i) { 81 | sol->y[i] *= (D[i] / scal->primal_scale); 82 | } 83 | for (i = 0; i < scal->m; ++i) { 84 | sol->s[i] /= (D[i] * scal->dual_scale); 85 | } 86 | } 87 | 88 | void SCS(un_normalize_primal)(ScsScaling *scal, scs_float *r) { 89 | scs_int i; 90 | scs_float *D = scal->D; 91 | for (i = 0; i < scal->m; ++i) { 92 | r[i] /= (D[i] * scal->dual_scale); 93 | } 94 | } 95 | 96 | void SCS(un_normalize_dual)(ScsScaling *scal, scs_float *r) { 97 | scs_int i; 98 | scs_float *E = scal->E; 99 | for (i = 0; i < scal->n; ++i) { 100 | r[i] /= (E[i] * scal->primal_scale); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/scs_version.c: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | #include "glbopts.h" 6 | 7 | const char *scs_version(void) { 8 | return SCS_VERSION; 9 | } 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | #include "glbopts.h" 4 | #include "linsys.h" 5 | #include "scs_matrix.h" 6 | 7 | /* return milli-seconds */ 8 | #if (defined NO_TIMER) 9 | 10 | void SCS(tic)(SCS(timer) * t) { 11 | } 12 | scs_float SCS(tocq)(SCS(timer) * t) { 13 | return NAN; 14 | } 15 | 16 | #elif (defined _WIN32 || _WIN64 || defined _WINDLL) 17 | 18 | void SCS(tic)(SCS(timer) * t) { 19 | QueryPerformanceFrequency(&t->freq); 20 | QueryPerformanceCounter(&t->tic); 21 | } 22 | 23 | scs_float SCS(tocq)(SCS(timer) * t) { 24 | QueryPerformanceCounter(&t->toc); 25 | return (1e3 * (t->toc.QuadPart - t->tic.QuadPart) / 26 | (scs_float)t->freq.QuadPart); 27 | } 28 | 29 | #elif (defined __APPLE__) 30 | #include 31 | 32 | void SCS(tic)(SCS(timer) * t) { 33 | /* read current clock cycles */ 34 | t->tic = mach_absolute_time(); 35 | } 36 | 37 | scs_float SCS(tocq)(SCS(timer) * t) { 38 | uint64_t duration; /* elapsed time in clock cycles*/ 39 | 40 | t->toc = mach_absolute_time(); 41 | duration = t->toc - t->tic; 42 | 43 | /*conversion from clock cycles to nanoseconds*/ 44 | mach_timebase_info(&(t->tinfo)); 45 | duration *= t->tinfo.numer; 46 | duration /= t->tinfo.denom; 47 | 48 | return (scs_float)duration / 1e6; 49 | } 50 | 51 | #else 52 | 53 | void SCS(tic)(SCS(timer) * t) { 54 | clock_gettime(CLOCK_MONOTONIC, &t->tic); 55 | } 56 | 57 | scs_float SCS(tocq)(SCS(timer) * t) { 58 | struct timespec temp; 59 | 60 | clock_gettime(CLOCK_MONOTONIC, &t->toc); 61 | 62 | if ((t->toc.tv_nsec - t->tic.tv_nsec) < 0) { 63 | temp.tv_sec = t->toc.tv_sec - t->tic.tv_sec - 1; 64 | temp.tv_nsec = 1e9 + t->toc.tv_nsec - t->tic.tv_nsec; 65 | } else { 66 | temp.tv_sec = t->toc.tv_sec - t->tic.tv_sec; 67 | temp.tv_nsec = t->toc.tv_nsec - t->tic.tv_nsec; 68 | } 69 | return (scs_float)temp.tv_sec * 1e3 + (scs_float)temp.tv_nsec / 1e6; 70 | } 71 | 72 | #endif 73 | 74 | void SCS(deep_copy_data)(ScsData *dest, const ScsData *src) { 75 | dest->n = src->n; 76 | dest->m = src->m; 77 | SCS(copy_matrix)(&(dest->A), src->A); 78 | SCS(copy_matrix)(&(dest->P), src->P); 79 | dest->b = (scs_float *)scs_calloc(dest->m, sizeof(scs_float)); 80 | memcpy(dest->b, src->b, dest->m * sizeof(scs_float)); 81 | dest->c = (scs_float *)scs_calloc(dest->n, sizeof(scs_float)); 82 | memcpy(dest->c, src->c, dest->n * sizeof(scs_float)); 83 | } 84 | 85 | void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) { 86 | memcpy(dest, src, sizeof(ScsSettings)); 87 | /* MATLAB does something weird with strdup, so use strcpy instead */ 88 | char *tmp; 89 | if (src->write_data_filename) { 90 | /* sizeof(char) = 1 */ 91 | tmp = (char *)scs_malloc(strlen(src->write_data_filename) + 1); 92 | strcpy(tmp, src->write_data_filename); 93 | dest->write_data_filename = tmp; 94 | } else { 95 | dest->write_data_filename = SCS_NULL; 96 | } 97 | /* MATLAB does something weird with strdup, so use strcpy instead */ 98 | if (src->log_csv_filename) { 99 | /* sizeof(char) = 1 */ 100 | tmp = (char *)scs_malloc(strlen(src->log_csv_filename) + 1); 101 | strcpy(tmp, src->log_csv_filename); 102 | dest->log_csv_filename = tmp; 103 | } else { 104 | dest->log_csv_filename = SCS_NULL; 105 | } 106 | } 107 | 108 | void SCS(free_data)(ScsData *d) { 109 | if (d) { 110 | scs_free(d->b); 111 | scs_free(d->c); 112 | if (d->A) { 113 | SCS(free_scs_matrix)(d->A); 114 | } 115 | if (d->P) { 116 | SCS(free_scs_matrix)(d->P); 117 | } 118 | scs_free(d); 119 | } 120 | } 121 | 122 | void SCS(free_sol)(ScsSolution *sol) { 123 | if (sol) { 124 | scs_free(sol->x); 125 | scs_free(sol->y); 126 | scs_free(sol->s); 127 | scs_free(sol); 128 | } 129 | } 130 | 131 | /* assumes stgs already allocated memory */ 132 | void scs_set_default_settings(ScsSettings *stgs) { 133 | /* These constants are defined in include/glbopts.h */ 134 | stgs->max_iters = MAX_ITERS; 135 | stgs->eps_abs = EPS_ABS; 136 | stgs->eps_rel = EPS_REL; 137 | stgs->eps_infeas = EPS_INFEAS; 138 | stgs->alpha = ALPHA; 139 | stgs->rho_x = RHO_X; 140 | stgs->scale = SCALE; 141 | stgs->verbose = VERBOSE; 142 | stgs->normalize = NORMALIZE; 143 | stgs->warm_start = WARM_START; 144 | stgs->acceleration_lookback = ACCELERATION_LOOKBACK; 145 | stgs->acceleration_interval = ACCELERATION_INTERVAL; 146 | stgs->adaptive_scale = ADAPTIVE_SCALE; 147 | stgs->write_data_filename = WRITE_DATA_FILENAME; 148 | stgs->log_csv_filename = LOG_CSV_FILENAME; 149 | stgs->time_limit_secs = TIME_LIMIT_SECS; 150 | } 151 | -------------------------------------------------------------------------------- /test/minunit.h: -------------------------------------------------------------------------------- 1 | /* Taken from http://www.jera.com/techinfo/jtns/jtn002.html */ 2 | 3 | /* Simple Macros for testing */ 4 | #define mu_assert_less(message, a, b) \ 5 | do { \ 6 | if (a > b) { \ 7 | scs_printf("%s: %1.3e > %1.3e\n", message, a, b); \ 8 | return message; \ 9 | } \ 10 | } while (0) 11 | 12 | #define mu_assert(message, test) \ 13 | do { \ 14 | if (!(test)) \ 15 | return message; \ 16 | } while (0) 17 | 18 | #define mu_run_test(test) _mu_run_test(#test, test) 19 | 20 | #define _mu_run_test(name, test) \ 21 | do { \ 22 | scs_printf("*********************************************************\n"); \ 23 | scs_printf("Running test: %s\n", name); \ 24 | const char *message = test(); \ 25 | tests_run++; \ 26 | if (message) \ 27 | return message; \ 28 | } while (0) 29 | -------------------------------------------------------------------------------- /test/problems/degenerate.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "problem_utils.h" 5 | #include "scs.h" 6 | #include "scs_matrix.h" 7 | #include "util.h" 8 | 9 | /* test degenerate cones */ 10 | static const char *degenerate(void) { 11 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 12 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 13 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 14 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 15 | ScsInfo info = {0}; 16 | scs_int exitflag, success; 17 | scs_float tpobj, tdobj, perr, derr; 18 | const char *fail; 19 | 20 | /* data */ 21 | scs_float Ax[] = {-10., -1., 1., -1.}; 22 | scs_int Ai[] = {1, 2, 1, 3}; 23 | scs_int Ap[] = {0, 2, 4}; 24 | 25 | scs_float Px[] = {0.02, 2.}; 26 | scs_int Pi[] = {0, 1}; 27 | scs_int Pp[] = {0, 1, 2}; 28 | 29 | scs_float b[] = {1., -1., 2., -0.5}; 30 | scs_float c[] = {1., 2.}; 31 | 32 | scs_int m = 4; 33 | scs_int n = 2; 34 | 35 | /* used later: */ 36 | scs_int sq[] = {1}; 37 | 38 | /* end data */ 39 | 40 | d->m = m; 41 | d->n = n; 42 | d->b = b; 43 | d->c = c; 44 | 45 | d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 46 | d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 47 | 48 | d->A->m = m; 49 | d->A->n = n; 50 | 51 | d->A->x = Ax; 52 | d->A->i = Ai; 53 | d->A->p = Ap; 54 | 55 | d->P->m = n; 56 | d->P->n = n; 57 | 58 | d->P->x = Px; 59 | d->P->i = Pi; 60 | d->P->p = Pp; 61 | 62 | scs_set_default_settings(stgs); 63 | stgs->eps_abs = 1e-6; 64 | stgs->eps_rel = 1e-6; 65 | stgs->eps_infeas = 1e-9; 66 | 67 | /* positive orthants */ 68 | k->l = 4; 69 | exitflag = scs(d, k, stgs, sol, &info); 70 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 71 | if (fail) { 72 | return fail; 73 | } 74 | mu_assert("bsize: SCS failed to produce outputflag SCS_SOLVED", 75 | exitflag == SCS_SOLVED); 76 | 77 | tpobj = info.pobj; 78 | tdobj = info.dobj; 79 | 80 | /* degenerate box cone */ 81 | k->bsize = 1; 82 | k->l = 3; 83 | exitflag = scs(d, k, stgs, sol, &info); 84 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 85 | if (fail) { 86 | return fail; 87 | } 88 | perr = info.pobj - tpobj; 89 | derr = info.dobj - tdobj; 90 | success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED; 91 | mu_assert("degenerate box cone failure", success); 92 | 93 | /* degenerate SOC cone */ 94 | k->bsize = 0; 95 | k->q = sq; 96 | k->qsize = 1; 97 | k->l = 3; 98 | exitflag = scs(d, k, stgs, sol, &info); 99 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 100 | if (fail) { 101 | return fail; 102 | } 103 | perr = info.pobj - tpobj; 104 | derr = info.dobj - tdobj; 105 | success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED; 106 | mu_assert("degenerate SOC cone failure", success); 107 | 108 | /* degenerate PSD cone */ 109 | k->q = 0; 110 | k->qsize = 0; 111 | k->s = sq; 112 | k->ssize = 1; 113 | k->l = 3; 114 | exitflag = scs(d, k, stgs, sol, &info); 115 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 116 | if (fail) { 117 | return fail; 118 | } 119 | perr = info.pobj - tpobj; 120 | derr = info.dobj - tdobj; 121 | success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED; 122 | mu_assert("degenerate PSD cone failure", success); 123 | 124 | SCS(free_sol)(sol); 125 | scs_free(d->A); 126 | scs_free(d->P); 127 | scs_free(k); 128 | scs_free(stgs); 129 | scs_free(d); 130 | return fail; 131 | } 132 | -------------------------------------------------------------------------------- /test/problems/hs21_tiny_qp.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "problem_utils.h" 5 | #include "scs.h" 6 | #include "scs_matrix.h" 7 | #include "util.h" 8 | 9 | static const char *hs21_tiny_qp(void) { 10 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 11 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 12 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 13 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 14 | ScsInfo info = {0}; 15 | scs_int exitflag; 16 | scs_float perr, derr; 17 | scs_int success; 18 | const char *fail; 19 | 20 | /* data */ 21 | scs_float Ax[] = {-10., -1., 1., -1.}; 22 | scs_int Ai[] = {1, 2, 1, 3}; 23 | scs_int Ap[] = {0, 2, 4}; 24 | 25 | scs_float Px[] = {0.02, 2.}; 26 | scs_int Pi[] = {0, 1}; 27 | scs_int Pp[] = {0, 1, 2}; 28 | 29 | scs_float b[] = {1., 0., 0., 0.}; 30 | scs_float c[] = {0., 0.}; 31 | 32 | scs_int m = 4; 33 | scs_int n = 2; 34 | 35 | scs_float bl[] = {10.0, 2.0, -50.0}; 36 | scs_float bu[] = {1e+20, 50.0, 50.0}; 37 | scs_int bsize = 4; 38 | 39 | scs_float opt = 0.04000000000000625; 40 | /* end data */ 41 | 42 | d->m = m; 43 | d->n = n; 44 | d->b = b; 45 | d->c = c; 46 | 47 | d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 48 | d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 49 | 50 | d->A->m = m; 51 | d->A->n = n; 52 | 53 | d->A->x = Ax; 54 | d->A->i = Ai; 55 | d->A->p = Ap; 56 | 57 | d->P->m = n; 58 | d->P->n = n; 59 | 60 | d->P->x = Px; 61 | d->P->i = Pi; 62 | d->P->p = Pp; 63 | 64 | k->bsize = bsize; 65 | k->bl = bl; 66 | k->bu = bu; 67 | 68 | scs_set_default_settings(stgs); 69 | stgs->eps_abs = 1e-6; 70 | stgs->eps_rel = 1e-6; 71 | stgs->eps_infeas = 0.; /* disable due to gpu test finding cert */ 72 | 73 | exitflag = scs(d, k, stgs, sol, &info); 74 | 75 | perr = info.pobj - opt; 76 | derr = info.dobj - opt; 77 | 78 | scs_printf("primal obj error %4e\n", perr); 79 | scs_printf("dual obj error %4e\n", derr); 80 | 81 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 82 | 83 | mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED", 84 | success); 85 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 86 | 87 | /* test warm-starting */ 88 | stgs->warm_start = 1; 89 | exitflag = scs(d, k, stgs, sol, &info); 90 | /* 25 iters should be enough if warm-started */ 91 | mu_assert("hs21_tiny_qp: warm-start failure", info.iter <= 25); 92 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 93 | 94 | mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED", 95 | success); 96 | 97 | /* test other settings */ 98 | stgs->warm_start = 0; 99 | stgs->normalize = 0; 100 | stgs->adaptive_scale = 0; 101 | stgs->acceleration_lookback = 10; 102 | stgs->acceleration_interval = 10; 103 | stgs->log_csv_filename = "hs21_tiny_qp.csv"; 104 | 105 | exitflag = scs(d, k, stgs, sol, &info); 106 | 107 | perr = info.pobj - opt; 108 | derr = info.dobj - opt; 109 | 110 | scs_printf("primal obj error %4e\n", perr); 111 | scs_printf("dual obj error %4e\n", derr); 112 | 113 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 114 | 115 | mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED", 116 | success); 117 | 118 | SCS(free_sol)(sol); 119 | scs_free(d->A); 120 | scs_free(d->P); 121 | scs_free(k); 122 | scs_free(stgs); 123 | scs_free(d); 124 | return fail; 125 | } 126 | -------------------------------------------------------------------------------- /test/problems/hs21_tiny_qp_rw.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "problem_utils.h" 5 | #include "rw.h" 6 | #include "scs.h" 7 | #include "scs_matrix.h" 8 | #include "util.h" 9 | 10 | /* test read / write logic */ 11 | static const char *hs21_tiny_qp_rw(void) { 12 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 13 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 14 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 15 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 16 | ScsInfo info = {0}; 17 | scs_int exitflag; 18 | scs_float perr, derr; 19 | scs_int success, read_status; 20 | const char *fail; 21 | 22 | /* data */ 23 | scs_float Ax[] = {-10., -1., 1., -1.}; 24 | scs_int Ai[] = {1, 2, 1, 3}; 25 | scs_int Ap[] = {0, 2, 4}; 26 | 27 | scs_float Px[] = {0.02, 2.}; 28 | scs_int Pi[] = {0, 1}; 29 | scs_int Pp[] = {0, 1, 2}; 30 | 31 | scs_float b[] = {1., 0., 0., 0.}; 32 | scs_float c[] = {0., 0.}; 33 | 34 | scs_int m = 4; 35 | scs_int n = 2; 36 | 37 | scs_float bl[] = {10.0, 2.0, -50.0}; 38 | scs_float bu[] = {1e+20, 50.0, 50.0}; 39 | scs_int bsize = 4; 40 | 41 | scs_float opt = 0.04000000000000625; 42 | /* end data */ 43 | 44 | d->m = m; 45 | d->n = n; 46 | d->b = b; 47 | d->c = c; 48 | 49 | d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 50 | d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 51 | 52 | d->A->m = m; 53 | d->A->n = n; 54 | 55 | d->A->x = Ax; 56 | d->A->i = Ai; 57 | d->A->p = Ap; 58 | 59 | d->P->m = n; 60 | d->P->n = n; 61 | 62 | d->P->x = Px; 63 | d->P->i = Pi; 64 | d->P->p = Pp; 65 | 66 | k->bsize = bsize; 67 | k->bl = bl; 68 | k->bu = bu; 69 | 70 | scs_set_default_settings(stgs); 71 | stgs->eps_abs = 1e-6; 72 | stgs->eps_rel = 1e-6; 73 | stgs->eps_infeas = 0.; /* disable due to gpu test finding cert */ 74 | 75 | stgs->write_data_filename = "hs21_tiny_qp"; 76 | stgs->max_iters = 1; 77 | 78 | exitflag = scs(d, k, stgs, sol, &info); 79 | 80 | /* kill the data */ 81 | scs_free(d->A); 82 | scs_free(d->P); 83 | scs_free(k); 84 | scs_free(stgs); 85 | scs_free(d); 86 | 87 | read_status = SCS(read_data)("hs21_tiny_qp", &d, &k, &stgs); 88 | 89 | if (read_status < 0) { 90 | return "Data read failure, exit.\n"; 91 | } 92 | 93 | stgs->max_iters = 1000; 94 | /* solve with read data */ 95 | exitflag = scs(d, k, stgs, sol, &info); 96 | 97 | perr = info.pobj - opt; 98 | derr = info.dobj - opt; 99 | 100 | scs_printf("primal obj error %4e\n", perr); 101 | scs_printf("dual obj error %4e\n", derr); 102 | 103 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 104 | 105 | mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED", 106 | success); 107 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 108 | 109 | /* test warm-starting */ 110 | stgs->warm_start = 1; 111 | exitflag = scs(d, k, stgs, sol, &info); 112 | /* 25 iters should be enough if warm-started */ 113 | mu_assert("hs21_tiny_qp: warm-start failure", info.iter <= 25); 114 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 115 | 116 | mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED", 117 | success); 118 | 119 | SCS(free_data)(d); 120 | SCS(free_cone)(k); 121 | SCS(free_sol)(sol); 122 | scs_free(stgs); 123 | 124 | return fail; 125 | } 126 | -------------------------------------------------------------------------------- /test/problems/infeasible_tiny_qp.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "problem_utils.h" 5 | #include "scs.h" 6 | #include "scs_matrix.h" 7 | #include "util.h" 8 | 9 | static const char *infeasible_tiny_qp(void) { 10 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 11 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 12 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 13 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 14 | ScsInfo info = {0}; 15 | scs_int exitflag; 16 | const char *fail; 17 | 18 | /* data */ 19 | scs_float Ax[] = { 20 | 4.51689976e-01, 3.06592046e-03, 5.17304192e-01, -3.03038477e+00, 21 | -1.40509892e+00, 7.94277342e-04, 2.39454841e+00, -7.60957360e-01, 22 | -1.18946302e+00, 3.98797701e-01, 1.01386914e+00, -2.53921734e+00, 23 | -3.21202445e-01, 9.25735134e-01, -2.54046934e-01, 1.28211442e-01, 24 | -1.65155072e-01, -4.53308401e-01, -4.66709068e-01, -2.24298562e-01, 25 | -4.92029627e-01, 8.05750411e-01, -1.72920210e+00, -1.45633836e-01, 26 | 6.39086786e-01, 1.20509649e-01, 4.19672104e-01, -2.29274817e-01, 27 | 3.30125838e-01, 4.12874191e-01, 1.05357823e+00, 2.10587878e+00, 28 | 5.54934230e-01, 2.42617608e+00, -8.33596918e-01, -6.83444334e-01, 29 | 8.23856780e-01, -4.14240741e-01, -7.24051659e-01, 1.06144329e-01, 30 | 6.92857027e-01, 1.64822980e+00, 1.94603528e-01, -7.58318366e-01, 31 | 1.42948833e+00, -2.49039902e-01, 2.15319490e-01, -1.52651434e+00, 32 | -3.94761305e-01, -5.24305949e-01}; 33 | scs_int Ai[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 34 | 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 35 | 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 36 | scs_int Ap[] = {0, 10, 20, 30, 40, 50}; 37 | 38 | scs_float Px[] = {0.40113649, 0.15897142, 0.37369516, -0.05899464, 39 | 0.0772996, 0.37333677, -0.02994108, 0.04870077, 40 | 0.32221413, 0.28665235, -0.27383424, 0.04842465, 41 | 0.07832219, 0.0660133, 0.49993284}; 42 | scs_int Pi[] = {0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4}; 43 | scs_int Pp[] = {0, 1, 3, 6, 10, 15}; 44 | 45 | scs_float b[] = {-0.057279, 0.10451534, -0.10459346, -0.18452294, 46 | 0.18609658, 0.15795524, -0.00562746, -0.85852899, 47 | -0.48271335, 0.61951655}; 48 | scs_float c[] = {-0.16566256, -1.33116808, -0.1767858, -1.0940148, 49 | 1.15348983}; 50 | 51 | scs_int m = 10; 52 | scs_int n = 5; 53 | 54 | scs_int l = m; 55 | 56 | /* end data */ 57 | 58 | d->m = m; 59 | d->n = n; 60 | d->b = b; 61 | d->c = c; 62 | 63 | d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 64 | d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 65 | 66 | d->A->m = m; 67 | d->A->n = n; 68 | 69 | d->A->x = Ax; 70 | d->A->i = Ai; 71 | d->A->p = Ap; 72 | 73 | d->P->m = n; 74 | d->P->n = n; 75 | 76 | d->P->x = Px; 77 | d->P->i = Pi; 78 | d->P->p = Pp; 79 | 80 | k->l = l; 81 | 82 | scs_set_default_settings(stgs); 83 | stgs->eps_abs = 1e-6; 84 | stgs->eps_rel = 1e-6; 85 | stgs->eps_infeas = 1e-9; 86 | 87 | exitflag = scs(d, k, stgs, sol, &info); 88 | 89 | mu_assert( 90 | "infeasible_tiny_qp: SCS failed to produce outputflag SCS_INFEASIBLE", 91 | exitflag == SCS_INFEASIBLE); 92 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 93 | 94 | SCS(free_sol)(sol); 95 | scs_free(d->A); 96 | scs_free(d->P); 97 | scs_free(k); 98 | scs_free(stgs); 99 | scs_free(d); 100 | return fail; 101 | } 102 | -------------------------------------------------------------------------------- /test/problems/max_ent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/test/problems/max_ent -------------------------------------------------------------------------------- /test/problems/max_ent.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "problems/test_prob_from_data_file.h" 3 | #include "scs.h" 4 | 5 | static const char *max_ent(void) { 6 | scs_float OPT = -6.067087663361563; /* from ecos */ 7 | return _test_prob_from_data("test/problems/max_ent", OPT); 8 | } 9 | -------------------------------------------------------------------------------- /test/problems/mpc_bug.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "problems/test_prob_from_data_file.h" 3 | #include "scs.h" 4 | 5 | static const char *mpc_bug(void) { 6 | const char *fail; 7 | scs_float OPT1 = -0.473957794500; /* from scs */ 8 | scs_float OPT2 = -0.029336830816; /* from scs */ 9 | scs_float OPT3 = -0.002215217478; /* from scs */ 10 | fail = _test_prob_from_data("test/problems/mpc_bug1", OPT1); 11 | if (fail) { 12 | return fail; 13 | } 14 | fail = _test_prob_from_data("test/problems/mpc_bug2", OPT2); 15 | if (fail) { 16 | return fail; 17 | } 18 | return _test_prob_from_data("test/problems/mpc_bug3", OPT3); 19 | } 20 | -------------------------------------------------------------------------------- /test/problems/mpc_bug1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/test/problems/mpc_bug1 -------------------------------------------------------------------------------- /test/problems/mpc_bug2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/test/problems/mpc_bug2 -------------------------------------------------------------------------------- /test/problems/mpc_bug3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/test/problems/mpc_bug3 -------------------------------------------------------------------------------- /test/problems/random_prob: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvxgrp/scs/8a739589e66f745d049fc838f55775d3e07f669b/test/problems/random_prob -------------------------------------------------------------------------------- /test/problems/random_prob.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "problems/test_prob_from_data_file.h" 3 | #include "scs.h" 4 | 5 | static const char *random_prob(void) { 6 | scs_float OPT = 5.751458006385587; 7 | return _test_prob_from_data("test/problems/random_prob", OPT); 8 | } 9 | -------------------------------------------------------------------------------- /test/problems/small_lp.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "minunit.h" 3 | #include "problem_utils.h" 4 | #include "scs.h" 5 | #include "util.h" 6 | 7 | static const char *small_lp(void) { 8 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 9 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 10 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 11 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 12 | ScsSolution *opt_sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 13 | ScsInfo info = {0}; 14 | scs_float p_f = 0.1; 15 | int seed = 1234; 16 | scs_int n = 100; 17 | scs_int m = 300; 18 | scs_int col_nnz = (scs_int)ceil(sqrt(n)); 19 | scs_int nnz = n * col_nnz; 20 | scs_int exitflag; 21 | scs_float perr, derr; 22 | scs_int success; 23 | const char *fail; 24 | 25 | k->z = (scs_int)floor(m * p_f); 26 | k->l = m - k->z; 27 | 28 | d->m = m; 29 | d->n = n; 30 | gen_random_prob_data(nnz, col_nnz, d, k, opt_sol, seed); 31 | scs_set_default_settings(stgs); 32 | stgs->eps_abs = 1e-5; 33 | stgs->eps_rel = 1e-5; 34 | 35 | exitflag = scs(d, k, stgs, sol, &info); 36 | 37 | perr = SCS(dot)(d->c, sol->x, d->n) - SCS(dot)(d->c, opt_sol->x, d->n); 38 | derr = -SCS(dot)(d->b, sol->y, d->m) + SCS(dot)(d->b, opt_sol->y, d->m); 39 | scs_printf("true obj %4e\n", SCS(dot)(d->c, opt_sol->x, d->n)); 40 | scs_printf("primal obj error %4e\n", perr); 41 | scs_printf("dual obj error %4e\n", derr); 42 | 43 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 44 | 45 | mu_assert("small_lp: SCS failed to produce outputflag SCS_SOLVED", success); 46 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 47 | SCS(free_data)(d); 48 | SCS(free_cone)(k); 49 | SCS(free_sol)(sol); 50 | SCS(free_sol)(opt_sol); 51 | scs_free(stgs); 52 | 53 | return fail; 54 | } 55 | -------------------------------------------------------------------------------- /test/problems/test_exp_cone.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "scs.h" 5 | 6 | /* Forward declare exponential cone projection routine. 7 | * Implemented in exp_cone.c. 8 | */ 9 | scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal); 10 | 11 | static scs_int _run_exp_cone_test(scs_float *v0, scs_float *vp_true, 12 | scs_float *vd_true) { 13 | scs_int success = 1; 14 | scs_float vp[3], vd[3]; 15 | const scs_float TOL = 1e-6; 16 | 17 | memcpy(vp, v0, 3 * sizeof(scs_float)); 18 | memcpy(vd, v0, 3 * sizeof(scs_float)); 19 | 20 | /* inefficient, but just for testing */ 21 | SCS(proj_pd_exp_cone)(vp, 1); 22 | SCS(proj_pd_exp_cone)(vd, 0); 23 | 24 | scs_printf("*******************************\n"); 25 | scs_printf("v0: (%f, %f, %f)\n", v0[0], v0[1], v0[2]); 26 | scs_printf("vp: (%f, %f, %f)\n", vp[0], vp[1], vp[2]); 27 | scs_printf("vp_true: (%f, %f, %f)\n", vp_true[0], vp_true[1], vp_true[2]); 28 | scs_printf("vd: (%f, %f, %f)\n", vd[0], vd[1], vd[2]); 29 | scs_printf("vd_true: (%f, %f, %f)\n", vd_true[0], vd_true[1], vd_true[2]); 30 | 31 | success &= (SCS(norm_diff)(vp, vp_true, 3) <= TOL); 32 | success &= (SCS(norm_diff)(vd, vd_true, 3) <= TOL); 33 | /* Moreau decomposition holds only for polar */ 34 | /* 35 | success &= (SCS(dot)(vp, vd, 3) <= TOL); 36 | success &= (ABS(v0[0] - vp[0] + vd[0]) <= TOL); 37 | success &= (ABS(v0[1] - vp[1] + vd[1]) <= TOL); 38 | success &= (ABS(v0[2] - vp[2] + vd[2]) <= TOL); 39 | */ 40 | 41 | if (!success) { 42 | scs_printf("Failed.\n"); 43 | } 44 | 45 | return success; 46 | } 47 | 48 | static const char *test_exp_cone(void) { 49 | scs_int success = 1; 50 | scs_int i; 51 | /* test points */ 52 | scs_float v0[6][3] = { 53 | {1, 2, 3}, 54 | {0.14814832, 1.04294573, 0.67905585}, 55 | {-0.78301134, 1.82790084, -1.05417044}, 56 | {1.3282585, -0.43277314, 1.7468072}, 57 | {0.67905585, 0.14814832, 1.04294573}, 58 | {0.50210027, 0.12314491, -1.77568921}, 59 | }; 60 | /* primal projections */ 61 | scs_float vp[6][3] = { 62 | {0.8899428, 1.94041881, 3.06957226}, 63 | {-0.02001571, 0.8709169, 0.85112944}, 64 | {-1.17415616, 0.9567094, 0.280399}, 65 | {0.53160512, 0.2804836, 1.86652094}, 66 | {0.38322814, 0.27086569, 1.11482228}, 67 | {0., 0., 0.}, 68 | }; 69 | /* dual projections */ 70 | scs_float vd[6][3] = { 71 | {-0., 2., 3.}, 72 | {-0., 1.04294573, 0.67905585}, 73 | {-0.68541419, 1.85424082, 0.01685653}, 74 | {-0.02277033, -0.12164823, 1.75085347}, 75 | {-0., 0.14814832, 1.04294573}, 76 | {-0., 0.12314491, -0.}, 77 | }; 78 | 79 | for (i = 0; i < 6; ++i) { 80 | success &= _run_exp_cone_test(v0[i], vp[i], vd[i]); 81 | } 82 | mu_assert("test_exp_cone: Failure", success); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /test/problems/test_prob_from_data_file.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCS_FILE_TEST_CHASSIS 2 | #define _SCS_FILE_TEST_CHASSIS 3 | 4 | #include "glbopts.h" 5 | #include "minunit.h" 6 | #include "problem_utils.h" 7 | #include "rw.h" 8 | #include "scs.h" 9 | #include "util.h" 10 | 11 | static const char *_test_prob_from_data(const char *file, scs_float OPT) { 12 | scs_int read_status; 13 | ScsData *d; 14 | ScsCone *k; 15 | ScsSettings *stgs; 16 | ScsSolution *sol; 17 | ScsInfo info = {0}; 18 | scs_int exitflag; 19 | scs_float perr, derr; 20 | scs_int success; 21 | const char *fail; 22 | scs_float xt_p_x; 23 | scs_float *px = SCS_NULL; 24 | 25 | read_status = SCS(read_data)(file, &d, &k, &stgs); 26 | 27 | if (read_status < 0) { 28 | return "Data read failure, exit.\n"; 29 | } 30 | 31 | stgs->eps_abs = 1e-6; 32 | stgs->eps_rel = 1e-6; 33 | /* Force verbosity for the test */ 34 | stgs->verbose = 1; 35 | 36 | sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 37 | exitflag = scs(d, k, stgs, sol, &info); 38 | 39 | if (d->P) { 40 | /* px = Px */ 41 | px = (scs_float *)scs_calloc(d->n, sizeof(scs_float)); 42 | memset(px, 0, d->n * sizeof(scs_float)); 43 | SCS(accum_by_p)(d->P, sol->x, px); 44 | xt_p_x = SCS(dot)(px, sol->x, d->n); 45 | } else { 46 | xt_p_x = 0.; 47 | } 48 | 49 | perr = 0.5 * xt_p_x + SCS(dot)(d->c, sol->x, d->n) - OPT; 50 | derr = -0.5 * xt_p_x - SCS(dot)(d->b, sol->y, d->m) - OPT; 51 | scs_printf("primal obj error %4e\n", perr); 52 | scs_printf("dual obj error %4e\n", derr); 53 | 54 | success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED; 55 | if (!success) { 56 | scs_printf("%s: FAILED\n", file); 57 | } 58 | mu_assert(file, success); 59 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 60 | SCS(free_data)(d); 61 | SCS(free_cone)(k); 62 | SCS(free_sol)(sol); 63 | scs_free(stgs); 64 | if (px) { 65 | scs_free(px); 66 | } 67 | if (fail) { 68 | scs_printf("%s: FAILED\n", file); 69 | } 70 | return fail; 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /test/problems/test_validation.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "minunit.h" 3 | #include "problem_utils.h" 4 | #include "scs.h" 5 | #include "util.h" 6 | 7 | static const char *test_validation(void) { 8 | scs_printf("Testing that SCS handles bad inputs correctly:\n"); 9 | 10 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 11 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 12 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 13 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 14 | ScsSolution *opt_sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 15 | ScsInfo info = {0}; 16 | scs_float p_f = 0.1; 17 | int seed = 1234; 18 | scs_int n = 1; 19 | scs_int m = 3; 20 | scs_int col_nnz = (scs_int)ceil(sqrt(n)); 21 | scs_int nnz = n * col_nnz; 22 | scs_int exitflag; 23 | 24 | k->z = (scs_int)floor(m * p_f); 25 | k->l = m - k->z; 26 | 27 | d->m = m; 28 | d->n = n; 29 | gen_random_prob_data(nnz, col_nnz, d, k, opt_sol, seed); 30 | scs_set_default_settings(stgs); 31 | 32 | /* TODO test more failure modes */ 33 | stgs->eps_abs = -1; 34 | 35 | exitflag = scs(d, k, stgs, sol, &info); 36 | 37 | mu_assert("test_fails: SCS failed to produce outputflag SCS_FAILED", 38 | exitflag == SCS_FAILED); 39 | SCS(free_data)(d); 40 | SCS(free_cone)(k); 41 | SCS(free_sol)(sol); 42 | SCS(free_sol)(opt_sol); 43 | scs_free(stgs); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/problems/unbounded_tiny_qp.h: -------------------------------------------------------------------------------- 1 | #include "glbopts.h" 2 | #include "linalg.h" 3 | #include "minunit.h" 4 | #include "problem_utils.h" 5 | #include "scs.h" 6 | #include "scs_matrix.h" 7 | #include "util.h" 8 | 9 | static const char *unbounded_tiny_qp(void) { 10 | ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone)); 11 | ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData)); 12 | ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings)); 13 | ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 14 | ScsInfo info = {0}; 15 | scs_int exitflag; 16 | const char *fail; 17 | 18 | /* data */ 19 | scs_float Ax[] = { 20 | -0.04101197, 1.68314201, 0.5543439, -0.96712378, 0.19370457, 21 | -1.15055711, 1.13315795, -1.05910693, 1.24512977, -0.70999048, 22 | -0.89976326, -0.41373294, -0.73848186, 0.08663554, -0.1681749, 23 | -0.42711619, -0.90501247, -0.490446, -0.67124734, 1.67772257, 24 | 0.39924394, 0.16330292, 0.55609205, -1.22088238, -0.25891675, 25 | -3.07159984, -1.84102417, 1.5621635, -1.13771529, 0.56067264, 26 | -0.0854747, 0.31024722, -0.07437118, -0.20711534, -0.35241366, 27 | -0.98965142, -1.91488894, 1.01591507, 0.45387459, 1.43709968, 28 | -0.0482982, -0.32447, -0.91433399, 0.49750765, 0.09150015, 29 | 0.69164184, 0.51064936, -1.35009809, -1.35403213, 1.51897627}; 30 | scs_int Ai[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 31 | 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 32 | 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 33 | scs_int Ap[] = {0, 10, 20, 30, 40, 50}; 34 | 35 | scs_float b[] = {1.4672744, 0.36190605, -0.5548082, -0.35039932, 36 | -1.12765224, 0.51012137, -0.24927975, -1.45270362, 37 | -1.94080389, -0.0189713}; 38 | scs_float c[] = {0.17547329, -0.11983635, -0.11791039, 0.12099476, 39 | 0.61931906}; 40 | 41 | scs_int m = 10; 42 | scs_int n = 5; 43 | 44 | scs_int l = m; 45 | 46 | /* end data */ 47 | 48 | d->m = m; 49 | d->n = n; 50 | d->b = b; 51 | d->c = c; 52 | 53 | d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix)); 54 | 55 | d->A->m = m; 56 | d->A->n = n; 57 | 58 | d->A->x = Ax; 59 | d->A->i = Ai; 60 | d->A->p = Ap; 61 | 62 | k->l = l; 63 | 64 | scs_set_default_settings(stgs); 65 | stgs->eps_abs = 1e-6; 66 | stgs->eps_rel = 1e-6; 67 | stgs->eps_infeas = 1e-7; 68 | 69 | exitflag = scs(d, k, stgs, sol, &info); 70 | 71 | mu_assert("unbounded_tiny_qp: SCS failed to produce outputflag SCS_UNBOUNDED", 72 | exitflag == SCS_UNBOUNDED); 73 | 74 | fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag); 75 | 76 | SCS(free_sol)(sol); 77 | SCS(free_cone)(k); 78 | scs_free(stgs); 79 | scs_free(d->A); 80 | scs_free(d); 81 | return fail; 82 | } 83 | -------------------------------------------------------------------------------- /test/rng.h: -------------------------------------------------------------------------------- 1 | /* This program by D E Knuth is in the public domain and freely copyable 2 | * AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES! 3 | * It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6 4 | * (or in the errata to the 2nd edition --- see 5 | * http://www-cs-faculty.stanford.edu/~knuth/taocp.html 6 | * in the changes to Volume 2 on pages 171 and following). */ 7 | 8 | /* N.B. The MODIFICATIONS introduced in the 9th printing (2002) are 9 | included here; there's no backwards compatibility with the original. */ 10 | 11 | /* This version also adopts Brendan McKay's suggestion to 12 | accommodate naive users who forget to call ran_start(seed). */ 13 | 14 | /* If you find any bugs, please report them immediately to 15 | * taocp@cs.stanford.edu 16 | * (and you will be rewarded if the bug is genuine). Thanks! */ 17 | 18 | /************ see the book for explanations and caveats! *******************/ 19 | /************ in particular, you need two's complement arithmetic **********/ 20 | 21 | #define KK 100 /* the long lag */ 22 | #define LL 37 /* the short lag */ 23 | #define MM (1L << 30) /* the modulus */ 24 | #define mod_diff(x, y) (((x) - (y)) & (MM - 1)) /* subtraction mod MM */ 25 | 26 | long ran_x[KK]; /* the generator state */ 27 | 28 | #ifdef __STDC__ 29 | void ran_array(long aa[], int n) 30 | #else 31 | void ran_array(aa, n) /* put n new random numbers in aa */ 32 | long *aa; /* destination */ 33 | int n; /* array length (must be at least KK) */ 34 | #endif 35 | { 36 | register int i, j; 37 | for (j = 0; j < KK; j++) 38 | aa[j] = ran_x[j]; 39 | for (; j < n; j++) 40 | aa[j] = mod_diff(aa[j - KK], aa[j - LL]); 41 | for (i = 0; i < LL; i++, j++) 42 | ran_x[i] = mod_diff(aa[j - KK], aa[j - LL]); 43 | for (; i < KK; i++, j++) 44 | ran_x[i] = mod_diff(aa[j - KK], ran_x[i - LL]); 45 | } 46 | 47 | /* the following routines are from exercise 3.6--15 */ 48 | /* after calling ran_start, get new randoms by, e.g., "x=ran_arr_next()" */ 49 | 50 | #define QUALITY 1009 /* recommended quality level for high-res use */ 51 | long ran_arr_buf[QUALITY]; 52 | long ran_arr_dummy = -1, ran_arr_started = -1; 53 | long *ran_arr_ptr = &ran_arr_dummy; /* the next random number, or -1 */ 54 | 55 | #define TT 70 /* guaranteed separation between streams */ 56 | #define is_odd(x) ((x)&1) /* units bit of x */ 57 | 58 | #ifdef __STDC__ 59 | void ran_start(long seed) 60 | #else 61 | void ran_start(seed) /* do this before using ran_array */ 62 | long seed; /* selector for different streams */ 63 | #endif 64 | { 65 | register int t, j; 66 | long x[KK + KK - 1]; /* the preparation buffer */ 67 | register long ss = (seed + 2) & (MM - 2); 68 | for (j = 0; j < KK; j++) { 69 | x[j] = ss; /* bootstrap the buffer */ 70 | ss <<= 1; 71 | if (ss >= MM) 72 | ss -= MM - 2; /* cyclic shift 29 bits */ 73 | } 74 | x[1]++; /* make x[1] (and only x[1]) odd */ 75 | for (ss = seed & (MM - 1), t = TT - 1; t;) { 76 | for (j = KK - 1; j > 0; j--) 77 | x[j + j] = x[j], x[j + j - 1] = 0; /* "square" */ 78 | for (j = KK + KK - 2; j >= KK; j--) 79 | x[j - (KK - LL)] = mod_diff(x[j - (KK - LL)], x[j]), 80 | x[j - KK] = mod_diff(x[j - KK], x[j]); 81 | if (is_odd(ss)) { /* "multiply by z" */ 82 | for (j = KK; j > 0; j--) 83 | x[j] = x[j - 1]; 84 | x[0] = x[KK]; /* shift the buffer cyclically */ 85 | x[LL] = mod_diff(x[LL], x[KK]); 86 | } 87 | if (ss) 88 | ss >>= 1; 89 | else 90 | t--; 91 | } 92 | for (j = 0; j < LL; j++) 93 | ran_x[j + KK - LL] = x[j]; 94 | for (; j < KK; j++) 95 | ran_x[j - LL] = x[j]; 96 | for (j = 0; j < 10; j++) 97 | ran_array(x, KK + KK - 1); /* warm things up */ 98 | ran_arr_ptr = &ran_arr_started; 99 | } 100 | 101 | #define ran_arr_next() (*ran_arr_ptr >= 0 ? *ran_arr_ptr++ : ran_arr_cycle()) 102 | long ran_arr_cycle(void) { 103 | if (ran_arr_ptr == &ran_arr_dummy) 104 | ran_start(314159L); /* the user forgot to initialize */ 105 | ran_array(ran_arr_buf, QUALITY); 106 | ran_arr_buf[KK] = -1; 107 | ran_arr_ptr = ran_arr_buf + 1; 108 | return ran_arr_buf[0]; 109 | } 110 | -------------------------------------------------------------------------------- /test/run_from_file.c: -------------------------------------------------------------------------------- 1 | #include "rw.h" 2 | #include "scs.h" 3 | #include "util.h" 4 | 5 | scs_int override_setting(ScsSettings *s, char *param, char *val) { 6 | scs_printf("Attempting to override %s with value %s.\n", param, val); 7 | if (strcmp(param, "normalize") == 0) { 8 | s->normalize = atoi(val); 9 | } else if (strcmp(param, "scale") == 0) { 10 | s->scale = atof(val); 11 | } else if (strcmp(param, "rho_x") == 0) { 12 | s->rho_x = atof(val); 13 | } else if (strcmp(param, "max_iters") == 0) { 14 | s->max_iters = atoi(val); 15 | } else if (strcmp(param, "eps_abs") == 0) { 16 | s->eps_abs = atof(val); 17 | } else if (strcmp(param, "eps_rel") == 0) { 18 | s->eps_rel = atof(val); 19 | } else if (strcmp(param, "eps_infeas") == 0) { 20 | s->eps_infeas = atof(val); 21 | } else if (strcmp(param, "alpha") == 0) { 22 | s->alpha = atof(val); 23 | } else if (strcmp(param, "verbose") == 0) { 24 | s->verbose = atoi(val); 25 | } else if (strcmp(param, "acceleration_lookback") == 0) { 26 | s->acceleration_lookback = atoi(val); 27 | } else if (strcmp(param, "acceleration_interval") == 0) { 28 | s->acceleration_interval = atoi(val); 29 | } else if (strcmp(param, "adaptive_scale") == 0) { 30 | s->adaptive_scale = atoi(val); 31 | } else if (strcmp(param, "log_csv_filename") == 0) { 32 | s->log_csv_filename = val; 33 | } else { 34 | return -1; 35 | } 36 | scs_printf("Success.\n"); 37 | return 0; 38 | } 39 | 40 | /* Simple helper function to run problems from data files */ 41 | /* Mostly useful for debugging */ 42 | int main(int argc, char **argv) { 43 | char *filename; 44 | scs_int read_status; 45 | ScsData *d; 46 | ScsCone *k; 47 | ScsSettings *stgs; 48 | ScsSolution *sol; 49 | ScsInfo info = {0}; 50 | scs_int i; 51 | if (argc < 2) { 52 | scs_printf("Need to specify a filename, exit.\n"); 53 | return -1; 54 | } 55 | filename = argv[1]; 56 | read_status = SCS(read_data)(filename, &d, &k, &stgs); 57 | if (read_status < 0) { 58 | scs_printf("Data read failure, exit.\n"); 59 | return -1; 60 | } 61 | for (i = 2; i < argc; i += 2) { 62 | if (argc < i + 2) { 63 | scs_printf("Incorrect number of arguments supplied.\n"); 64 | 65 | SCS(free_data)(d); 66 | SCS(free_cone)(k); 67 | scs_free(stgs); 68 | 69 | return -1; 70 | } 71 | if (override_setting(stgs, argv[i], argv[i + 1]) < 0) { 72 | scs_printf("Unrecognized setting %s\n", argv[i]); 73 | 74 | SCS(free_data)(d); 75 | SCS(free_cone)(k); 76 | scs_free(stgs); 77 | 78 | return -1; 79 | } 80 | } 81 | if (!stgs->verbose) { 82 | scs_printf( 83 | "File data set `verbose` to 0, SCS will not output information. Add " 84 | "`verbose 1` to call to override.\n"); 85 | } 86 | scs_printf("Solving problem.\n"); 87 | sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution)); 88 | scs(d, k, stgs, sol, &info); 89 | 90 | SCS(free_data)(d); 91 | SCS(free_cone)(k); 92 | SCS(free_sol)(sol); 93 | scs_free(stgs); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /test/run_tests.c: -------------------------------------------------------------------------------- 1 | /* Taken from http://www.jera.com/techinfo/jtns/jtn002.html */ 2 | #include 3 | 4 | #include "minunit.h" 5 | #include "problem_utils.h" 6 | #include "scs.h" 7 | 8 | /* Include Tests */ 9 | #include "problems/degenerate.h" 10 | #include "problems/hs21_tiny_qp.h" 11 | #include "problems/infeasible_tiny_qp.h" 12 | #include "problems/qafiro_tiny_qp.h" 13 | #include "problems/small_lp.h" 14 | #include "problems/small_qp.h" 15 | #include "problems/test_exp_cone.h" 16 | #include "problems/unbounded_tiny_qp.h" 17 | 18 | int tests_run = 0; 19 | 20 | /* decrement tests_run since mu_unit will increment it, so this cancels */ 21 | #define _SKIP(problem) \ 22 | char *problem(void) { \ 23 | scs_printf("skipped\n"); \ 24 | tests_run--; \ 25 | return 0; \ 26 | } 27 | 28 | #if NO_VALIDATE == 0 29 | #include "problems/test_validation.h" 30 | #else 31 | _SKIP(test_validation) 32 | #endif 33 | 34 | /* solve SDPs, requires blas / lapack */ 35 | #if defined(USE_LAPACK) && NO_READ_WRITE == 0 36 | #include "problems/random_prob.h" 37 | #include "problems/rob_gauss_cov_est.h" 38 | #else 39 | _SKIP(rob_gauss_cov_est) 40 | _SKIP(random_prob) 41 | #endif 42 | 43 | #if NO_READ_WRITE == 0 /* reads / writes */ 44 | #include "problems/hs21_tiny_qp_rw.h" 45 | #include "problems/max_ent.h" 46 | #include "problems/mpc_bug.h" 47 | #else 48 | _SKIP(hs21_tiny_qp_rw) 49 | _SKIP(max_ent) 50 | _SKIP(mpc_bug) 51 | #endif 52 | 53 | static const char *all_tests(void) { 54 | mu_run_test(test_validation); 55 | mu_run_test(degenerate); 56 | mu_run_test(small_lp); 57 | mu_run_test(small_qp); 58 | mu_run_test(rob_gauss_cov_est); 59 | mu_run_test(hs21_tiny_qp); 60 | mu_run_test(hs21_tiny_qp_rw); 61 | mu_run_test(qafiro_tiny_qp); 62 | mu_run_test(infeasible_tiny_qp); 63 | mu_run_test(unbounded_tiny_qp); 64 | mu_run_test(random_prob); 65 | mu_run_test(max_ent); 66 | mu_run_test(mpc_bug); 67 | mu_run_test(test_exp_cone); 68 | return 0; 69 | } 70 | int main(void) { 71 | const char *result = all_tests(); 72 | if (result != 0) { 73 | scs_printf("%s\n", result); 74 | scs_printf("TEST FAILED!\n"); 75 | } else { 76 | scs_printf("ALL TESTS PASSED\n"); 77 | } 78 | scs_printf("Tests run: %d\n", tests_run); 79 | 80 | return result != 0; 81 | } 82 | --------------------------------------------------------------------------------