Skip to content

Commit

Permalink
ProjectQ v0.4.2
Browse files Browse the repository at this point in the history
  • Loading branch information
damiansteiger committed Jan 31, 2019
2 parents 24d0cbf + f7bef17 commit 1513fb5
Show file tree
Hide file tree
Showing 26 changed files with 677 additions and 164 deletions.
2 changes: 2 additions & 0 deletions docs/projectq.ops.rst
Expand Up @@ -6,6 +6,7 @@ The operations collection consists of various default gates and is a work-in-pro
.. autosummary::

projectq.ops.BasicGate
projectq.ops.MatrixGate
projectq.ops.SelfInverseGate
projectq.ops.BasicRotationGate
projectq.ops.BasicPhaseGate
Expand Down Expand Up @@ -52,6 +53,7 @@ The operations collection consists of various default gates and is a work-in-pro
projectq.ops.UniformlyControlledRy
projectq.ops.UniformlyControlledRz
projectq.ops.StatePreparation
projectq.ops.FlipBits


Module contents
Expand Down
58 changes: 49 additions & 9 deletions docs/projectq.setups.decompositions.rst
Expand Up @@ -9,18 +9,23 @@ The decomposition package is a collection of gate decomposition / replacement ru
projectq.setups.decompositions.arb1qubit2rzandry
projectq.setups.decompositions.barrier
projectq.setups.decompositions.carb1qubit2cnotrzandry
projectq.setups.decompositions.cnot2cz
projectq.setups.decompositions.cnu2toffoliandcu
projectq.setups.decompositions.crz2cxandrz
projectq.setups.decompositions.entangle
projectq.setups.decompositions.globalphase
projectq.setups.decompositions.ph2r
projectq.setups.decompositions.qft2crandhadamard
projectq.setups.decompositions.qubitop2onequbit
projectq.setups.decompositions.r2rzandph
projectq.setups.decompositions.rx2rz
projectq.setups.decompositions.ry2rz
projectq.setups.decompositions.sqrtswap2cnot
projectq.setups.decompositions.stateprep2cnot
projectq.setups.decompositions.swap2cnot
projectq.setups.decompositions.time_evolution
projectq.setups.decompositions.toffoli2cnotandtgate
projectq.setups.decompositions.uniformlycontrolledr2cnot


Submodules
Expand All @@ -32,7 +37,7 @@ projectq.setups.decompositions.arb1qubit2rzandry module
.. automodule:: projectq.setups.decompositions.arb1qubit2rzandry
:members:
:undoc-members:


projectq.setups.decompositions.barrier module
---------------------------------------------
Expand All @@ -48,6 +53,13 @@ projectq.setups.decompositions.carb1qubit2cnotrzandry module
:members:
:undoc-members:

projectq.setups.decompositions.cnot2cz module
---------------------------------------------

.. automodule:: projectq.setups.decompositions.cnot2cz
:members:
:undoc-members:

projectq.setups.decompositions.cnu2toffoliandcu module
------------------------------------------------------

Expand All @@ -61,35 +73,42 @@ projectq.setups.decompositions.crz2cxandrz module
.. automodule:: projectq.setups.decompositions.crz2cxandrz
:members:
:undoc-members:

projectq.setups.decompositions.entangle module
----------------------------------------------

.. automodule:: projectq.setups.decompositions.entangle
:members:
:undoc-members:

projectq.setups.decompositions.globalphase module
-------------------------------------------------

.. automodule:: projectq.setups.decompositions.globalphase
:members:
:undoc-members:

projectq.setups.decompositions.ph2r module
------------------------------------------

.. automodule:: projectq.setups.decompositions.ph2r
:members:
:undoc-members:

projectq.setups.decompositions.qft2crandhadamard module
-------------------------------------------------------

.. automodule:: projectq.setups.decompositions.qft2crandhadamard
:members:
:undoc-members:


projectq.setups.decompositions.qubitop2onequbit module
-------------------------------------------------------

.. automodule:: projectq.setups.decompositions.qubitop2onequbit
:members:
:undoc-members:

projectq.setups.decompositions.r2rzandph module
-----------------------------------------------

Expand All @@ -110,7 +129,21 @@ projectq.setups.decompositions.ry2rz module
.. automodule:: projectq.setups.decompositions.ry2rz
:members:
:undoc-members:


projectq.setups.decompositions.sqrtswap2cnot module
---------------------------------------------------

.. automodule:: projectq.setups.decompositions.sqrtswap2cnot
:members:
:undoc-members:

projectq.setups.decompositions.stateprep2cnot module
----------------------------------------------------

.. automodule:: projectq.setups.decompositions.stateprep2cnot
:members:
:undoc-members:

projectq.setups.decompositions.swap2cnot module
-----------------------------------------------

Expand All @@ -124,14 +157,21 @@ projectq.setups.decompositions.time_evolution module
.. automodule:: projectq.setups.decompositions.time_evolution
:members:
:undoc-members:

projectq.setups.decompositions.toffoli2cnotandtgate module
----------------------------------------------------------

.. automodule:: projectq.setups.decompositions.toffoli2cnotandtgate
:members:
:undoc-members:


projectq.setups.decompositions.uniformlycontrolledr2cnot module
---------------------------------------------------------------

.. automodule:: projectq.setups.decompositions.uniformlycontrolledr2cnot
:members:
:undoc-members:


Module contents
---------------
Expand Down
197 changes: 197 additions & 0 deletions examples/variational_quantum_eigensolver.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion projectq/_version.py
Expand Up @@ -13,4 +13,4 @@
# limitations under the License.

"""Define version number here and read it from setup.py automatically"""
__version__ = "0.4.1"
__version__ = "0.4.2"
6 changes: 3 additions & 3 deletions projectq/backends/_circuits/_to_latex.py
Expand Up @@ -209,7 +209,7 @@ def _footer(settings):
Returns:
tex_footer_str (string): Latex document footer.
"""
return "\n\n\end{tikzpicture}\n\end{document}"
return "\n\n\\end{tikzpicture}\n\\end{document}"


class _Circ2Tikz(object):
Expand Down Expand Up @@ -329,7 +329,7 @@ def to_tikz(self, line, circuit, end=None):
self.is_quantum[l] = False
elif gate == Allocate:
# draw 'begin line'
add_str = "\n\\node[none] ({}) at ({},-{}) {{$\Ket{{0}}{}$}};"
add_str = "\n\\node[none] ({}) at ({},-{}) {{$\\Ket{{0}}{}$}};"
id_str = ""
if self.settings['gates']['AllocateQubitGate']['draw_id']:
id_str = "^{{\\textcolor{{red}}{{{}}}}}".format(cmds[i].id)
Expand Down Expand Up @@ -433,7 +433,7 @@ def _sqrtswap_gate(self, lines, ctrl_lines, daggered):
gate_str += ("\n\\node[xstyle] ({op}) at ({pos},-{line})\
{{\\scriptsize $\\frac{{1}}{{2}}{dagger}$}};"
).format(op=op_mid, line=midpoint, pos=pos,
dagger='^{{\dagger}}' if daggered else '')
dagger='^{{\\dagger}}' if daggered else '')

# add two vertical lines to connect circled 1/2
gate_str += "\n\\draw ({}) edge[edgestyle] ({});".format(
Expand Down
2 changes: 1 addition & 1 deletion projectq/backends/_circuits/_to_latex_test.py
Expand Up @@ -174,7 +174,7 @@ def test_body():
# CZ is two phases plus 2 from CNOTs + 2 from cswap + 2 from csqrtswap
assert code.count("phase") == 8
assert code.count("{{{}}}".format(str(H))) == 2 # 2 hadamard gates
assert code.count("{$\Ket{0}") == 3 # 3 qubits allocated
assert code.count("{$\\Ket{0}") == 3 # 3 qubits allocated
# 1 cnot, 1 not gate, 3 SqrtSwap, 1 inv(SqrtSwap)
assert code.count("xstyle") == 7
assert code.count("measure") == 1 # 1 measurement
Expand Down
18 changes: 16 additions & 2 deletions projectq/backends/_ibm/_ibm.py
Expand Up @@ -46,6 +46,7 @@ class IBMBackend(BasicEngine):
"""
def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
user=None, password=None, device='ibmqx4',
num_retries=3000, interval=1,
retrieve_execution=None):
"""
Initialize the Backend object.
Expand All @@ -62,6 +63,11 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
password (string): IBM Quantum Experience password
device (string): Device to use ('ibmqx4', or 'ibmqx5')
if use_hardware is set to True. Default is ibmqx4.
num_retries (int): Number of times to retry to obtain
results from the IBM API. (default is 3000)
interval (float, int): Number of seconds between successive
attempts to obtain results from the IBM API.
(default is 1)
retrieve_execution (int): Job ID to retrieve instead of re-
running the circuit (e.g., if previous run timed out).
"""
Expand All @@ -75,6 +81,8 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
self._verbose = verbose
self._user = user
self._password = password
self._num_retries = num_retries
self._interval = interval
self._probabilities = dict()
self.qasm = ""
self._measured_ids = []
Expand Down Expand Up @@ -256,11 +264,17 @@ def _run(self):
if self._retrieve_execution is None:
res = send(info, device=self.device,
user=self._user, password=self._password,
shots=self._num_runs, verbose=self._verbose)
shots=self._num_runs,
num_retries=self._num_retries,
interval=self._interval,
verbose=self._verbose)
else:
res = retrieve(device=self.device, user=self._user,
password=self._password,
jobid=self._retrieve_execution)
jobid=self._retrieve_execution,
num_retries=self._num_retries,
interval=self._interval,
verbose=self._verbose)

counts = res['data']['counts']
# Determine random outcome
Expand Down
74 changes: 47 additions & 27 deletions projectq/backends/_ibm/_ibm_http_client.py
Expand Up @@ -17,6 +17,7 @@
import requests
import getpass
import json
import signal
import sys
import time
from requests.compat import urljoin
Expand All @@ -35,7 +36,8 @@ def is_online(device):
return r.json()['state']


def retrieve(device, user, password, jobid):
def retrieve(device, user, password, jobid, num_retries=3000,
interval=1, verbose=False):
"""
Retrieves a previously run job by its ID.
Expand All @@ -46,12 +48,13 @@ def retrieve(device, user, password, jobid):
jobid (str): Id of the job to retrieve
"""
user_id, access_token = _authenticate(user, password)
res = _get_result(device, jobid, access_token)
res = _get_result(device, jobid, access_token, num_retries=num_retries,
interval=interval, verbose=verbose)
return res


def send(info, device='sim_trivial_2', user=None, password=None,
shots=1, verbose=False):
shots=1, num_retries=3000, interval=1, verbose=False):
"""
Sends QASM through the IBM API and runs the quantum circuit.
Expand Down Expand Up @@ -84,7 +87,9 @@ def send(info, device='sim_trivial_2', user=None, password=None,
execution_id = _run(info, device, user_id, access_token, shots)
if verbose:
print("- Waiting for results...")
res = _get_result(device, execution_id, access_token)
res = _get_result(device, execution_id, access_token,
num_retries=num_retries,
interval=interval, verbose=verbose)
if verbose:
print("- Done.")
return res
Expand Down Expand Up @@ -143,32 +148,47 @@ def _run(qasm, device, user_id, access_token, shots):


def _get_result(device, execution_id, access_token, num_retries=3000,
interval=1):
interval=1, verbose=False):
suffix = 'Jobs/{execution_id}'.format(execution_id=execution_id)
status_url = urljoin(_api_url, 'Backends/{}/queue/status'.format(device))

print("Waiting for results. [Job ID: {}]".format(execution_id))

for retries in range(num_retries):
r = requests.get(urljoin(_api_url, suffix),
params={"access_token": access_token})
r.raise_for_status()

r_json = r.json()
if 'qasms' in r_json:
qasm = r_json['qasms'][0]
if 'result' in qasm:
return qasm['result']
time.sleep(interval)
if device in ['ibmqx4', 'ibmqx5'] and retries % 60 == 0:
r = requests.get(status_url)
if verbose:
print("Waiting for results. [Job ID: {}]".format(execution_id))

original_sigint_handler = signal.getsignal(signal.SIGINT)

def _handle_sigint_during_get_result(*_):
raise Exception("Interrupted. The ID of your submitted job is {}."
.format(execution_id))

try:
signal.signal(signal.SIGINT, _handle_sigint_during_get_result)

for retries in range(num_retries):
r = requests.get(urljoin(_api_url, suffix),
params={"access_token": access_token})
r.raise_for_status()
r_json = r.json()
if 'state' in r_json and not r_json['state']:
raise DeviceOfflineError("Device went offline. The ID of your "
"submitted job is {}."
.format(execution_id))
if 'lengthQueue' in r_json:
print("Currently there are {} jobs queued for execution on {}."
.format(r_json['lengthQueue'], device))
if 'qasms' in r_json:
qasm = r_json['qasms'][0]
if 'result' in qasm and qasm['result'] is not None:
return qasm['result']
time.sleep(interval)
if device in ['ibmqx4', 'ibmqx5'] and retries % 60 == 0:
r = requests.get(status_url)
r_json = r.json()
if 'state' in r_json and not r_json['state']:
raise DeviceOfflineError("Device went offline. The ID of "
"your submitted job is {}."
.format(execution_id))
if verbose and 'lengthQueue' in r_json:
print("Currently there are {} jobs queued for execution "
"on {}."
.format(r_json['lengthQueue'], device))

finally:
if original_sigint_handler is not None:
signal.signal(signal.SIGINT, original_sigint_handler)

raise Exception("Timeout. The ID of your submitted job is {}."
.format(execution_id))

0 comments on commit 1513fb5

Please sign in to comment.