merge Pauli gates for composite blocks
Currently only single qubit pauli gate in chain and prod supports merging pauli gates.
Composite blocks like kron and PauliString with pure Pauli gates can be merged by when inside chain/prod as well.
I'll leave this to next release, so we can have some time play with this new optimization pass see what needs to improve.
Fortunately, our simplifier just works for the follow composite blocks (multi-qubits blocks contains single qubits Paulis)
julia> using YaoBlocks
julia> g = chain(2, kron(X, chain(X, Y)), control(2, 1=>X))
nqubits: 2, datatype: Complex{Float64}
chain
├─ kron
│ ├─ 1=>X gate
│ └─ 2=>chain
│ ├─ X gate
│ └─ Y gate
└─ control(2)
└─ (1,)X gate
julia> simplify(g)
nqubits: 2, datatype: Complex{Float64}
prod
├─ control(2)
│ └─ (1,)X gate
└─ kron
├─ 1=>X gate
└─ 2=>[-im] Z gate
I think next step is to define simplification rules for Cliffords, which will work for multi-qubits circuit in general. Probably this part should be moved to another package in the future, but whoever interested in this feature could start trying YaoBlocks with it now.
Merging pauli gates might be a useful feature.
But please don't use prod in unitary evolutions, this example just shows how terrible it is.
This is useful and this is not related to this issue, see #9. The point to use prod here is just because it's easy to implement. I think eventually these things should be move to a single package for symbolic computing and circuit optimization. But we can use it for now.
it's easy to implement
Not implementing it would be better. For preventing potential errors.
I don't see any potential errors, you can't construct/desctruct a Prod without operators.
The point of #9 is when someone really hit something, it's never too late to make things work. We can't make everything work with one go.
when someone really hit something.
I think we both agreed that our development should be demand-driven.
Then, we should remove the Prod, keep the issue and wait for the feature requests. Prod is a replaceable structure, it is almost parallel to chain in functionality.
It's something required for simplify for now, if this is removed, it won't work at all. I don't think remove functionality is a good idea. The point is we could remove Prod after implementation a pass for chain.
It's not something breaking the API, since Prod is just a temporary representation of * and Prod. And not something preventing things not to work.
There should not be too much overlap between Prod and ChainBlock, make it possible or remove Prod.
remove Prod after implementation a pass for chain
Don't get this point.
I can just remove Chain's pass so simplify only works for Prod. And add it back when we have time to implement one for Chain.
ok, then please also polish the printing
instead of
prod
|- X gate
|- Y gate
print X*Y.
This printing should be a bug. I'll have a look when I'm back.
Ok now */prod strictly corresponding to Prod, nothing else will create a Prod node implicitly. (It's just one line anyway)
@GiggleLiu The printing is correct:
julia> X * Y
nqubits: 1, datatype: Complex{Float64}
prod
├─ X gate
└─ Y gate
I don't get
prod
|- X gate
|- Y gate
I mean, X*Y would be better.
But this will mess up the following
control(2, 1, 2=>X) * kron(X, Y)
which make sense for simplification and basis, etc. (they are Cliffords) and I don't think it's trivial to workaround that. I'd like to keep what it is now, at least it is readable (it won't be readable at all for composite block in a single line).
X * Y only works for primitive blocks, since you don't need multiple lines.
you are right.