Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multi-register circuit conversion #72

Merged
merged 5 commits into from
Dec 22, 2023

Conversation

gcalin
Copy link
Contributor

@gcalin gcalin commented Dec 21, 2023

Description

Currently, the tk_to_qulacs function converts the indices of the qubits upon gates operate in an absolute manner, i.e., retrieve the qubit's index from its register. For example, for two qubit gates:

  id1 = index_map[com.qubits[0].index[0]]
  id2 = index_map[com.qubits[1].index[0]]

As a result, circuits with multiple registers are not converted correctly. The corresponding Qulacs circuit that the function builds only has a single register, and index_map does not account for the register's position in the original tket circuit. I added two functions that build a dictionary in such a way that multiple registers are accounted for in the input circuit.

@gcalin gcalin requested a review from yao-cqc as a code owner December 21, 2023 13:53
@yao-cqc
Copy link
Contributor

yao-cqc commented Dec 21, 2023

@gcalin Hi, thanks for the PR! Could you provide an example that produces the problem? We do have a default FlattenRegisters pass in the compilation stack that should merge all registers into a single register.

@gcalin
Copy link
Contributor Author

gcalin commented Dec 21, 2023

@yao-cqc Thank you for looking into this. I am encountering this error when using a different compilation stack. Particularly, the workflow I am using is (1) building a circuit in qiskit -> (2) transpiling in qiskit (to a compatible gate set) -> (3) converting (directly, no compilation) to qulacs using pytket-qiskit and pytket-qulacs.

I am new to tket and I understand the usual workflow includes a (tket) compilation step (and the flattening pass) - but is that strictly necessary to use the tk_to_qulacs conversion function?

@yao-cqc
Copy link
Contributor

yao-cqc commented Dec 21, 2023

@yao-cqc Thank you for looking into this. I am encountering this error when using a different compilation stack. Particularly, the workflow I am using is (1) building a circuit in qiskit -> (2) transpiling in qiskit (to a compatible gate set) -> (3) converting (directly, no compilation) to qulacs using pytket-qiskit and pytket-qulacs.

I am new to tket and I understand the usual workflow includes a (tket) compilation step (and the flattening pass) - but is that strictly necessary to use the tk_to_qulacs conversion function?

Got you. The documentation for tk_to_qulacs is a bit lacking atm. It assumes that the input circuit only has the default quantum register. You can try run the level 0 compilation pass, which doesn't do any optimisation and only does box decomposition, rebase (if the gatesets don't match) and register merging.

If you don't like the way how FlattenRegisters behaves, you also have the option to use Circuit.rename_units to manually merge your registers. API doc, example

@yao-cqc
Copy link
Contributor

yao-cqc commented Dec 21, 2023

For example:

from pytket.extensions.qulacs.qulacs_convert import (
    tk_to_qulacs,
)
from pytket.extensions.qulacs.backends import QulacsBackend
from pytket.circuit import Circuit, Qubit

c = Circuit()
reg_A = c.add_q_register("A", 1)
reg_B = c.add_q_register("B", 2)
c.CX(reg_A[0], reg_B[1])
# option 1: use the default compilation pass
b = QulacsBackend()
d = b.get_compiled_circuit(c, optimisation_level=0)
qulacs_circ = tk_to_qulacs(d)

# option 2: manually rename (assume that your circuit doesn't need rebase)
c.rename_units({
    reg_A[0]: Qubit(0),
    reg_B[0]: Qubit(1),
    reg_B[1]: Qubit(2),
})
qulacs_circ = tk_to_qulacs(c)

of course you can also call FlattenRegisters directly

from pytket.passes import FlattenRegisters
FlattenRegisters().apply(c)

@gcalin
Copy link
Contributor Author

gcalin commented Dec 21, 2023

@yao-cqc Thank you for looking into this. I am encountering this error when using a different compilation stack. Particularly, the workflow I am using is (1) building a circuit in qiskit -> (2) transpiling in qiskit (to a compatible gate set) -> (3) converting (directly, no compilation) to qulacs using pytket-qiskit and pytket-qulacs.
I am new to tket and I understand the usual workflow includes a (tket) compilation step (and the flattening pass) - but is that strictly necessary to use the tk_to_qulacs conversion function?

Got you. The documentation for tk_to_qulacs is a bit lacking atm. It assumes that the input circuit only has the default quantum register. You can try run the level 0 compilation pass, which doesn't do any optimisation and only does box decomposition, rebase (if the gatesets don't match) and register merging.

If you don't like the way how FlattenRegisters behaves, you also have the option to use Circuit.rename_units to manually merge your registers. API doc, example

Understood, thank very much you for the references and examples. In this case, would you be interested in extending the functionality of tk_to_qulacs to arbitrary circuits (i.e., by performing checks on presupposed properties, like there being a single register, which means the conversion might perform compilation subroutines?), or is the "basic" (optimisation_level=0) compilation a must for the input circuit?

@yao-cqc
Copy link
Contributor

yao-cqc commented Dec 21, 2023

@yao-cqc Thank you for looking into this. I am encountering this error when using a different compilation stack. Particularly, the workflow I am using is (1) building a circuit in qiskit -> (2) transpiling in qiskit (to a compatible gate set) -> (3) converting (directly, no compilation) to qulacs using pytket-qiskit and pytket-qulacs.
I am new to tket and I understand the usual workflow includes a (tket) compilation step (and the flattening pass) - but is that strictly necessary to use the tk_to_qulacs conversion function?

Got you. The documentation for tk_to_qulacs is a bit lacking atm. It assumes that the input circuit only has the default quantum register. You can try run the level 0 compilation pass, which doesn't do any optimisation and only does box decomposition, rebase (if the gatesets don't match) and register merging.
If you don't like the way how FlattenRegisters behaves, you also have the option to use Circuit.rename_units to manually merge your registers. API doc, example

Understood, thank very much you for the references and examples. In this case, would you be interested in extending the functionality of tk_to_qulacs to arbitrary circuits (i.e., by performing checks on presupposed properties, like there being a single register, which means the conversion might perform compilation subroutines?), or is the "basic" (optimisation_level=0) compilation a must for the input circuit?

To make tk_to_qulacs more useful as a standalone function, I think it should be suffice to add a check for circuit.is_simple() (doc). Other properties are already being checked by this line.

@gcalin
Copy link
Contributor Author

gcalin commented Dec 21, 2023

@yao-cqc Thank you for looking into this. I am encountering this error when using a different compilation stack. Particularly, the workflow I am using is (1) building a circuit in qiskit -> (2) transpiling in qiskit (to a compatible gate set) -> (3) converting (directly, no compilation) to qulacs using pytket-qiskit and pytket-qulacs.
I am new to tket and I understand the usual workflow includes a (tket) compilation step (and the flattening pass) - but is that strictly necessary to use the tk_to_qulacs conversion function?

Got you. The documentation for tk_to_qulacs is a bit lacking atm. It assumes that the input circuit only has the default quantum register. You can try run the level 0 compilation pass, which doesn't do any optimisation and only does box decomposition, rebase (if the gatesets don't match) and register merging.
If you don't like the way how FlattenRegisters behaves, you also have the option to use Circuit.rename_units to manually merge your registers. API doc, example

Understood, thank very much you for the references and examples. In this case, would you be interested in extending the functionality of tk_to_qulacs to arbitrary circuits (i.e., by performing checks on presupposed properties, like there being a single register, which means the conversion might perform compilation subroutines?), or is the "basic" (optimisation_level=0) compilation a must for the input circuit?

To make tk_to_qulacs more useful as a standalone function, I think it should be suffice to add a check for circuit.is_simple() (doc). Other properties are already being checked by this line.

I removed my initial solution and replaced it with a conditional FlattenRegisters pass. This indeed makes it possible to circumvent the rest of the compilation stack for my use case.

Copy link
Contributor

@yao-cqc yao-cqc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you @gcalin !

@yao-cqc yao-cqc merged commit 8e46736 into CQCL:develop Dec 22, 2023
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants