parityos 2.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. parityos-2.1.1/License.txt +37 -0
  2. parityos-2.1.1/PKG-INFO +11 -0
  3. parityos-2.1.1/README.md +103 -0
  4. parityos-2.1.1/parityos/__init__.py +14 -0
  5. parityos-2.1.1/parityos/api_interface/__init__.py +13 -0
  6. parityos-2.1.1/parityos/api_interface/authentication.py +86 -0
  7. parityos-2.1.1/parityos/api_interface/compiler_run.py +83 -0
  8. parityos-2.1.1/parityos/api_interface/connection.py +138 -0
  9. parityos-2.1.1/parityos/api_interface/exceptions.py +27 -0
  10. parityos-2.1.1/parityos/base/__init__.py +7 -0
  11. parityos-2.1.1/parityos/base/circuit.py +142 -0
  12. parityos-2.1.1/parityos/base/constraints.py +90 -0
  13. parityos-2.1.1/parityos/base/exceptions.py +26 -0
  14. parityos-2.1.1/parityos/base/gates.py +361 -0
  15. parityos-2.1.1/parityos/base/problem_representation.py +279 -0
  16. parityos-2.1.1/parityos/base/qubits.py +57 -0
  17. parityos-2.1.1/parityos/base/utils.py +120 -0
  18. parityos-2.1.1/parityos/compiler_client.py +140 -0
  19. parityos-2.1.1/parityos/device_model.py +174 -0
  20. parityos-2.1.1/parityos/encodings/__init__.py +12 -0
  21. parityos-2.1.1/parityos/encodings/mappings.py +100 -0
  22. parityos-2.1.1/parityos/encodings/parity_decoder.py +259 -0
  23. parityos-2.1.1/parityos/encodings/parity_encoder.py +42 -0
  24. parityos-2.1.1/parityos/encodings/parityos_output.py +159 -0
  25. parityos-2.1.1/parityos.egg-info/PKG-INFO +11 -0
  26. parityos-2.1.1/parityos.egg-info/SOURCES.txt +105 -0
  27. parityos-2.1.1/parityos.egg-info/dependency_links.txt +1 -0
  28. parityos-2.1.1/parityos.egg-info/requires.txt +17 -0
  29. parityos-2.1.1/parityos.egg-info/top_level.txt +3 -0
  30. parityos-2.1.1/parityos_addons/documentation/__init__.py +0 -0
  31. parityos-2.1.1/parityos_addons/documentation/html/_images/hypergraph_solution_tutorial.png +0 -0
  32. parityos-2.1.1/parityos_addons/documentation/html/_images/hypergraph_tutorial.png +0 -0
  33. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/api_interface.rst.txt +6 -0
  34. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/base.rst.txt +14 -0
  35. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/encodings.rst.txt +11 -0
  36. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/index.rst.txt +11 -0
  37. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/parityos.rst.txt +6 -0
  38. parityos-2.1.1/parityos_addons/documentation/html/_sources/api_reference/parityos_addons.rst.txt +13 -0
  39. parityos-2.1.1/parityos_addons/documentation/html/_sources/asynchronous_submission.rst.txt +67 -0
  40. parityos-2.1.1/parityos_addons/documentation/html/_sources/custom_device_models.rst.txt +215 -0
  41. parityos-2.1.1/parityos_addons/documentation/html/_sources/index.rst.txt +14 -0
  42. parityos-2.1.1/parityos_addons/documentation/html/_sources/installation.rst.txt +33 -0
  43. parityos-2.1.1/parityos_addons/documentation/html/_sources/parity_decoder.rst.txt +69 -0
  44. parityos-2.1.1/parityos_addons/documentation/html/_sources/quickstart.rst.txt +220 -0
  45. parityos-2.1.1/parityos_addons/documentation/html/_sources/tutorial.rst.txt +432 -0
  46. parityos-2.1.1/parityos_addons/documentation/html/_static/_sphinx_javascript_frameworks_compat.js +123 -0
  47. parityos-2.1.1/parityos_addons/documentation/html/_static/basic.css +903 -0
  48. parityos-2.1.1/parityos_addons/documentation/html/_static/css/badge_only.css +1 -0
  49. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  50. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  51. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  52. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  53. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/fontawesome-webfont.eot +0 -0
  54. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  55. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  56. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/fontawesome-webfont.woff +0 -0
  57. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  58. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-bold-italic.woff +0 -0
  59. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  60. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-bold.woff +0 -0
  61. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-bold.woff2 +0 -0
  62. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-normal-italic.woff +0 -0
  63. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  64. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-normal.woff +0 -0
  65. parityos-2.1.1/parityos_addons/documentation/html/_static/css/fonts/lato-normal.woff2 +0 -0
  66. parityos-2.1.1/parityos_addons/documentation/html/_static/css/theme.css +4 -0
  67. parityos-2.1.1/parityos_addons/documentation/html/_static/doctools.js +156 -0
  68. parityos-2.1.1/parityos_addons/documentation/html/_static/documentation_options.js +14 -0
  69. parityos-2.1.1/parityos_addons/documentation/html/_static/file.png +0 -0
  70. parityos-2.1.1/parityos_addons/documentation/html/_static/jquery.js +2 -0
  71. parityos-2.1.1/parityos_addons/documentation/html/_static/js/badge_only.js +1 -0
  72. parityos-2.1.1/parityos_addons/documentation/html/_static/js/html5shiv-printshiv.min.js +4 -0
  73. parityos-2.1.1/parityos_addons/documentation/html/_static/js/html5shiv.min.js +4 -0
  74. parityos-2.1.1/parityos_addons/documentation/html/_static/js/theme.js +1 -0
  75. parityos-2.1.1/parityos_addons/documentation/html/_static/language_data.js +199 -0
  76. parityos-2.1.1/parityos_addons/documentation/html/_static/minus.png +0 -0
  77. parityos-2.1.1/parityos_addons/documentation/html/_static/plus.png +0 -0
  78. parityos-2.1.1/parityos_addons/documentation/html/_static/pygments.css +75 -0
  79. parityos-2.1.1/parityos_addons/documentation/html/_static/searchtools.js +566 -0
  80. parityos-2.1.1/parityos_addons/documentation/html/_static/sphinx_highlight.js +144 -0
  81. parityos-2.1.1/parityos_addons/documentation/html/api_reference/api_interface.html +215 -0
  82. parityos-2.1.1/parityos_addons/documentation/html/api_reference/base.html +723 -0
  83. parityos-2.1.1/parityos_addons/documentation/html/api_reference/encodings.html +337 -0
  84. parityos-2.1.1/parityos_addons/documentation/html/api_reference/index.html +131 -0
  85. parityos-2.1.1/parityos_addons/documentation/html/api_reference/parityos.html +607 -0
  86. parityos-2.1.1/parityos_addons/documentation/html/api_reference/parityos_addons.html +360 -0
  87. parityos-2.1.1/parityos_addons/documentation/html/asynchronous_submission.html +184 -0
  88. parityos-2.1.1/parityos_addons/documentation/html/custom_device_models.html +332 -0
  89. parityos-2.1.1/parityos_addons/documentation/html/genindex.html +625 -0
  90. parityos-2.1.1/parityos_addons/documentation/html/index.html +125 -0
  91. parityos-2.1.1/parityos_addons/documentation/html/installation.html +141 -0
  92. parityos-2.1.1/parityos_addons/documentation/html/objects.inv +0 -0
  93. parityos-2.1.1/parityos_addons/documentation/html/parity_decoder.html +188 -0
  94. parityos-2.1.1/parityos_addons/documentation/html/py-modindex.html +187 -0
  95. parityos-2.1.1/parityos_addons/documentation/html/quickstart.html +346 -0
  96. parityos-2.1.1/parityos_addons/documentation/html/search.html +126 -0
  97. parityos-2.1.1/parityos_addons/documentation/html/searchindex.js +1 -0
  98. parityos-2.1.1/parityos_addons/documentation/html/tutorial.html +513 -0
  99. parityos-2.1.1/parityos_addons/documentation/show.py +23 -0
  100. parityos-2.1.1/parityos_addons/interfaces/__init__.py +21 -0
  101. parityos-2.1.1/parityos_addons/interfaces/cirq_exporter.py +122 -0
  102. parityos-2.1.1/parityos_addons/interfaces/qiskit_exporter.py +121 -0
  103. parityos-2.1.1/parityos_addons/qaoa/__init__.py +11 -0
  104. parityos-2.1.1/parityos_addons/qaoa/qaoa_scheduler.py +104 -0
  105. parityos-2.1.1/parityos_addons/spin_hamiltonians.py +109 -0
  106. parityos-2.1.1/setup.cfg +4 -0
  107. parityos-2.1.1/setup.py +43 -0
@@ -0,0 +1,37 @@
1
+ ParityOS Client Software License Terms (BSD-3-Clause)
2
+ =====================================================
3
+
4
+ Copyright 2023 Parity Quantum Computing GmbH (ParityQC)
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its contributors
17
+ may be used to endorse or promote products derived from this software
18
+ without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ ===============================================================================
32
+
33
+ Parity Quantum Computing GmbH
34
+ Rennweg 1 / Top 314 / 6020 Innsbruck, Austria
35
+ info@parityqc.com / www.parityqc.com
36
+
37
+ ===============================================================================
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.1
2
+ Name: parityos
3
+ Version: 2.1.1
4
+ Summary: Python bindings to the ParityOS API
5
+ Home-page: https://parityqc.com/
6
+ Requires-Python: >=3.7
7
+ Provides-Extra: cirq
8
+ Provides-Extra: qiskit
9
+ Provides-Extra: spinz
10
+ Provides-Extra: all
11
+ License-File: License.txt
@@ -0,0 +1,103 @@
1
+ # ParityOS
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+ Copyright (c) 2020-2023.
6
+
7
+ This package contains the client software to use the ParityOS cloud service.
8
+
9
+ ## Installation
10
+ It is recommended to install this package in a separate Python `venv` or Conda environment.
11
+ ```commandline
12
+ # To create a standard Python environment:
13
+ python -m venv my_new_venv && source my_new_venv/bin/activate
14
+ # Or, alternatively, to create a Anaconda/Miniconda environment:
15
+ conda create --name my_new_conda_env && conda activate my_new_conda_env
16
+ ```
17
+
18
+ Installation is done with the following command:
19
+ ```commandline
20
+ pip install parityos
21
+ ```
22
+ This will install two Python libraries: `parityos` and `parityos_addons`.
23
+
24
+ Some addons depend on external libraries like Cirq, Sympy or Qiskit.
25
+ The `pip` command will resolve these dependencies automatically if you specify which addons you
26
+ want to include. E.g. to include dependencies for the `spin_hamiltonians` and `qiskit_exporter`
27
+ addons, use this command:
28
+ ```commandline
29
+ pip install 'parityos[spinz,qiksit]'
30
+ ```
31
+ or to use `spin_hamiltonians` and `cirq_exporter`:
32
+ ```commandline
33
+ pip install 'parityos[spinz,cirq]'
34
+ ```
35
+ These commands will make sure that additional dependencies like `sympy`, `qiskit` or `cirq`
36
+ are installed correctly.
37
+ If you want to make sure that all optional dependencies are included, use:
38
+ ```commandline
39
+ pip install 'parityos[all]'
40
+ ```
41
+
42
+
43
+ ## ParityOS
44
+ A Python package that provides the `CompilerClient` class to connect to
45
+ the ParityOS cloud service. The package defines data structures to construct
46
+ the inputs and to process the outputs from the ParityOS cloud service.
47
+
48
+ from parityos import CompilerClient, RectangularDigitalDevice
49
+
50
+ username = '' # Put here your ParityOS username or set the PARITYOS_USER environment variable.
51
+ compiler_client = CompilerClient(username)
52
+ device_model = RectangularDigitalDevice(4, 4)
53
+ parityos_output = compiler_client.compile(hamiltonian, device_model)
54
+
55
+ ## ParityOS Addons
56
+ Additional tools that help you to get the most out of the ParityOS framework.
57
+
58
+ ### addon documentation
59
+ Detailed documentation on how to use the ParityOS framework, including a
60
+ quickstart guide and a QAOA tutorial.
61
+
62
+ To open the documentation in your web browser, type the following command
63
+ on the command line:
64
+
65
+ python -m parityos_addons.documentation.show
66
+
67
+ ### addon spin_hamiltonians
68
+ A Python package that provides tools to construct a spin Hamiltonian as a product
69
+ of Pauli spin Z operators. An example:
70
+
71
+ from parityos_addons.spin_hamiltonians import spinz_to_hamiltonian, SpinZ as Z
72
+
73
+ hamiltonian = spinz_to_hamiltonian(
74
+ Z('a') + Z('b') - 2 * Z('c') + 4 * Z('a') * Z('b') - (Z('a') + Z('b')) * Z('c')
75
+ )
76
+
77
+ ### addon qaoa
78
+ A Python package that provides tools to construct a QAOA circuit from the
79
+ output returned by the ParityOS cloud service.
80
+
81
+ from parityos_addons.qaoa import generate_qaoa
82
+
83
+ parityos_circuit, parameter_bounds = generate_qaoa(parityos_output=parityos_output,
84
+ unitary_pattern='ZCX' * 4)
85
+
86
+ ### addon interfaces
87
+ Provides the tools to export quantum circuits from ParityOS to other
88
+ frameworks like Cirq or Qiskit. Here is an example with Qiskit:
89
+
90
+ from qiskit.circuit import Parameter
91
+ from parityos_addons.interfaces import QiskitExporter
92
+
93
+ # Map ParityOS parameters onto Qiskit parameters
94
+ parameter_map = {key: Parameter(str(key)) for key in parameter_bounds.keys()}
95
+ # Instantiate the exporter
96
+ qiskit_exporter = QiskitExporter(parameter_map=parameter_map, qubit_map=qubit_map)
97
+ # Convert the ParityOS circuit to a qiskit circuit
98
+ qiskit_circuit = qiskit_exporter.to_qiskit(parityos_circuit)
99
+
100
+ ## License
101
+ Since version 2.1.0, the ParityOS Client software package is made available
102
+ under the 3-Clause BSD License. See the file `License.txt` for details.
103
+
@@ -0,0 +1,14 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Tools to use the ParityOS cloud services.
10
+ """
11
+ from .base import ProblemRepresentation, ParityOSException, ParityOSImportError, Qubit
12
+ from .device_model import RectangularAnalogDevice, RectangularDigitalDevice
13
+ from .encodings import ParityOSOutput
14
+ from .compiler_client import CompilerClient
@@ -0,0 +1,13 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Tools to connect to the ParityOS cloud services and to process the results.
10
+ """
11
+ from .compiler_run import CompilerRun, CompilerRunStatus
12
+ from .connection import ClientBase
13
+ from .exceptions import ParityOSAuthError, ParityOSRequestError
@@ -0,0 +1,86 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2023.
7
+ All rights reserved.
8
+
9
+ Tools to authenticate with the ParityOS cloud services.
10
+ """
11
+ import getpass
12
+ import os
13
+ from typing import Dict, Iterator
14
+ import warnings
15
+
16
+
17
+ def generate_credentials(
18
+ username: str = None,
19
+ username_variable: str = "",
20
+ password_variable: str = "",
21
+ intents: int = 3,
22
+ ) -> Iterator[Dict[str, str]]:
23
+ """
24
+ Generates a series of JSON compatible dictionaries with a username and a password.
25
+ The username can be provided as an argument. Otherwise, it is taken from the given system
26
+ variable (this is tried only once), or requested from the user on the prompt.
27
+ For security reasons, the password can not be provided as an argument. It is either taken
28
+ from the given system variable (this is tried only once), or requested from the user on the
29
+ prompt.
30
+ The argument `intents` sets the maximum number of times to ask for a username or password,
31
+ either from the environment or from the prompt.
32
+ To make this generator fully non-interactive, set intents to 1 and set the correct system
33
+ variables.
34
+
35
+ :param str username: The username for the account on the server.
36
+ :param str username_variable: System variable to query for the username
37
+ :param str password_variable: System variable to query for the password
38
+ :param int intents: Maximum number of times to ask for a username or password.
39
+ """
40
+ # The credentials object allows for a number of intents to provide the password.
41
+ # First intent: get data from the environment variables or else from prompt.
42
+ username = username or _get_username(username, username_variable)
43
+ password = _get_password(password_variable=password_variable)
44
+ yield {"username": username, "password": password}
45
+
46
+ # The next intents are always interactive.
47
+ for intent in range(1, intents):
48
+ print("Login failed. Please provide the correct credentials.")
49
+ username = _get_username(username)
50
+ password = _get_password(password)
51
+ yield {"username": username, "password": password}
52
+
53
+
54
+ def _get_username(username: str = "", username_variable: str = "") -> str:
55
+ """
56
+ Ask for a username, either from the provided environment variable or on the prompt.
57
+ If a username argument is given, then this is shown as a suggestion on the prompt
58
+ and returned as the result if the user only types return.
59
+ """
60
+ if username_variable and not username:
61
+ username = os.getenv(username_variable)
62
+ if username:
63
+ return username
64
+
65
+ suggestion = f" [{username}]" if username else ""
66
+ username = input(f"ParityOS Username{suggestion}: ") or username
67
+ return username
68
+
69
+
70
+ def _get_password(password: str = "", password_variable: str = "") -> str:
71
+ """
72
+ Ask for a password, either from the provided environment variable or on the prompt.
73
+ If a password argument is given, then "***" is shown as a suggestion on the prompt
74
+ and the given value is returned as the result if the user only types return.
75
+ """
76
+ if password_variable and not password:
77
+ with warnings.catch_warnings():
78
+ warnings.simplefilter("ignore")
79
+ password = os.getenv(password_variable)
80
+
81
+ if password:
82
+ return password
83
+
84
+ suggestion = " [***]" if password else ""
85
+ password = getpass.getpass(f"ParityOS Password{suggestion}: ") or password
86
+ return password
@@ -0,0 +1,83 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Tools to process the results from the ParityOS cloud service.
10
+ """
11
+ from enum import Enum
12
+
13
+ from parityos.base import JSONMappingType
14
+
15
+
16
+ class CompilerRun:
17
+ """
18
+ Encapsulates a compiler run; has attributes which describe relevant times
19
+ at which they were submitted, started, and eventually finished or failed
20
+ (in which case, a reason for failure is also given).
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ id,
26
+ submission_id,
27
+ status,
28
+ submitted_at,
29
+ started_at=None,
30
+ finished_at=None,
31
+ failed_at=None,
32
+ failure_reason=None,
33
+ ):
34
+ """
35
+ :param id: id of the compiler run in ParityOS cloud database
36
+ :param submission_id: id of the submission which triggered compile run
37
+ :param status: status of the submission; see CompilerRunStatus enum
38
+ :param submitted_at: time at which run was queued for execution
39
+ :param started_at: time at which run started being executed
40
+ :param finished_at: time at which run was completed
41
+ :param failed_at: time at which run failed
42
+ :param failure_reason: reason for which run failed
43
+ """
44
+ self.id = id
45
+ self.submission_id = submission_id
46
+ self.status = CompilerRunStatus(status)
47
+ self.submitted_at = submitted_at
48
+ self.started_at = started_at
49
+ self.finished_at = finished_at
50
+ self.failed_at = failed_at
51
+ self.failure_reason = failure_reason
52
+
53
+ @classmethod
54
+ def from_json(cls, data: JSONMappingType) -> "CompilerRun":
55
+ """
56
+ Creates a CompilerRun object from a JSON-like data dictionary.
57
+ :return: a CompilerRun object
58
+ """
59
+ return cls(**data)
60
+
61
+ def __repr__(self):
62
+ args = (
63
+ self.id,
64
+ self.submission_id,
65
+ self.status.value,
66
+ self.submitted_at,
67
+ self.started_at,
68
+ self.finished_at,
69
+ self.failed_at,
70
+ self.failure_reason,
71
+ )
72
+ return f"{self.__class__.__name__}{args}"
73
+
74
+
75
+ class CompilerRunStatus(Enum):
76
+ """
77
+ Enum for compiler run status.
78
+ """
79
+
80
+ SUBMITTED = "S"
81
+ RUNNING = "R"
82
+ COMPLETED = "C"
83
+ FAILED = "F"
@@ -0,0 +1,138 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Tools to connect to the ParityOS cloud services.
10
+ """
11
+ from json.decoder import JSONDecodeError
12
+ from typing import Dict, Tuple
13
+
14
+ from requests import Session, Response
15
+ from requests.adapters import HTTPAdapter
16
+ from requests.packages.urllib3.util.retry import Retry
17
+
18
+ from parityos.api_interface.authentication import generate_credentials
19
+ from parityos.api_interface.exceptions import ParityOSAuthError, ParityOSRequestError
20
+
21
+
22
+ DEFAULT_HOST = "api.parityqc.com"
23
+
24
+ # Define environment variables that can hold the credentials for the default host.
25
+ DEFAULT_ENVIRONMENT = dict(
26
+ username_variable="PARITYOS_USER",
27
+ password_variable="PARITYOS_PASS",
28
+ )
29
+ # Define the environment variables that can hold the credentials for alternative hosts.
30
+ ALTERNATIVE_ENVIRONMENT = dict(
31
+ username_variable="PARITYOS_ALTUSER",
32
+ password_variable="PARITYOS_ALTPASS",
33
+ )
34
+
35
+
36
+ class ClientBase:
37
+ """
38
+ Base class that sets up HTTP parameters (authentication, API endpoints, and so on).
39
+ It should not be used directly unless you are debugging HTTP requests,
40
+ use parityos.CompilerClient instead.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ username: str = None,
46
+ host: str = DEFAULT_HOST,
47
+ url_prefix: str = "v1",
48
+ http_retries: int = 3,
49
+ http_timeout: int = 10,
50
+ http_backoff_factor: float = 0.02,
51
+ intents: int = 3,
52
+ ):
53
+ """
54
+ :param str username: ParityOS id of the user.
55
+ :param str host: ParityAPI host name.
56
+ :param str url_prefix: Prefix to REST API paths, used mostly for versioning.
57
+ :param int http_retries: Number of http retries.
58
+ :param int http_timeout: Maximum time in seconds to wait for a http response.
59
+ :param int http_backoff_factor: Http exponential backoff factor.
60
+ :param int intents: Maximum number of intents with different passwords.
61
+ """
62
+ self.username = username
63
+ self.host = host
64
+ self.url_prefix = url_prefix
65
+ self.base_url = f"https://{self.host}/{self.url_prefix}"
66
+ self.http_timeout = http_timeout
67
+ self.http_retries = http_retries
68
+ self.http_backoff_factor = http_backoff_factor
69
+ self.intents = intents
70
+ self._setup_connection()
71
+
72
+ def _setup_connection(self):
73
+ """
74
+ Connects to the ParityAPI server, logs the user in and stores the session token.
75
+ """
76
+ # Credentials are instantiated here so that the password information
77
+ # is garbage collected as soon as this method terminates.
78
+ self.http = Session()
79
+ adapter = HTTPAdapter(
80
+ max_retries=Retry(total=self.http_retries, backoff_factor=self.http_backoff_factor)
81
+ )
82
+ self.http.mount("https://", adapter)
83
+ self.username, token = self._get_authentication()
84
+ # Only the username is stored in self so that the password information
85
+ # can be garbage collected.
86
+ self.http.headers.update({"Authorization": f"Token {token}"})
87
+
88
+ def _get_authentication(self) -> Tuple[str, str]:
89
+ """
90
+ Log in on the server to obtain an authentication token for future requests.
91
+ """
92
+ # The credentials object allows for a number of intents to provide the password.
93
+ environment_variables = (
94
+ DEFAULT_ENVIRONMENT if self.host == DEFAULT_HOST else ALTERNATIVE_ENVIRONMENT
95
+ )
96
+ authentication_intents = generate_credentials(
97
+ self.username,
98
+ **environment_variables,
99
+ intents=self.intents,
100
+ )
101
+ for credentials_data in authentication_intents:
102
+ response = self.http.post(f"{self.base_url}/auth", data=credentials_data)
103
+ data = response.json()
104
+ if "token" in data:
105
+ return credentials_data["username"], data["token"]
106
+
107
+ # No authentication intents left after failed logins
108
+ username = credentials_data["username"]
109
+ raise ParityOSAuthError(f"Failed login for user {username} on server {self.host}.")
110
+
111
+ def _send_request(self, method: str, url: str, data: Dict = None) -> Response:
112
+ """
113
+ Send an http request
114
+
115
+ :param method: request method to use ('GET', 'POST', 'PUT', ... )
116
+ :param url: target url
117
+ :param data: payload data as a dictionary
118
+ :return: requests.Response object
119
+ """
120
+ try:
121
+ response = self.http.request(method, url=url, json=data, timeout=self.http_timeout)
122
+ except Exception as err:
123
+ message = f"Failed to receive valid response after at most {self.http_retries} retries."
124
+ err.args = (*err.args, message)
125
+ raise err
126
+
127
+ if response.ok:
128
+ return response
129
+ else:
130
+ try:
131
+ error_data = response.json()
132
+ except JSONDecodeError:
133
+ error_data = "None"
134
+
135
+ raise ParityOSRequestError(
136
+ f"{method} on {url}: {response.status_code}, {error_data}",
137
+ response=response,
138
+ )
@@ -0,0 +1,27 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Exceptions for errors from the ParityOS cloud services.
10
+ """
11
+ from requests.exceptions import RequestException
12
+
13
+
14
+ class ParityOSAuthError(RequestException, ValueError):
15
+ """
16
+ Exception for failed logins to the ParityAPI server.
17
+ """
18
+
19
+ pass
20
+
21
+
22
+ class ParityOSRequestError(RequestException):
23
+ """
24
+ Exception for failed logins to the ParityAPI server.
25
+ """
26
+
27
+ pass
@@ -0,0 +1,7 @@
1
+ from .circuit import Circuit
2
+ from .constraints import EqualityConstraint
3
+ from .exceptions import ParityOSException, ParityOSImportError
4
+ from .gates import Gate, CNOT, H, X, Y, Z, Rx, Ry, Rz, Rzz
5
+ from .problem_representation import ProblemRepresentation
6
+ from .qubits import Qubit
7
+ from .utils import json_wrap, dict_filter, JSONType, JSONMappingType, JSONLoadSaveMixin
@@ -0,0 +1,142 @@
1
+ """
2
+ Parity Quantum Computing GmbH
3
+ Rennweg 1 Top 314
4
+ 6020 Innsbruck, Austria
5
+
6
+ Copyright (c) 2020-2022.
7
+ All rights reserved.
8
+
9
+ Classes that store information on sequences of quantum gates
10
+ """
11
+ from math import pi
12
+ from typing import Iterator, Mapping, Set, Union
13
+
14
+ from parityos.base.qubits import Qubit
15
+ from parityos.base.gates import Gate, CNOT, Rx, Ry, Rz, Rzz
16
+ from parityos.base.utils import json_wrap, JSONLoadSaveMixin
17
+ from parityos.base.exceptions import ParityOSException
18
+
19
+
20
+ class Circuit(JSONLoadSaveMixin, list):
21
+ """
22
+ A sequence of Gate and/or Circuit objects.
23
+ """
24
+
25
+ @property
26
+ def qubits(self) -> Set[Qubit]:
27
+ """
28
+ :return: All qubits from the elements in the circuit
29
+ """
30
+ return set().union(*(element.qubits for element in self))
31
+
32
+ @classmethod
33
+ def from_json(cls, data):
34
+ """
35
+ Creates a Circuit from a list of elements in json
36
+
37
+ :param data: a list of elements in json format
38
+ :return: a Circuit object
39
+ """
40
+ data = _remove_empty_lists(data)
41
+ args = (
42
+ Gate.from_json(element_data)
43
+ if isinstance(element_data[0], str)
44
+ else cls.from_json(element_data)
45
+ for element_data in data
46
+ )
47
+ return cls(args)
48
+
49
+ def to_json(self):
50
+ """
51
+ Converts the Container to json
52
+
53
+ :return: a list with the elements of the circuit in json format
54
+ """
55
+ return [json_wrap(element) for element in self]
56
+
57
+ def remap(self, context: Mapping = None, **kwargs) -> "Circuit":
58
+ """
59
+ Creates a copy of the circuit where the remap has been applied to all parametrized gates
60
+ in the circuit (see `gates.RMixin.remap` for details).
61
+
62
+ :param context: a mapping of parameter names (strings) to parameter values (number-like
63
+ objects) or to new parameter names (strings).
64
+ """
65
+ return Circuit((element.remap(context=context, **kwargs) for element in self))
66
+
67
+ def __repr__(self):
68
+ args = ", ".join(repr(element) for element in self)
69
+ return f"{self.__class__.__name__}([{args}])"
70
+
71
+
72
+ CircuitElement = Union[Gate, Circuit]
73
+ HALF_PI = 0.5 * pi
74
+
75
+
76
+ def convert_cnots_to_rzzs(circuit: Circuit) -> Circuit:
77
+ """
78
+ ZZ rotations instead of CNOTs.
79
+
80
+ Replaces the standards CNOTs on the optimized circuit with an equivalent implementation based on
81
+ ZZ and local rotations. The resulting circuit will contain additional subcircuits to account
82
+ for the necessary Rx, Ry and Rz rotations.
83
+
84
+ :param circuit: a circuit containing moments with CNOT gates.
85
+ :type circuit: Circuit
86
+ :return: a new circuit where all CNOTs have been replaced by ZZ and local rotations.
87
+ :rtype: Circuit
88
+ """
89
+ new_circuit = Circuit()
90
+ for subcircuit in circuit:
91
+ if not isinstance(subcircuit, Circuit):
92
+ # This situation can occur when gates and subcircuits were mixed together at the same
93
+ # level. We raise an error in this case, because this method expects gates to be grouped
94
+ # in moments (i.e. parallelizable subcircuits).
95
+ raise ParityOSException(
96
+ "Unexpected mix of gates and subcircuits encountered. Please "
97
+ "organize gates in moments (parallelizable subcircuits)."
98
+ )
99
+ elif all(isinstance(element, Gate) for element in subcircuit):
100
+ new_circuit.extend(_convert_moment(subcircuit))
101
+ else:
102
+ new_circuit.append(convert_cnots_to_rzzs(subcircuit))
103
+
104
+ return new_circuit
105
+
106
+
107
+ def _convert_moment(circuit) -> Iterator[Circuit]:
108
+ """
109
+ A helper function for convert_cnots_to_rzzs.
110
+ Lowest level circuits are expanded and have cnots turned into rzzs. This results in additional
111
+ circuits to be added before and after the moment circuit to account for the necessary Rx, Ry
112
+ and Rz rotations.
113
+
114
+ :return: a list of circuits representing the original circuit where cnots have been converted to
115
+ rzz gates.
116
+ """
117
+ before, moment, after1, after2 = Circuit(), Circuit(), Circuit(), Circuit()
118
+ # Representing a Cnot as a ZZ interaction requires the injection of a moment before and two
119
+ # moments after the original moment.
120
+ for gate in circuit:
121
+ if not isinstance(gate, CNOT):
122
+ # Copy the other gates directly to the new moment.
123
+ moment.append(gate)
124
+ else:
125
+ control, target = gate.qubit_list
126
+ # Add the necessary rotation before the ZZ interaction.
127
+ before.append(Ry(target, -HALF_PI))
128
+ # Replace the CNOT with a ZZ rotation.
129
+ moment.append(Rzz(control, target, -HALF_PI))
130
+ # Add the remaining rotations after the ZZ interaction.
131
+ after1.append(Rx(target, HALF_PI))
132
+ after2.append(Rz(control, HALF_PI))
133
+ after2.append(Rz(target, HALF_PI))
134
+
135
+ return (subcircuit for subcircuit in [before, moment, after1, after2] if subcircuit)
136
+
137
+
138
+ def _remove_empty_lists(data):
139
+ empty_list = []
140
+ for _ in range(data.count(empty_list)):
141
+ data.remove(empty_list)
142
+ return data