Coder Social home page Coder Social logo

pytket-extensions's Introduction

This repository is archived.

See this page for details of the currently-supported extensions.

pytket-extensions's People

Contributors

burgholzer avatar calmaccq avatar cqc-alec avatar cqc-melf avatar dhaycraft avatar drzenharper avatar eendebakpt avatar ferbetanzo avatar irfankhan10 avatar isobelhooper avatar johnchildren avatar lmondada avatar mlk621 avatar roland-djee avatar sjdilkes avatar ss2165 avatar vanyae-cqc avatar yao-cqc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pytket-extensions's Issues

Separate docs for each extension

Currently the docs are built monolithically, by running make html from the docs directory, which builds and indexes docs for all extensions together. But when we release an update to one extension we need to be able to update the docs for that extension only.

This means giving each module its own docs build, and probably publishing them into subdirectories of https://cqcl.github.io/pytket/build/html/extensions/ instead of having a flat structure.

[pytket-qiskit] IBMQBackend / IBMQEmulatorBackend don't work with IBMQFactory.enable_account()

I tried to use IBMQ.enable_account() to set up credentials for IBMQBackend rather than using IBMQ.save_account(), as I have a workflow where we want to not save credentials to disk.

But it looks like IBMQBackend only looks for credentials in three places:

  • where IBMQ.save_account() saves them
  • qiskitrc file if there is one
  • a Pytket config file for pytket-qiskit, if there is one

and all of those look for the credentials on disk, and can't do anything with the qiskit AccountProvider that .enable_account() returns.

This could be fixed with an optional extra AccountProvider parameter to IBMQBackend and IBMQEmulatorBackend. If this is passed, then rather than using stored credentials and the parameters passed in, you could instead use the credentials and the hub/project/group in the passed AccountProvider.

Will make a PR for this.

[pytket-braket] BraketBackend.circuit_status relies on the past state of its internal cache

I've run into an error in a workflow that uses a new BraketBackend instance for each step of processing. In this case:

  • BraketBackend.get_result calls self.circuit_status to get the result and put it into the BraketBackend result cache.
  • self.circuit_status assumes that we already have our particular ResultHandle in the cache and thus directly does self._cache[handle].update.

This is okay if we used the same BraketBackend to process the circuits and to retrieve the results, but if we don't then the cache is empty when it comes to getting the results, and we get a KeyError on self._cache[handle].

I think we could fix this by creating self._cache[handle] if it doesn’t exist, as is done in the Honeywell backend.

Will open a PR for this.

[pytket-cirq] Unused qubits not included in state returned by CirqStateSimBackend

Can be seen in comparison with AerStateBackend:

from pytket.extensions.cirq import CirqStateSimBackend
from pytket.extensions.qiskit import AerStateBackend
from pytket import Circuit
cirq_state = CirqStateSimBackend()
c = Circuit(2).X(1)
print(cirq_state.get_state(c))
aer_state = AerStateBackend()
print(aer_state.get_state(c))
array([0.+0.j, 1.+0.j)
array([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j])

pytket-braket relies on setting credentials in the AWS CLI

I'd like to use pytket-braket in an automated fashion, and so it would be good to have a way to pass credentials into BraketBackend programmatically, rather than relying on the AWS CLI.

This might be doable if BraketBackend took an optional argument of a boto3 Session, which can take credentials directly, or a braket AwsSession which can take a boto3.Session.

I'll work on a PR for this if that's okay.

[pytket-qiskit] Get rid of deprecation warnings.

With qiskit 0.28 we get the following deprecation warnings when running the tests:

  /home/alec/r/pytket-extensions/modules/pytket-qiskit/pytket/extensions/qiskit/tket_backend.py:101: DeprecationWarning: The BaseBackend abstract interface is deprecated as of the 0.18.0 release and will be removed in a future release. Instead you should build your backends using the BackendV1 abstract class (which is the current latest version of the backend interface)
    super().__init__(configuration=config, provider=None)

and

  /home/alec/r/pytket-extensions/modules/pytket-qiskit/pytket/extensions/qiskit/tket_job.py:39: DeprecationWarning: The BaseJob abstract interface is deprecated as of the 0.18.0 release and will be removed in a future release. Instead you should build your backends using the JobV1 abstract class (which is the current latest version of the backend interface)
    super().__init__(backend, str(handles[0]))

[pytket-qiskit] Support qiskit 0.24.

Note that updating the qiskit version to 0.24.0 causes test_tketautopass to fail. apparently because a qiskit.providers.ibmq.IBMQBackend is no longer an instance of a qiskit.providers.BaseBackend, meaning that we can't construct a TketAutoPass from one. (IBMQ credentials required to run this test.)

[pytket-cirq] Document cirq backends.

The docs build currently includes only cirq_to_tk, tk_to_cirq and process_characterisation from pytket-cirq. It should include the backends as well.

Error when trying to compile Qiskit parameterised circuits

If I have a circuit containing qiskit Parameter objects, I can convert back and forth between qiskit and pytket using qiskit_to_tk and tk_to_qiskit but I get an error when I try to compile the circuits. Is this a bug, or is this not something that is supported?

I have pytket v0.9.0 and pytket-qiskit v0.9.1 installed through pip.

Example

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from pytket.extensions.qiskit import qiskit_to_tk, tk_to_qiskit, IBMQBackend

circ = QuantumCircuit(2)
circ.rx(Parameter('a'),0,)
circ.ry(Parameter('b'),1)
circ.cx(0,1)
# circ.draw()

pytket_circ = qiskit_to_tk(circ)
final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()

pytket_backend = IBMQBackend(
    'ibmq_santiago',
    hub='ibm-q',
    group='open',
    project='main',
)
pytket_backend.compile_circuit(pytket_circ, optimisation_level=2)

final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()

gives an error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-bb05aab7fce3> in <module>
     19     project='main',
     20 )
---> 21 pytket_backend.compile_circuit(pytket_circ, optimisation_level=2)

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/pytket/backends/backend.py in compile_circuit(self, circuit, optimisation_level)
    141         :type optimisation_level: int, optional
    142         """
--> 143         self.default_compilation_pass(optimisation_level).apply(circuit)
    144 
    145     @property

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/pytket/extensions/qiskit/backends/ibm.py in _tk1_to_x_sx_rz(a, b, c)
    111 def _tk1_to_x_sx_rz(a: float, b: float, c: float) -> Circuit:
    112     circ = Circuit(1)
--> 113     if _approx_0_mod_2(b):
    114         circ.Rz(a + c, 0)
    115     elif _approx_0_mod_2(b + 1):

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/pytket/extensions/qiskit/backends/ibm.py in _approx_0_mod_2(x, eps)
    106 def _approx_0_mod_2(x: float, eps: float = 1e-10) -> bool:
    107     x %= 2
--> 108     return min(x, 2 - x) < eps
    109 
    110 

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/sympy/core/relational.py in __bool__(self)
    393 
    394     def __bool__(self):
--> 395         raise TypeError("cannot determine truth value of Relational")
    396 
    397     def _eval_as_set(self):

TypeError: cannot determine truth value of Relational

But if I bind the parameters first everything works fine:

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from pytket.extensions.qiskit import qiskit_to_tk, tk_to_qiskit, IBMQBackend

circ = QuantumCircuit(2)
circ.rx(Parameter('a'),0,)
circ.ry(Parameter('b'),1)
circ.cx(0,1)
circ = circ.bind_parameters([1,1])
# circ.draw()

pytket_circ = qiskit_to_tk(circ)
final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()

pytket_backend = IBMQBackend(
    'ibmq_santiago',
    hub='ibm-q',
    group='open',
    project='main',
)
pytket_backend.compile_circuit(pytket_circ, optimisation_level=2)

final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()
print(final_circ)
global phase: π
                                                                        
node_0: ────────────────────────────────────────────────────────────────
           ┌────┐  ┌────────────┐    ┌────┐    ┌───────┐           ┌───┐
node_1: ───┤ √X ├──┤ RZ(10.425) ├────┤ √X ├────┤ RZ(π) ├───────────┤ X ├
        ┌──┴────┴─┐└───┬────┬───┘┌───┴────┴───┐└─┬────┬┘┌─────────┐└─┬─┘
node_2: ┤ RZ(π/2) ├────┤ √X ├────┤ RZ(10.425) ├──┤ √X ├─┤ RZ(π/2) ├──■──
        └─────────┘    └────┘    └────────────┘  └────┘ └─────────┘     

[pytket-cirq] Cirq 0.11 breaks pytket-cirq

pytket-cirq has the requirement cirq ~= 0.10, which accepts 0.11 (released yesterday). This breaks some of our code:

ModuleNotFoundError: No module named 'cirq.devices'

We should (a) make pytket-cirq compatible with cirq 0.11, and (b) change the requirement to cirq ~= 0.11.0 so that this doesn't happen next time.

[pytket-qiskit] Compilation of circuit containg a `SetBits` operation succeeds.

Although compilation succeeds, the circuit is still invalid for the backend.

from pytket import Circuit
from pytket.extensions.qiskit import IBMQBackend
c = Circuit(1,1)
c.add_c_setbits([True], [0])
c.measure_all()
b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main")
b.compile_circuit(c)
b.process_circuit(c, n_shots=1)

Error:

CircuitNotValidError: Circuit with index 0 in submitted does not satisfy GateSetPredicate:{ SX Measure noop CX U1 U2 U3 Reset X Barrier Rz } (try running backend.compile_circuit(circuit) first).

[pytket-qiskit] `test_device` takes too long

The test_device test (which is not run on the CI because it requires IBMQ credentials) takes far too long. (There are thousands of jobs on the queue for ibmq_santiago.) We should probably just delete it.

[pytket-qiskit] Compiling does not fully preserve parameter objects, breaking dictionary based binding

If I compile parameterised circuits using pytket the circuit returned contains parameter objects that have the same names, but do not pass == tests with the original parameter objects used to build the circuit. This means the original parameter objects cannot be used to bind values using a dictionary.

I have pytket 0.10.0 installed, and I have the up-to-date develop branch of pytket-qiskit (commit c50f7c2) installed.

This is an example of the problem:

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from pytket.extensions.qiskit import qiskit_to_tk, tk_to_qiskit, IBMQBackend

param_a = Parameter('a')
param_b = Parameter('b')

circ = QuantumCircuit(2)
circ.rx(param_a,0,)
circ.ry(param_b,1)
circ.cx(0,1)
# circ.draw()

print(circ.parameters)
print(param_a in circ.parameters)
print(param_b in circ.parameters)

pytket_circ = qiskit_to_tk(circ)
final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()

pytket_backend = IBMQBackend(
    'ibmq_santiago',
    hub='ibm-q',
    group='open',
    project='main',
)
pytket_backend.compile_circuit(pytket_circ, optimisation_level=2)

final_circ = tk_to_qiskit(pytket_circ)
# final_circ.draw()

print(final_circ.parameters)
print(param_a in final_circ.parameters)
print(param_b in final_circ.parameters)

param_dict = dict(zip([param_a, param_b], [1, 2]))
final_circ.bind_parameters(param_dict)

This gives output:

ParameterView([Parameter(a), Parameter(b)])
True
True
ParameterView([Parameter(a), Parameter(b)])
False
False
---------------------------------------------------------------------------
CircuitError                              Traceback (most recent call last)
<ipython-input-5-57fb80c7dd47> in <module>
     36 
     37 param_dict = dict(zip([param_a, param_b], [1, 2]))
---> 38 final_circ.bind_parameters(param_dict)

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/qiskit/utils/deprecation.py in wrapper(*args, **kwargs)
     54             if kwargs:
     55                 _rename_kwargs(func.__name__, kwargs, kwarg_map)
---> 56             return func(*args, **kwargs)
     57         return wrapper
     58     return decorator

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py in bind_parameters(self, values, value_dict)
   2084                 raise TypeError(
   2085                     'Found ParameterExpression in values; use assign_parameters() instead.')
-> 2086             return self.assign_parameters(values)
   2087         else:
   2088             if any(isinstance(value, ParameterExpression) for value in values):

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/qiskit/utils/deprecation.py in wrapper(*args, **kwargs)
     54             if kwargs:
     55                 _rename_kwargs(func.__name__, kwargs, kwarg_map)
---> 56             return func(*args, **kwargs)
     57         return wrapper
     58     return decorator

/opt/anaconda3/envs/qiskit0.25.2-qcoptim/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py in assign_parameters(self, parameters, inplace, param_dict)
   2048                                      if param_key not in unsorted_parameters]
   2049             if len(params_not_in_circuit) > 0:
-> 2050                 raise CircuitError('Cannot bind parameters ({}) not present in the circuit.'.format(
   2051                     ', '.join(map(str, params_not_in_circuit))))
   2052 

CircuitError: 'Cannot bind parameters (a, b) not present in the circuit.'

[pytket-qiskit] Eliminate deprecation warnings

A full run of the pytket-qiskit tests generates quite a lot of deprecation warnings. Let's try and get rid of these.

PendingDeprecationWarning: Using a qobj for run() is deprecated and will be removed in a future release.
    return func(*args, **kwargs)

PendingDeprecationWarning: The `QasmSimulator` backend will be deprecated in the future. It has been superseded by the `AerSimulator` backend.
    warn('The `QasmSimulator` backend will be deprecated in the'

DeprecationWarning: Passing a Qobj to Backend.run is deprecated and will be removed in a future release. Please pass in circuits or pulse schedules instead.
    job = self._backend.run(qobj)

PendingDeprecationWarning: The `snapshot_expectation_value` circuit method will be deprecated  in the future. It has been superseded by the `save_expectation_value` and `save_expectation_value_variance` circuit methods.
    warn('The `snapshot_expectation_value` circuit method will be deprecated '

PendingDeprecationWarning: The `SnapshotExpectationValue` instruction will be deprecated in the future. It has been superseded by the `SaveExpectationValue` and `SaveExpectationValueVariance` instructions.
    warn('The `SnapshotExpectationValue` instruction will be deprecated in the'

DeprecationWarning: Back-references to from Bit instances to their containing Registers have been deprecated. Instead, inspect Registers to find their contained Bits.
    qubits = [self.qregmap[qbit.register][qbit.index] for qbit in qargs]

DeprecationWarning: Back-references to from Bit instances to their containing Registers have been deprecated. Instead, inspect Registers to find their contained Bits.
    bits = [self.cregmap[bit.register][bit.index] for bit in cargs]

PendingDeprecationWarning: The `UnitarySimulator` backend will be deprecated in the future. It has been superseded by the `AerSimulator` backend. To obtain legacy functionality initalize with `AerSimulator(method="unitary")` and append run circuits with the `save_state` instruction.
    warn('The `UnitarySimulator` backend will be deprecated in the'

DeprecationWarning: Passing a Qobj to Backend.run is deprecated and will be removed in a future release. Please pass in circuits or pulse schedules instead.
    return super().run(circuits, job_name=job_name, job_share_level=job_share_level,

DeprecationWarning: The QuantumCircuit.cu1 method is deprecated as of 0.16.0. It will be removed no earlier than 3 months after the release date. You should use the QuantumCircuit.cp method instead, which acts identically.
    qc.cu1(pi / 5, qr[2], qr[3])

DeprecationWarning: The QuantumCircuit.cu3 method is deprecated as of 0.16.0. It will be removed no earlier than 3 months after the release date. You should use the QuantumCircuit.cu method instead, where cu3(ϴ,φ,λ) = cu(ϴ,φ,λ,0).
    qc.cu3(pi / 4, pi / 5, pi / 6, qr[3], qr[0])

DeprecationWarning: The QuantumCircuit.u1 method is deprecated as of 0.16.0. It will be removed no earlier than 3 months after the release date. You should use the QuantumCircuit.p method instead, which acts identically.
    qc.u1(pi / 2, qr[1])

DeprecationWarning: The QuantumCircuit.u2 method is deprecated as of 0.16.0. It will be removed no earlier than 3 months after the release date. You can use the general 1-qubit gate QuantumCircuit.u instead: u2(φ,λ) = u(π/2, φ, λ). Alternatively, you can decompose it interms of QuantumCircuit.p and QuantumCircuit.sx: u2(φ,λ) = p(π/2+φ) sx p(λ-π/2) (1 pulse on hardware).
    qc.u2(pi / 2, pi / 3, qr[2])

DeprecationWarning: The QuantumCircuit.u3 method is deprecated as of 0.16.0. It will be removed no earlier than 3 months after the release date. You should use QuantumCircuit.u instead, which acts identically. Alternatively, you can decompose u3 in terms of QuantumCircuit.p and QuantumCircuit.sx: u3(ϴ,φ,λ) = p(φ+π) sx p(ϴ+π) sx p(λ) (2 pulses on hardware).
    qc.u3(pi / 2, pi / 3, pi / 4, qr[3])

[pytket-pyquil] ForestBackend relies on self._cache to retrieve results

ForestBackend uses self._cache to store two items from .process_results(), and relies on them being set for .get_results():

  • c_bits, the classical bits used in the quantum circuit.
  • qam, a PyQuil Quantum Abstract Machine, which is an interface over the machine running the circuit.

This means that ForestBackend won't currently work in a workflow that has different backend instances for process_results() and `get_results().

c_bits could potentially be added to the ResultHandle, but I don't think qam could be - we are limited in the types we can pass in a ResultHandle.

We also can't re-derive qam in get_results because QAM objects are stateful, so creating one in a new backend instance would not have the results.


A better fix for ForestBackend may be to wait for a release that contains rigetti/pyquil#1331, which removes the statefulness from QAM objects and offers its own handles that we could put into the ResultHandle to query later.

[pytket-cirq] docs build fails

Merging #83 seems to have caused the docs build to fail for pytket-cirq (both on CI and locally).

.../pytket-extensions/modules/pytket-cirq/docs$ sphinx-build -b html . build
Running Sphinx v4.0.1
[autosummary] generating autosummary for: api.rst, changelog.rst, index.rst

Extension error (sphinx.ext.autosummary):
Handler <function process_generate_options at 0x7fb5485c71f0> for event 'builder-inited' threw an exception (exception: list.remove(x): x not in list)

[pytket-qiskit] AerBackend does not respect n_shots list

AerBackend appears to only pick one n_shots value in the new interface that allows different numbers of shots to be specified for each circuit using process_circuits.

Failing example:

from pytket import Circuit
from pytket.extensions.qiskit import AerBackend
b = AerBackend()
circuit = Circuit(1)
assert [len(res.get_shots()) for res in b.get_results(b.process_circuits((circuit, circuit), n_shots=(1, 2)))] == [1, 2]

[pytket-cirq] Improve test coverage

The pytket-cirq tests are rather sparse in their coverage. In particular, the following functionality is not tested:

  • default compilation passes on backends with optimization level 0 and 2;
  • querying circuit status;
  • package_result();
  • _get_default_uids() (called from run_circuit() and run_circuit_moments()) in the case where circuit.qubit_readout is non-empty;
  • cirq_to_tk() with GridQubit and NamedQubit qubit types.

[pytket-qiskit] Test failure: `test_ibmq_mid_measure`.

This test requires IBMQ credentials so isn't run on the CI.
It fails with the following error:

____________________________________________________ test_ibmq_mid_measure _____________________________________________________

    @pytest.mark.skipif(skip_remote_tests, reason="Skipping remote tests")
    def test_ibmq_mid_measure() -> None:
        c = Circuit(3, 3).H(1).CX(1, 2).Measure(0, 0).Measure(1, 1)
        c.add_barrier([0, 1, 2])
    
        c.CX(1, 0).H(0).Measure(2, 2)
    
        # test open backend does not support mid-measure
        # cannot test premium backends that do
        b = IBMQEmulatorBackend("ibmq_athens")
    
        with pytest.raises(RuntimeError) as warninfo:
            b.compile_circuit(c)
>           assert "Not a valid operation" in str(warninfo.value)

backend_test.py:829: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <ExceptionInfo for raises contextmanager>

    @property
    def value(self) -> _E:
        """The exception value."""
>       assert (
            self._excinfo is not None
        ), ".value can only be used after the context manager exits"
E       AssertionError: .value can only be used after the context manager exits

[pytket-qiskit] `TketPass` cannot be used in a qiskit `PassManager` to run multiple circuits.

When a PassManager is constructed from a TketPass, it can be used to run single circuits, but when a list of circuits is passed to the run() method it falls over with a message about not being able to pickle the pass object.

from pytket.extensions.qiskit.tket_pass import TketPass
from pytket.passes import FullPeepholeOptimise
from qiskit import QuantumRegister, QuantumCircuit
from qiskit.transpiler import PassManager

qr = QuantumRegister(1)
qc = QuantumCircuit(qr)
qc.h(qr[0])
tkpass = FullPeepholeOptimise()
qispass = TketPass(tkpass)
pm = PassManager(qispass)
pm.run(qc) # OK
pm.run([qc, qc]) # TypeError: cannot pickle 'pytket._tket.passes.BasePass' object

This makes the PassManager unusable in many qiskit algorithms.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.