{"id":26123418,"url":"https://github.com/cvxgrp/dsp","last_synced_at":"2025-04-13T14:34:41.965Z","repository":{"id":65310402,"uuid":"542885690","full_name":"cvxgrp/dsp","owner":"cvxgrp","description":"A CVXPY extension for saddle problems","archived":false,"fork":false,"pushed_at":"2025-01-06T05:00:00.000Z","size":1494,"stargazers_count":26,"open_issues_count":3,"forks_count":3,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-10T20:37:56.003Z","etag":null,"topics":["cvxpy","modeling-language","optimization","python","saddle-point"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cvxgrp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-09-29T02:44:35.000Z","updated_at":"2025-01-22T19:36:25.000Z","dependencies_parsed_at":"2023-02-17T02:31:17.797Z","dependency_job_id":"492aadc8-9e4c-4881-9f26-6ca937bc62b3","html_url":"https://github.com/cvxgrp/dsp","commit_stats":{"total_commits":254,"total_committers":5,"mean_commits":50.8,"dds":"0.47637795275590555","last_synced_commit":"61a66d3c4297fc4e0309694ed3fb142e770e22c2"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvxgrp%2Fdsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvxgrp%2Fdsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvxgrp%2Fdsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvxgrp%2Fdsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cvxgrp","download_url":"https://codeload.github.com/cvxgrp/dsp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248728697,"owners_count":21152277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cvxpy","modeling-language","optimization","python","saddle-point"],"created_at":"2025-03-10T15:53:09.896Z","updated_at":"2025-04-13T14:34:41.928Z","avatar_url":"https://github.com/cvxgrp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DSP -  Disciplined Saddle Programming\n[![build](https://github.com/cvxgrp/dsp/actions/workflows/build.yml/badge.svg)](https://github.com/cvxgrp/dsp/actions/workflows/build.yml)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=dsp\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=dsp)\n\nA CVXPY extension for Disciplined Saddle Programming.\nDSP allows solving convex-concave saddle point problems, and more generally\nconvex optimization problems we refer to as _saddle problems_, which include the partial\nsupremum or infimum of convex-concave saddle functions.\nSaddle functions are functions that are (jointly) convex in a subset of their\narguments, and (jointly) concave in the remaining arguments.\nA detailed description of the underlying method is given in our [accompanying paper](https://arxiv.org/abs/2301.13427).\n\n## Installation\n\nThe DSP package can be installed using pip as follows\n```bash\npip install dsp-cvxpy\n```\nThe DSP package requires CVXPY 1.3 or later.\n\n## Minimal example\n\nThe following example creates and solves a simple saddle point problem known as a matrix game.\nA saddle point problem is created by specifying an objective and a list of constraints.\nHere, the objective is $f(x, y) = x^TCy$, which is simultaneously minimized over $x$ and maximized over $y$.\nThe resulting saddle point is an optimal mixed strategy for both players in the matrix game.\nEach component is explained below in more detail.\n\n```python\nimport dsp\nimport cvxpy as cp\nimport numpy as np\n\nx = cp.Variable(2)\ny = cp.Variable(2)\nC = np.array([[1, 2], [3, 1]])\n\nf = dsp.inner(x, C @ y)\nobj = dsp.MinimizeMaximize(f)\n\nconstraints = [x \u003e= 0, cp.sum(x) == 1, y \u003e= 0, cp.sum(y) == 1]\nprob = dsp.SaddlePointProblem(obj, constraints)\nprob.solve()  # solves the problem\n\nprob.value  # 1.6666666666666667\nx.value  # array([0.66666667, 0.33333333])\ny.value  # array([0.33333333, 0.66666667])\n```\n\n## New atoms\nIn DSP, saddle functions are created from atoms. Each atom represents a saddle function, with the convention being\nthat the first argument is the convex argument and the second argument is the concave argument.\n\n- `inner(x, y)`  \nThe inner product $x^Ty$, with both arguments affine.\n- `saddle_inner(Fx, Gy)`  \nThe inner product $F(x)^TG(y)$, with $F$ convex and nonnegative, and $G$ concave. If $G$ is not nonnegative, a constraint\n$G \\geq 0$ is added.\n- `weighted_norm2(x, y)`  \nThe weighted $\\ell_2$ norm $\\left(\\sum_i y_i x_i^2\\right)^{1/2}$. Here too, a constraint $y \\geq 0$ is added if $y$ is not\nnonnegative.\n- `weighted_log_sum_exp(x, y)`\nThe weighted log-sum-exp function $\\log\\left(\\sum_i y_i \\exp(x_i)\\right)$. Again a constraint $y \\geq 0$ is added if $y$ is not\nnonnegative.\n- `quasidef_quad_form(x, y, P, Q, S)`  \nFor a positive semidefinite matrix $P$ and a negative semidefinite matrix $S$, this atom represents the function\n\n$$\nf(x,y) = \\left[\\begin{array}{c} x \\\\\\\\ y \\end{array}\\right]^T\n\\left[\\begin{array}{cc} P \u0026 S \\\\\\\\ S^T \u0026 Q \\end{array}\\right]\n\\left[\\begin{array}{c} x \\\\\\\\ y \\end{array}\\right].\n$$\n- `saddle_quad_form(x, Y)`  \nThe quadratic form $x^TYx$, where $Y$ a positive semindefinite matrix.\n\n## Calculus rules\nSaddle functions can be scaled and composed by addition. DCP convex expressions are treated as saddle functions with\nno concave arguments, and DCP concave expressions are treated as saddle functions with no convex arguments.\nWhen adding two saddle functions, a variable may not appear as a convex variable in one expression and as a concave\nvariable in the other expression.\n\nNote that negating a saddle function switches the roles of the convex and concave arguments.  \nFor example, `-inner(x, y)` is equivalent to `inner(y, -x)`, not `inner(-x, y)`.\nThis might seem counterintuitive, especially for bi-affine functions, where both are DSP-compliant, but it is consistent with the fact that\n\n$$\n-\\min_x\\max_y x^T y = \\max_x\\min_y -x^T y \\neq \\min_x\\max_y - x^T y.\n$$\n\n## Saddle point problems\nTo create a saddle point problem, a `MinimizeMaximize` object is created first, which represents the objective function,\nusing\n```python\nobj = dsp.MinimizeMaximize(f)\n```\nwhere `f` is a DSP-compliant expression.\n\nThe syntax for specifying saddle point problems is\n```python\nproblem = dsp.SaddlePointProblem(obj, constraints, cvx_vars, ccv_vars)\n```\nwhere `obj` is the `MinimizeMaximize` object, `constraints` is a list of constraints, and `cvx_vars` and `ccv_vars` are\nlists of variables to be minimized and maximized over, respectively.\n\nEach constraint must be DCP, and can only involve variables that are either convex or concave.\nWhen the role of a variable can be inferred, it can be omitted from the list of convex or concave variables.\nThe role can be inferred either from a saddle atom, a DCP atom that is convex or concave, but not affine, or from a\nconstraint, when a variable appears in a constraint that involves variables with known roles.\n\nNevertheless, specifying the role of each variable can add clarity to the problem formulation, and is especially\nuseful for debugging.\n\nTo solve the problem, call `problem.solve()`. This returns the optimal saddle value, which is also stored in the\nproblem's `value` attribute. Further all `value` attribute of the variables are populated with their optimal values.\n\n## Saddle extremum functions\nA saddle extremum function has one of the forms\n\n$$\nG(x) = \\sup_{y \\in \\mathcal{Y}} f(x,y) \\quad \\text{or} \\quad\nH(y) = \\inf_{x \\in \\mathcal{X}} f(x,y),\n$$\n\nwhere $f$ is a saddle function, and $\\mathcal{X}$ and $\\mathcal{Y}$ are convex.\nSince the functions only depend on $x$ or $y$, respectively, the other variables have to be declared as\n`LocalVariable`s. Any `LocalVariable` can only be used in one saddle extremum function. The syntax for\ncreating a saddle extremum function is\n```python\ndsp.saddle_max(f, constraints)\ndsp.saddle_min(f, constraints)\n```\nwhere `f` is a DSP-compliant scalar saddle function, and `constraints` is a list of constraints, which can\nonly involve `LocalVariable`s. DSP-compliant saddle extremum functions are DCP-convex or DCP-concave, respectively,\nand as such can be used in DCP optimization problems.\n\nAn example of a saddle extremum function is\n```python\n# Creating variables\nx = cp.Variable(2)\n\n# Creating local variables\ny_loc = dsp.LocalVariable(2)\n\n# Convex in x, concave in y_loc\nf = dsp.saddle_inner(C @ x, y_loc)\n\n# maximizes over y_loc\nG = dsp.saddle_max(f, [y_loc \u003e= 0, cp.sum(y_loc) == 1])\n```\n\n## Saddle problems\nA saddle problem is a convex optimization problem that involves saddle extremum functions. Any DCP convex optimization\ncan include saddle extremum functions when they are DSP-compliant. Using the saddle extremum function `G` from above,\nwe can solve the following problem:\n```python\nprob = cp.Problem(cp.Minimize(G), [x \u003e= 0, cp.sum(x) == 1])\nprob.solve() # solving the problem\n\nprob.value # 1.6666666666666667\nx.value # array([0.66666667, 0.33333333])\n```\n\n## Citation\nIf you want to reference DSP in your research, please consider citing us by using the following BibTeX:\n\n```BibTeX\n@article{schiele2024dsp,\n  title = {Disciplined Saddle Programming},\n  author = {Schiele, Philipp and Luxenberg, Eric and Boyd, Stephen},\n  journal = {Transactions on Machine Learning Research},\n  year = {2024},\n  pages = {1--25},\n  url = {https://openreview.net/forum?id=KhMLfEIoUm},\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvxgrp%2Fdsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcvxgrp%2Fdsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvxgrp%2Fdsp/lists"}