{ "info": { "author": "AJ Friend", "author_email": "ajfriend@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "# CySCS\n[![Build Status](https://travis-ci.org/ajfriend/cyscs.svg?branch=master)](https://travis-ci.org/ajfriend/cyscs)\n\n`cyscs` is a Python interface, written in Cython, for [SCS](https://github.com/cvxgrp/scs), a numerical optimization package written in C for solving convex cone problems. The main advantage of this interface over the existing\nPython interface is the `Workspace` object, which allows for re-use\nof matrix factorizations, which can reduce solve time when applied\na sequence of related problems.\n\nSCS solves convex cone programs via operator splitting.\nIt can solve: linear programs (LPs), second-order cone programs (SOCPs),\nsemidefinite programs (SDPs), exponential cone programs (ECPs), and\npower cone programs (PCPs), or problems with any combination of these\ncones.\n\nMost users will not interact with `cyscs` directly. The most common use-case is as\na back-end to a convex optimization modeling framework like [CVXPY](http://www.cvxpy.org).\n\nAdvanced users can consult the interface notes below, the [tutorial IPython notebook](tutorial.ipynb) or the [parallel tutorial IPython notebook](parallel_tutorial.ipynb). For more complete definitions of the input data format, convex cones, and output variables, please see the [`SCS README`](https://github.com/cvxgrp/scs/blob/master/README.md) or the [SCS Paper](http://web.stanford.edu/~boyd/papers/scs.html).\n\n## Installation\n### Pip\n- XXX: not yet uploaded to PyPI, so `pip` won't work\n- `pip install cyscs`\n\n### Building from source with Cython\nUsers can also install by\n- cloning this GitHub repo with `git clone --recursive https://github.com/ajfriend/cyscs.git`\n- installing dependencies `pip install numpy scipy cython`\n- (optionally, for tests) `pip install pytest`\n- running `python setup.py install --cython` inside the `cyscs` directory\n- (optionally) run tests with `make test`\n\n## Basic Usage\nThe basic usage is almost identical to the existing SCS Python interface: \n```python\nimport cyscs as scs\nsol = scs.solve(data, cone, warm_start=None, **settings)\n```\n\nNote that `cyscs` can be used as a drop-in replacement to the current\nPython interface `scs` using the import statement `import cyscs as scs`.\n(Some advanced features like warm-starting are *not* identical\nacross both interfaces. Converting between them manually is easy, however.)\n\nWe describe the arguments to `cyscs.solve()` briefly below. For more detail, please see the [`SCS README`](https://github.com/cvxgrp/scs/blob/master/README.md).\n\n- `data` is a Python `dict` with keys:\n - `'A'`: `scipy.sparse.csc` matrix, i.e., a matrix in Compressed Sparse Column format with `m` rows and `n` columns\n - `'b'`: 1D `numpy` array of length `m`\n - `'c'`: 1D `numpy` array of lenth `n`\n- `cone` is a Python `dict` with potential keys:\n - `'f'`: `int` of linear equality constraints\n - `'l'`: `int` of linear inequality constraints\n - `'q'`: `list` of `int`s giving second-order cone sizes\n - `'s'`: `list` of `int`s giving semidefinite cone sizes\n - `'ep'`: `int` of primal exponential cones\n - `'ed'`: `int` of dual exponential cones\n - `'p'`: `list` of `float`s of primal/dual power cone parameters \n- `warm_start` is an **optional** `dict` of `numpy` arrays (with keys `'x'`, `'y'`, and `'s'`) used to warm-start the solver; if these values are close to the final solution, warm-starting can reduce the number of SCS iterations\n- `cyscs.solve()` also accepts optional keyword arguments for solver settings:\n - `use_indirect`\n - `verbose`\n - `normalize`\n - `max_iters`\n - `scale`\n - `eps`\n - `cg_rate`\n - `alpha`\n - `rho_x`\n- settings are passed as keyword arguments:\n - `cyscs.solve(data, cone, max_iters=100)`\n - `cyscs.solve(data, cone, alpha=1.4, eps=1e-5, verbose=True)`\n - `cyscs.solve(data, cone, warm_start, use_indirect=True)`\n- default settings can be seen by calling `scs.default_settings()`\n- `sol` is a `dict` with keys:\n - `'x'`: `numpy` array\n - `'y'`: `numpy` array\n - `'s'`: `numpy` array\n - `'info'`: `dict` containing solver status information\n\n### Warm-starting\nThe solver can be warm-started, that is, started from a point close to the final solution in the hope of reducing the solve-time. You must supply `numpy` arrays for for **all** of the warm-started variables `x`, `y`, and `s`. Pass them as dictionary to the `warm_start` parameter in `cyscs.solve()`:\n\n```python\nws = {'x': x, 'y': y, 's': s}\nsol = scs.solve(data, cone, warm_start=ws)\n```\n\nOutput from previous solves can be used to warm-start future solves:\n```python\nsol = scs.solve(data, cone, eps=1e-3)\nsol = scs.solve(data, cone, warm_start=sol, eps=1e-4)\n```\n\n\n### Data Formats\nBelow are the integer and floating-point format expectations for input data.\nIf the formats are not exactly correct, `cyscs` will attempt to convert the data for you.\n\n`cyscs.solve()` expects `b`, `c`, `x`, `y`, and `s` to be one-dimensional `numpy` arrays with `dtype` `'float64'`.\n\n`solve()` also expects `A` to be a `scipy.sparse.csc` matrix such that the values of the matrix have `dtype` `'float64'`, and the attributes `A.indices` and `A.indptr` are `numpy` arrays with `dtype` `'int64'`:\n\n```python\n>>> A.dtype\ndtype('float64')\n>>> A.indices.dtype, A.indptr.dtype\n(dtype('int64'), dtype('int64')) \n```\n\nNote that, by default, `scipy.sparse.csc` matrices have `indptr` and `indices` arrays with `dtype` `int32`. If the matrices are not converted ahead of time, `cyscs` will do the conversion internally, without modifying the original `A` matrix. However, it may be more efficient to construct an `A` with the correct `dtype`s initially, rather than convert.\n\n### Data Immutability\n`cyscs.solve()` will not modify the input data in `data`, `cone`, or `warm_start`. Copies of the data will be made for internal use, and new `numpy` arrays will be created to be returned in `sol`.\n\n\n## Factorization Caching with `cyscs.Workspace`\nWhen using the **direct** solver (`use_indirect=False`), a single matrix factorization is performed and used many times in SCS's iterative procedure.\nThis factorization depends on the input matrix `A` but **not** on the vectors\n`b` or `c`. When solving many problems where `A` is fixed, but `b` and `c` change, the `cyscs.Workspace()` object allows us to cache the initial factorization and reuse it across many solves, without having to re-compute it. This can save time when solving many related problems.\n\nThe `Workspace` is instantiated with the same `data` and `cone` dictionaries\nas `cyscs.solve()`, along with optional settings:\n```python\nwork = scs.Workspace(data, cone, **settings)\n```\n\nOnce the `Workspace` object is created, we can call its solve method\n```python\nsol = work.solve(new_bc=None, warm_start=None, **settings)\n```\n\nwhich will re-use the matrix factorization that was computed when the `Workspace` was initialized. Note that all of the parameters to `work.solve()` are optional. `new_bc` is a dictionary which can optionally provide\nupdated `b` or `c` vectors (any other keys, including `A`, are ignored).\n\nThe return value, `sol`, is a `dict` with keys `x`, `y`, `s`, and `info`, just as in `cyscs.solve()`.\n\n### `Workspace` state\n`work.solve()` will operate on the data contained in the `work` object:\n\n- `work.data`\n- `work.settings`\n\nThe user can modify the state of the `Workspace` object between calls to `work.solve`.\n\n#### `work.data`\nNote that `work.data` is a `dict` with keys `b` and `c`, but **not** `A`. This is because `A` is copied and stored internally (along with its factorization) upon initialization, and cannot be modified.\n\nDue to the data copy, the user is now free to delete or modify the `A` matrix that they passed into the `cyscs.Workspace` constructor, as this will have no effect on the `Workspace` object.\n\n#### `work.settings`\nOnly some of the values in `work.settings` can be modified between calls to `work.solve()`.\n\nThe following settings are **fixed** at `Workspace` initialization time:\n\n- `use_indirect`\n- `rho_x`\n- `normalize`\n- `scale`\n\nA copy of the `dict` of **fixed settings** is given by `work.fixed`. If any of the `work.settings` differ from `work.fixed` when `work.solve()` is called, an `Exception` will be raised. Calling `work.fixed` returns a **copy** of the underlying `dict`, which cannot be modified. XXX: make a test for this\n\nThe following settings **can** be modified between calls to `work.solve()`:\n\n- `verbose`\n- `max_iters`\n- `eps`\n- `cg_rate`\n- `alpha`\n\n#### `work.info`\n\nWhen calling `sol = work.solve()`, solver status information is available\nthrough the `sol['info']` dictionary. This same information is also available through the attribute `work.info`.\n\nThis attribute is useful, for instance, if you'd like to know the solver setup time after calling `Workspace()` but before calling `work.solve()`, which you can access with `work.info['setupTime']`.\n\n#### Immutable `work` state\nUpon initialization, `A` is copied, stored, and factored internally.\nAny changes made to the `scipy` sparse input matrix `A` after the fact\nwill not be reflected in the `work` object.\nSimilarly, `work.cone` is fixed at initialization and cannot be modified.\nTo avoid confusion, we do not expose `A` or `cone` to the user\nthrough the `work` object.\n\n### `work.solve()` arguments\n\n#### `new_bc` and `settings`\nPassing a `new_bc` dictionary or additional settings to `work.solve()` provides one last chance to modify the problem data before calling the solver. Any changes are written to the `work` object and persist to future calls to `work.solve()`. In fact,\n```python\nnew_b = dict(b=b)\nwork.solve(new_bc = new_b, eps=1e-5, alpha=1.1)\n```\n\nis exactly equivalent to\n\n```python\nwork.data['b'] = b\nwork.settings['eps'] = 1e-5\nwork.settings['alpha'] = 1.1\nwork.solve()\n```\n\nIf `new_bc` is passed to `work.solve()`, only the keys `b` and `c` will be used to update `work.data`. If an `A` key exists, it will be ignored.\n\nMore commonly, a user might simply update the original `data` dictionary and pass it to `work.solve()`:\n\n```python\nwork = scs.Workspace(data, cone)\n...\ndata['b'] = b # update the b vector\nsol = work.solve(new_bc=data)\n```\n\n#### `warm_start`\nYou can also provide a dictionary of warm-start vectors to the `warm_start` parameter, which may help reduce the solve time.\n\nIn the example below, we first solve a problem to a tolerance of `1e-3`, and use that solution as a warm-start for solving the problem to a higher tolerance of `1e-4`. The second call to `work.solve()` will generally take fewer iterations than if we hadn't provided a `warm_start`, and also\nbenefits from not having to re-compute the matrix factorization.\n\n```python\nwork = scs.Workspace(data, cone)\nsol = work.solve(eps=1e-3)\nsol = work.solve(warm_start=sol, eps=1e-4)\n```\n\n## Example Library\n`cyscs` comes with a small examples library,\n`cyscs.examples`, which\ndemonstrates the proper problem input format,\nand can be used to easily test the solver.\n\nFor example,\n```python\nimport cyscs as scs\ndata, cone = scs.examples.l1(m=100, seed=0)\nsol = scs.solve(data, cone)\n```\n\nsolves a simple least L1-norm problem.\n\n## Python GIL\n\n`cyscs.solve()`, `Workspace` initialization, and `Worksapce.solve()` all release the Python GIL when running the underlying C solver code. This allows for multithreaded parallelism, so that multiple SCS problems can be solved at once\non multicore machines.\n\nProblems can be solved using, for example, the `concurrent.futures.ThreadPoolExecutor` or `concurrent.futures.ProcessPoolExecutor` interfaces.\nSince SCS releases the GIL, we can benefit from using the `ThreadPoolExecutor` since it does not require launching separate python interpreters or the serialization of data for communication between processes. `ProcessPoolExecutor` requires both of these.\n\nFor examples, see the [parallel tutorial IPython notebook](parallel_tutorial.ipynb).", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/ajfriend/cyscs", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "cyscs", "package_url": "https://pypi.org/project/cyscs/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/cyscs/", "project_urls": { "Homepage": "http://github.com/ajfriend/cyscs" }, "release_url": "https://pypi.org/project/cyscs/0.1/", "requires_dist": [ "numpy (>=1.7)", "scipy (>=0.13.2)" ], "requires_python": "", "summary": "CySCS: A Cython wrapper for the SCS convex optimization solver.", "version": "0.1" }, "last_serial": 2111841, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "41ba271318eaab7222a72e4c5f89f9c8", "sha256": "208a8b90298ea01c10a8187bb731fa89fca6b8f72d57509caad7f9c49ba3aae2" }, "downloads": -1, "filename": "cyscs-0.1-cp35-cp35m-macosx_10_11_x86_64.whl", "has_sig": false, "md5_digest": "41ba271318eaab7222a72e4c5f89f9c8", "packagetype": "bdist_wheel", "python_version": "cp35", "requires_python": null, "size": 235518, "upload_time": "2016-05-12T04:05:15", "url": "https://files.pythonhosted.org/packages/da/76/2069acd9daee236d21048df14ec9665ac4146957e0e8e6e5754576f8b23d/cyscs-0.1-cp35-cp35m-macosx_10_11_x86_64.whl" }, { "comment_text": "", "digests": { "md5": "c318eda4bac63c0925e4fb35fd64f352", "sha256": "a0aec7da3f8afaf92665b202fcd52ce7fb43ecf9e55b3fbe87f8ff5c002fa581" }, "downloads": -1, "filename": "cyscs-0.1.tar.gz", "has_sig": false, "md5_digest": "c318eda4bac63c0925e4fb35fd64f352", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 282252, "upload_time": "2016-05-12T04:05:22", "url": "https://files.pythonhosted.org/packages/58/46/01b1bdd38d94f418c85914c2d373c38b143f4271ad91c923256a2c336224/cyscs-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "41ba271318eaab7222a72e4c5f89f9c8", "sha256": "208a8b90298ea01c10a8187bb731fa89fca6b8f72d57509caad7f9c49ba3aae2" }, "downloads": -1, "filename": "cyscs-0.1-cp35-cp35m-macosx_10_11_x86_64.whl", "has_sig": false, "md5_digest": "41ba271318eaab7222a72e4c5f89f9c8", "packagetype": "bdist_wheel", "python_version": "cp35", "requires_python": null, "size": 235518, "upload_time": "2016-05-12T04:05:15", "url": "https://files.pythonhosted.org/packages/da/76/2069acd9daee236d21048df14ec9665ac4146957e0e8e6e5754576f8b23d/cyscs-0.1-cp35-cp35m-macosx_10_11_x86_64.whl" }, { "comment_text": "", "digests": { "md5": "c318eda4bac63c0925e4fb35fd64f352", "sha256": "a0aec7da3f8afaf92665b202fcd52ce7fb43ecf9e55b3fbe87f8ff5c002fa581" }, "downloads": -1, "filename": "cyscs-0.1.tar.gz", "has_sig": false, "md5_digest": "c318eda4bac63c0925e4fb35fd64f352", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 282252, "upload_time": "2016-05-12T04:05:22", "url": "https://files.pythonhosted.org/packages/58/46/01b1bdd38d94f418c85914c2d373c38b143f4271ad91c923256a2c336224/cyscs-0.1.tar.gz" } ] }