{"id":33183032,"url":"https://github.com/jtiosue/qubovert","last_synced_at":"2026-01-12T06:33:50.289Z","repository":{"id":43706164,"uuid":"197088901","full_name":"jtiosue/qubovert","owner":"jtiosue","description":"The one-stop package for formulating, simulating, and solving problems in boolean and spin form","archived":false,"fork":false,"pushed_at":"2024-12-21T04:08:40.000Z","size":1245,"stargazers_count":41,"open_issues_count":1,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-11-20T22:03:31.939Z","etag":null,"topics":["ising","optimization","quantum-computing","qubo"],"latest_commit_sha":null,"homepage":"https://jtiosue.github.io/qubovert","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/jtiosue.png","metadata":{"files":{"readme":"README.rst","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}},"created_at":"2019-07-16T00:10:25.000Z","updated_at":"2025-05-09T12:18:45.000Z","dependencies_parsed_at":"2023-11-14T17:02:38.828Z","dependency_job_id":null,"html_url":"https://github.com/jtiosue/qubovert","commit_stats":{"total_commits":197,"total_committers":2,"mean_commits":98.5,"dds":"0.040609137055837574","last_synced_commit":"16f21d29d26b74a349bc9fee43dcc3128013be22"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/jtiosue/qubovert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtiosue%2Fqubovert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtiosue%2Fqubovert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtiosue%2Fqubovert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtiosue%2Fqubovert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jtiosue","download_url":"https://codeload.github.com/jtiosue/qubovert/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jtiosue%2Fqubovert/sbom","scorecard":{"id":540036,"data":{"date":"2025-08-11","repo":{"name":"github.com/jtiosue/qubovert","commit":"16f21d29d26b74a349bc9fee43dcc3128013be22"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/13 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/publish_manylinus_wheels.yml:1","Warn: no topLevel permission defined: .github/workflows/publish_source.yml:1","Warn: no topLevel permission defined: .github/workflows/publish_windows_macos_wheels.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_manylinus_wheels.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_manylinus_wheels.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_manylinus_wheels.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_manylinus_wheels.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish_manylinus_wheels.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_manylinus_wheels.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_source.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_source.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_source.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_source.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_windows_macos_wheels.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_windows_macos_wheels.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish_windows_macos_wheels.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/jtiosue/qubovert/publish_windows_macos_wheels.yml/master?enable=pin","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2018-34 / GHSA-2fc2-6r4j-p65h","Warn: Project is vulnerable to: PYSEC-2021-856 / GHSA-5545-2q6w-2gh6","Warn: Project is vulnerable to: PYSEC-2019-108 / GHSA-9fq2-x9r6-wfmf","Warn: Project is vulnerable to: PYSEC-2018-33 / GHSA-cw6w-4rcx-xphc","Warn: Project is vulnerable to: PYSEC-2021-857 / GHSA-f7c7-j99h-c22f","Warn: Project is vulnerable to: GHSA-fpfv-jqm9-f5jm","Warn: Project is vulnerable to: PYSEC-2017-1 / GHSA-frgw-fgh6-9g52","Warn: Project is vulnerable to: PYSEC-2013-22 / GHSA-27x4-j476-jp5f","Warn: Project is vulnerable to: PYSEC-2025-49 / GHSA-5rjg-fvgr-3xxf","Warn: Project is vulnerable to: GHSA-cx63-2mw6-8hw5","Warn: Project is vulnerable to: PYSEC-2022-43012 / GHSA-r9hx-vwmv-q579","Warn: Project is vulnerable to: PYSEC-2022-43017 / GHSA-qwmp-2cf2-g9g6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T07:58:52.535Z","repository_id":43706164,"created_at":"2025-08-20T07:58:52.535Z","updated_at":"2025-08-20T07:58:52.535Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28336316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ising","optimization","quantum-computing","qubo"],"created_at":"2025-11-16T04:00:33.244Z","updated_at":"2026-01-12T06:33:50.285Z","avatar_url":"https://github.com/jtiosue.png","language":"Python","funding_links":[],"categories":["Quantum annealing"],"sub_categories":[],"readme":"qubovert\n========\n\nThe one-stop package for formulating, simulating, and solving problems in boolean and spin form.\n\n\n*master branch*\n\n.. image:: https://github.com/jtiosue/qubovert/workflows/build/badge.svg?branch=master\n    :target: https://github.com/jtiosue/qubovert/actions?query=workflow%3Abuild+branch%3Amaster\n    :alt: GitHub Actions CI\n.. image:: https://readthedocs.org/projects/qubovert/badge/?version=latest\n    :target: https://qubovert.readthedocs.io/en/latest/\n    :alt: Documentation Status\n.. image:: https://codecov.io/gh/jtiosue/qubovert/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/jtiosue/qubovert/branch/master\n    :alt: Code Coverage\n.. image:: https://img.shields.io/lgtm/grade/python/g/jtiosue/qubovert.svg?logo=lgtm\u0026logoWidth=18\n    :target: https://lgtm.com/projects/g/jtiosue/qubovert/context:python\n    :alt: Code Quality\n\n*dev branch*\n\n.. image:: https://github.com/jtiosue/qubovert/workflows/build/badge.svg?branch=dev\n    :target: https://github.com/jtiosue/qubovert/actions?query=workflow%3Abuild+branch%3Adev\n    :alt: GitHub Actions CI\n.. image:: https://readthedocs.org/projects/qubovert/badge/?version=dev\n    :target: https://qubovert.readthedocs.io/en/dev/\n    :alt: Documentation Status\n.. image:: https://codecov.io/gh/jtiosue/qubovert/branch/dev/graph/badge.svg\n    :target: https://codecov.io/gh/jtiosue/qubovert/branch/dev\n    :alt: Code Coverage\n\n*pypi distribution*\n\n.. image:: https://badge.fury.io/py/qubovert.svg\n    :target: https://badge.fury.io/py/qubovert\n    :alt: pypi dist\n.. image:: https://pepy.tech/badge/qubovert\n    :target: https://pepy.tech/project/qubovert\n    :alt: pypi dist downloads\n\n\nPlease see the `Repository \u003chttps://github.com/jtiosue/qubovert\u003e`_ and `Docs \u003chttps://qubovert.readthedocs.io\u003e`_. For examples/tutorials, see the `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_.\n\n\n.. contents::\n    :local:\n    :backlinks: top\n\n\nInstallation\n------------\n\nFor the stable release (same version as the *master* branch):\n\n.. code:: shell\n\n  pip install qubovert\n\n\nOr to install from source:\n\n.. code:: shell\n\n  git clone https://github.com/jtiosue/qubovert.git\n  cd qubovert\n  pip install -e .\n\n\nThen you can use it in Python **versions 3.6 and above** with\n\n.. code:: python\n\n    import qubovert as qv\n\n\nNote that to install from source on Windows you will need `Microsoft Visual C++ Build Tools 14 \u003chttps://visualstudio.microsoft.com/visual-cpp-build-tools/\u003e`_ installed.\n\n\nExample of the typical workflow\n-------------------------------\n\nHere we show an example of formulating a pseudo-boolean objective function. We can also make spin objective functions (Hamiltonians) in a very similar manner. See the `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_ for examples.\n\n\nCreate the boolean objective function to minimize\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code:: python\n\n    from qubovert import boolean_var\n\n    N = 10\n\n    # create the variables\n    x = {i: boolean_var('x(%d)' % i) for i in range(N)}\n\n    # minimize \\sum_{i=0}^{N-2} (1-2x_{i}) x_{i+1}\n    model = 0\n    for i in range(N-1):\n        model += (1 - 2 * x[i]) * x[i+1]\n\n    # subject to the constraint that x_1 equals the XOR of x_3 and x_5\n    # enforce with a penalty factor of 3\n    model.add_constraint_eq_XOR(x[1], x[3], x[5], lam=3)\n\n    # subject to the constraints that the sum of all variables is less than 4\n    # enforce with a penalty factor of 5\n    model.add_constraint_lt_zero(sum(x.values()) - 4, lam=5)\n\n\nNext we will show multiple ways to solve the model.\n\n\nSolving the model with bruteforce\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nBefore using the bruteforce solver, always check that ``model.num_binary_variables`` is relatively small!\n\n\n.. code:: python\n\n    model_solution = model.solve_bruteforce()\n    print(\"Variable assignment:\", model_solution)\n    print(\"Model value:\", model.value(model_solution))\n    print(\"Constraints satisfied?\", model.is_solution_valid(model_solution))\n\n\nSolving the model with *qubovert*'s simulated annealing\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nPlease see the definition of PUBO in the next section. We will anneal the PUBO.\n\n.. code:: python\n\n    from qubovert.sim import anneal_pubo\n\n    res = anneal_pubo(model, num_anneals=10)\n    model_solution = res.best.state\n\n    print(\"Variable assignment:\", model_solution)\n    print(\"Model value:\", res.best.value)\n    print(\"Constraints satisfied?\", model.is_solution_valid(model_solution))\n\n\nSolving the model with D-Wave's simulated annealer\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n`D-Wave's simulated annealer \u003chttps://github.com/dwavesystems/dwave-neal\u003e`_ cannot anneal PUBOs as we did above. Instead the model must be reduced to a QUBO. See the next section for definitions of QUBO and PUBO.\n\n.. code:: python\n\n    from neal import SimulatedAnnealingSampler\n\n    # Get the QUBO form of the model\n    qubo = model.to_qubo()\n\n    # D-Wave accept QUBOs in a different format than qubovert's format\n    # to get the qubo in this form, use the .Q property\n    dwave_qubo = qubo.Q\n\n    # solve with D-Wave\n    res = SimulatedAnnealingSampler().sample_qubo(dwave_qubo, num_reads=10)\n    qubo_solution = res.first.sample\n\n    # convert the qubo solution back to the solution to the model\n    model_solution = model.convert_solution(qubo_solution)\n\n    print(\"Variable assignment:\", model_solution)\n    print(\"Model value:\", model.value(model_solution))\n    print(\"Constraints satisfied?\", model.is_solution_valid(model_solution))\n\n\nManaging QUBO, QUSO, PUBO, PUSO, PCBO, and PCSO formulations\n------------------------------------------------------------\n\n*qubovert* defines, among many others, the following objects.\n\n- QUBO: Quadratic Unconstrained Boolean Optimization (``qubovert.QUBO``)\n- QUSO: Quadratic Unconstrained Spin Optimization (``qubovert.QUSO``)\n- PUBO: Polynomial Unconstrained Boolean Optimization (``qubovert.PUBO``)\n- PUSO: Polynomial Unconstrained Spin Optimization (``qubovert.PUSO``)\n- PCBO: Polynomial Constrained Boolean Optimization (``qubovert.PCBO``)\n- PCSO: Polynomial Constrained Spin Optimization (``qubovert.PCSO``)\n\nEach of the objects has many methods and arbitary arithmetic defined; see the docstrings of each object and the `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_ for more info. A boolean optimization model is one whose variables can be assigned to be either 0 or 1, while a spin optimization model is one whose variables can be assigned to be either 1 or -1. The ``qubovert.boolean_var(name)`` function will create a PCBO representing the boolean variable with name ``name``. Similarly, the ``qubovert.spin_var(name)`` function will create a PCSO representing the spin variable with name ``name``.\n\n\nThere are many utilities in the *utils* library that can be helpful. Some examples of utility functions are listed here.\n\n- ``qubovert.utils.solve_pubo_bruteforce``, solve a PUBO by iterating through all possible solutions.\n- ``qubovert.utils.solve_puso_bruteforce``, solve a PUSO by iterating through all possible solutions.\n- ``qubovert.utils.pubo_to_puso``, convert a PUBO to a PUSO.\n- ``qubovert.utils.puso_to_pubo``, convert a PUSO to a PUBO.\n- ``qubovert.utils.pubo_value``, determine the value that a PUBO takes with a particular solution mapping.\n- ``qubovert.utils.puso_value``, determine the value that a PUSO takes with a particular solution mapping.\n- ``qubovert.utils.approximate_pubo_extrema``, approximate the minimum and maximum values that a PUBO can take; the true extrema will lie within these bounds.\n- ``qubovert.utils.approximate_puso_extrema``, approximate the minimum and maximum values that a PUSO can take; the true extrema will lie within these bounds.\n- ``qubovert.utils.subgraph``, create the subgraph of a model that only contains certain given variables.\n- ``qubovert.utils.subvalue``, create the submodel of a model with certain values of the model replaced with values.\n- ``qubovert.utils.normalize``, normalize a model such that its coefficients have a maximum absolute magnitude.\n\nSee ``qubovert.utils.__all__`` for more. Please note that all conversions between boolean and spin map {0, 1} to/from {1, -1} in that order! This is the convention that *qubovert* uses everywhere.\n\n\nThe PCBO and PCSO objects have constraint methods; for example, the ``.add_constraint_le_zero`` method will enforce that an expression is less than or equal to zero by adding a penalty to the model whenever it does not. The PCBO object also has constraint methods for satisfiability expressions; for example, the ``.add_constraint_OR`` will enforce that the OR of the given boolean expression evaluates to True by adding a penalty to the model whenever it does not. See the docstrings and `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_ for more info.\n\n\nFor more utilities on satisfiability expressions, *qubovert* also has a *sat* library; see ``qubovert.sat.__all__``. Consider the following 3-SAT example. We have variables ``x0, x1, x2, x3``, labeled by ``0, 1, 2, 3``. We can create an expression ``C`` that evaluates to 1 whenever the 3-SAT conditions are satisfied.\n\n.. code:: python\n\n    from qubovert.sat import AND, NOT, OR\n\n    C = AND(OR(0, 1, 2), OR(NOT(0), 2, NOT(3)), OR(NOT(1), NOT(2), 3))\n\n    # C = 1 for a satisfying assignment, C = 0 otherwise\n    # So minimizing -C will solve it.\n    P = -C\n    solution = P.solve_bruteforce()\n\n\n\nBasic examples of common functionality\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nSee the `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_ for many fully worked out examples. Here we will just show some basic and brief examples.\n\n\nThe basic building block of a binary optimization model is a Python dictionary. The keys of the dictionary are tuples of variable names, and the values are their corresponding coefficients. For example, in the below code block, ``model1``, ``model2``, and ``model3`` are equivalent.\n\n.. code:: python\n\n    from qubovert import boolean_var, PUBO\n\n    x0, x1, x2 = boolean_var('x0'), boolean_var('x1'), boolean_var('x2')\n\n    model1 = -1 + x0 + 2 * x0 * x1 - 3 * x0 * x2 + x0 * x1 * x2\n    model2 = {(): -1, ('x0',): 1, ('x0', 'x1'): 2, ('x0', 'x2'): -3, ('x0', 'x1', 'x2'): 1}\n    model3 = PUBO(model2)\n\n\nSimilarly, in the below code block, ``model1``, ``model2``, and ``model3`` are equivalent.\n\n.. code:: python\n\n    from qubovert import spin_var, PUSO\n\n    z0, z1, z2 = spin_var('z0'), spin_var('z1'), spin_var('z2')\n\n    model1 = -1 + z0 + 2 * z0 * z1 - 3 * z0 * z2 + z0 * z1 * z2\n    model2 = {(): -1, ('z0',): 1, ('z0', 'z1'): 2, ('z0', 'z2'): -3, ('z0', 'z1', 'z2'): 1}\n    model3 = PUSO(model2)\n\n\n\nLet's take the same model from above (ie define :code:`model = model1.copy()`). Suppose we want to find the ground state of the model subject to the constraints that the sum of the variables is negative and that the product of ``z0`` and ``z1`` is 1. We have to enforce these constraints with a penalty called ``lam``. For now, let's set it as a Symbol that we can adjust later.\n\n.. code:: python\n\n    from sympy import Symbol\n\n    lam = Symbol('lam')\n    model.add_constraint_lt_zero(z0 + z1 + z2, lam=lam)\n    model.add_constraint_eq_zero(z0 * z1 - 1, lam=lam)\n\n\nNote that constraint methods can also be strung together if you want. So we could have written this as\n\n.. code:: python\n\n    model.add_constraint_lt_zero(\n        z0 + z1 + z2, lam=lam\n    ).add_constraint_eq_zero(\n        z0 * z1 - 1, lam=lam\n    )\n\n\nThe first thing you notice if you :code:`print(model.variables)` is that there are now new variables in the model called ``'__a0'`` and ``'__a1'``. These are auxillary or *ancilla* variables that are needed to enforce the constraints. The next thing to notice if you :code:`print(model.degree)` is that the model is a polynomial of degree 3. Many solvers (for example D-Wave's solvers) only solve degree 2 models. To get a QUBO or QUSO (which are degree two modes) from ``model``, simply call the ``.to_qubo`` or ``.to_quso`` methods, which will reduce the degree to 2 by introducing more variables.\n\n.. code:: python\n\n    qubo = model.to_qubo()\n    quso = model.to_quso()\n\n\nNext let's solve the QUBO and/or QUSO formulations. First we have to substitute a value in for our placeholder symbol ``lam`` that is used to enforce the constraints. We'll just use ``lam=3`` for now.\n\n.. code:: python\n\n    qubo = qubo.subs({lam: 3})\n    quso = quso.subs({lam: 3})\n\n\nHere we will use `D-Wave's simulated annealer \u003chttps://github.com/dwavesystems/dwave-neal\u003e`_.\n\n.. code:: python\n\n    from neal import SimulatedAnnealingSampler\n\n    # D-Wave represents QUBOs a little differently than qubovert does.\n    # to get D-Wave's form, use the .Q property\n    dwave_qubo = qubo.Q\n\n    # D-Wave represents QUSOs a little differently than qubovert does.\n    # to get D-Wave's form, use the .h property the linear terms and the\n    # .J property for the quadratic terms\n    dwave_linear, dwave_quadratic = quso.h, quso.J\n\n    # call dwave\n    qubo_res = SimulatedAnnealingSampler().sample_qubo(dwave_qubo)\n    quso_res = SimulatedAnnealingSampler().sample_ising(dwave_linear, dwave_quadratic)\n\n    qubo_solution = qubo_res.first.sample\n    quso_solution = quso_res.first.sample\n\n\nNow we have to convert the solution in terms of the QUBO/QUSO variables back to a solution in terms of the original variables. We can then check if the proposed solution satisfies all of the constraints!\n\n.. code:: python\n\n    converted_qubo_solution = model.convert_solution(qubo_solution)\n    print(model.is_solution_valid(converted_qubo_solution))\n\n    converted_quso_solution = model.convert_solution(quso_solution)\n    print(model.is_solution_valid(converted_quso_solution))\n\n\nConvert common problems to quadratic form (the *problems* library)\n------------------------------------------------------------------\n\nOne of the goals of *qubovert* is to become a large collection of problems mapped to QUBO and QUSO forms in order to aid the recent increase in study of these problems due to quantum optimization algorithms. Use Python's ``help`` function! I have very descriptive doc strings on all the functions and classes. Please see the `notebooks \u003chttps://github.com/jtiosue/qubovert/tree/master/notebook_examples\u003e`_ for a few more examples as well.\n\n\nSee the following Set Cover example.\n\n.. code:: python\n\n    from qubovert.problems import SetCover\n    from any_module import qubo_solver\n    # or you can use my bruteforce solver...\n    # from qubovert.utils import solve_qubo_bruteforce as qubo_solver\n\n    U = {\"a\", \"b\", \"c\", \"d\"}\n    V = [{\"a\", \"b\"}, {\"a\", \"c\"}, {\"c\", \"d\"}]\n\n    problem = SetCover(U, V)\n    Q = problem.to_qubo()\n\n    obj, sol = qubo_solver(Q)\n\n    solution = problem.convert_solution(sol)\n\n    print(solution)\n    # {0, 2}\n    print(problem.is_solution_valid(solution))\n    # will print True, since V[0] + V[2] covers all of U\n    print(obj == len(solution))\n    # will print True\n\nTo use the QUSO formulation instead:\n\n.. code:: python\n\n    from qubovert.problems import SetCover\n    from any_module import quso_solver\n    # or you can use my bruteforce solver...\n    # from qubovert.utils import solve_quso_bruteforce as quso_solver\n\n    U = {\"a\", \"b\", \"c\", \"d\"}\n    V = [{\"a\", \"b\"}, {\"a\", \"c\"}, {\"c\", \"d\"}]\n\n    problem = SetCover(U, V)\n    L = problem.to_quso()\n\n    obj, sol = quso_solver(L)\n\n    solution = problem.convert_solution(sol)\n\n    print(solution)\n    # {0, 2}\n    print(problem.is_solution_valid(solution))\n    # will print True, since V[0] + V[2] covers all of U\n    print(obj == len(solution))\n    # will print True\n\n\nTo see problem specifics, run\n\n.. code:: python\n\n    help(qubovert.problems.SetCover)\n    help(qubovert.problems.VertexCover)\n    # etc\n\n\n====\n\n.. image:: https://raw.githubusercontent.com/jtiosue/qubovert/master/assets/qvfire.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjtiosue%2Fqubovert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjtiosue%2Fqubovert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjtiosue%2Fqubovert/lists"}