Closed campsd closed 2 years ago
Another open issue is how we can map an optimized tensor expression back to a circuit object. This could as simple as iterating over the factors of the optimized model and assigning the result to the tensors in the circuit object. What do you think @yhtang ?
Nice work overall!
There's two outstanding issues:
- the
dtype
should be handled in a consistent manner: it should always be a complex data type?
Agree. For this particular application area, I guess we can start with the two most common options complex64
and complex128
. Not sure if 16-bit floats is useful but it could the subject of a future project :grin:
- the
offset
in the circuits are not yet handled correctly when circuits are added to circuits.
Could you please clarify a little bit? Does offset
refer to the position of the qubits?
Another open issue is how we can map an optimized tensor expression back to a circuit object. This could as simple as iterating over the factors of the optimized model and assigning the result to the tensors in the circuit object. What do you think @yhtang ?
This can be broken down into two sub-problems that we can solve independently:
There's two outstanding issues:
- the
dtype
should be handled in a consistent manner: it should always be a complex data type?Agree. For this particular application area, I guess we can start with the two most common options
complex64
andcomplex128
. Not sure if 16-bit floats is useful but it could the subject of a future project 😁
I was unsure how we enforce this, but I guess using something like fac = ff.Factorization.from_tsrex(circ.to_tsrex(), dtype=ab.complex128)
would work?
- the
offset
in the circuits are not yet handled correctly when circuits are added to circuits.Could you please clarify a little bit? Does
offset
refer to the position of the qubits?
This optional argument specifies if the qubits of the circuit don't range from 0
to nbqubits-1
but from offset
to nbqubits-1+offset
. It is ignored if a circuit only consists of gates, but if you add a circuit to another circuit, you can control the placement of the subcircuit with this. For example:
circ2 = ffq.Circuit(2, offset=0)
circ2.append(ffq.OneQubitUnitary(0))
circ2.append(ffq.CX(1, 0))
circ1 = ffq.Circuit(1, offset=1)
circ1.append(ffq.PauliY(0))
circ2.append(circ1) # circ1 now acts on qubit 1 of circ2
circ2.to_tsrex()
Another open issue is how we can map an optimized tensor expression back to a circuit object. This could as simple as iterating over the factors of the optimized model and assigning the result to the tensors in the circuit object. What do you think @yhtang ?
This can be broken down into two sub-problems that we can solve independently:
- Is there a way for us to uniquely label each circuit & its corresponding abstract tensor?
- Is there a way to enumerate/access the gates in a circuit so that we can update them with concrete tensors?
This makes sense. Shall we handle this in a follow up PR?
Also for future reference: the to_tsrex
function in the Circuit
class is very naive. It places gates one by one and blows all of them up to dimension 2**n
, this can be significantly improved to reduce the cost. I suggest that we move forward with the naive implementation for now and optimize it later.
This makes sense. Shall we handle this in a follow up PR?
Sure. I'm pretty sure this is going to take more than one PRs to accomplish :grin:
I was unsure how we enforce this, but I guess using something like
fac = ff.Factorization.from_tsrex(circ.to_tsrex(), dtype=ab.complex128)
would work?
Actually this sounds like a better option. So basically we factor out the representation of a quantum circuit from its numerical realization.
This optional argument specifies if the qubits of the circuit don't range from
0
tonbqubits-1
but fromoffset
tonbqubits-1+offset
. It is ignored if a circuit only consists of gates, but if you add a circuit to another circuit, you can control the placement of the subcircuit with this. For example:circ2 = ffq.Circuit(2, offset=0) circ2.append(ffq.OneQubitUnitary(0)) circ2.append(ffq.CX(1, 0)) circ1 = ffq.Circuit(1, offset=1) circ1.append(ffq.PauliY(0)) circ2.append(circ1) # circ1 now acts on qubit 1 of circ2 circ2.to_tsrex()
I see. Would it be better to specify the placement of a circuit at the time when it gets inserted into another one? In this way, we can define a circuit once and then reuse it multiple times at different places in a bigger circuit.
This feels a bit like the index renaming mechanism that we implemented to the tensor expressions. For example, we can define a circuit using a set of 'nomial' qubits and then map them onto actual ones when placing them into a bigger one.
This feels a bit like the index renaming mechanism that we implemented to the tensor expressions. For example, we can define a circuit using a set of 'nomial' qubits and then map them onto actual ones when placing them into a bigger one.
I wonder how qiskit or a hardware description language handles this scenario.😎
This feels a bit like the index renaming mechanism that we implemented to the tensor expressions. For example, we can define a circuit using a set of 'nomial' qubits and then map them onto actual ones when placing them into a bigger one.
I wonder how qiskit or a hardware description language handles this scenario.😎
For how qiskit handles this scenario, see: https://qiskit.org/documentation/tutorials/circuits_advanced/01_advanced_circuits.html#Composition
you can attach a subcircuit to certain qubits of the main circuit in the append
function.
Further updates based on our discussion before.
Current usage examples:
circ = ffq.Circuit(3)
G1 = ffq.TwoQubitUnitary()
circ.append(G1 @ (0, 1))
circ.append(G1, at=(1, 2))
circ = ffq.Circuit(2)
CNOT = ffq.CX()
circ.append(CNOT @ (1, 0)) # first = control, second = target
A module for simple quantum circuits and gates.
Example usage:
This can help us optimize parametrized circuits, and eventually integrate with qiskit #221
There's two outstanding issues:
dtype
should be handled in a consistent manner: it should always be a complex data type?offset
in the circuits are not yet handled correctly when circuits are added to circuits.