Skip to content
This repository has been archived by the owner on Dec 18, 2021. It is now read-only.

ControlBlock should be primitive #4

Open
GiggleLiu opened this issue Mar 20, 2019 · 9 comments
Open

ControlBlock should be primitive #4

GiggleLiu opened this issue Mar 20, 2019 · 9 comments

Comments

@GiggleLiu
Copy link
Member

  • it does not call apply! of its block member.
  • in gate counting, it's behavior is different from other composite blocks.
  • RotationGate is primitive, for consistency, control block should also be primitive.
@Roger-luo
Copy link
Member

Roger-luo commented Mar 20, 2019

The definition of composition is Block constructed by other blocks. The reason why RotationGate is primitive is because the usually we only use XYZ block and use that as a mark, that's why it's primitive. But it's true, one can also rotate on a parametrized block, so making RotationGate a composite gate is more correct.

On the other hand, if control become primitive, there'll be a large influence on printing, cache and block tree iteration.

Note: the concept composition doesn't have anything to do with its methods. It's only about type.

@GiggleLiu
Copy link
Member Author

GiggleLiu commented Mar 20, 2019

  1. we can also use SWAP and CNOT (any Hermitian, Reflexive operator) inside a RotationGate.
  2. when X, Y and Z gate used in controlled block and rotation block, they are not actually applied. In fact, for rotation gate, it is incorrect to call its sub-block as a gate, it is a generator.

The definition of composition is Block constructed by other blocks.

constructed by is not accurate. Let's say, apply! of sub-blocks are called, or effectively called. At least this is physically well defined.

On the other hand, if control become primitive, there'll be a large influence on printing, cache and block tree iteration.

It should be special

@Roger-luo
Copy link
Member

Roger-luo commented Mar 20, 2019

we can also use SWAP and CNOT (any Hermitian, Reflexive operator) inside a RotationGate.

This is also the reason to make it composite, see what I replied above.

constructed by is not accurate. Let's say, apply! of sub-blocks are called, or effectively called. At least this is physically well defined.

The tiny type system inside Yao is based on some basic type theory definition. This is already accurate enough: https://en.wikipedia.org/wiki/Composite_data_type

The type system inside Yao for quantum operators, is just a mirror of Julia type system, and should not be different (or it will cause the library become non-idiomatic).

The reason why there's nothing to do with a specific method is because we don't want to mangle type with methods, type is a separated concept. This is straight forward, well known and easy to understand.

It should be special

I don't see any benefits to make this special. Making anything special will result in inconsistency, which is the original reason you mentioned in this issue. So it doesn't make any difference.

If we make this special by re-writing a large amount of code to only make gate counting easier, I don't think it worth it, since you only need to define a single line to make gate counting correct:

ngate(::ControlBlock) = 1 # or whatever this should be

PS. the number of gates should depend on the structure of control block, if we are talking about hardware related gate counting.

@Roger-luo
Copy link
Member

Roger-luo commented Mar 20, 2019

The only two primitive blocks that remains questionable are RotationGate and TimeEvolution, but the reason why they are primitive is also simple:

  • the block inside RotationGate is just a mark on directions (although arbitrary constant gate can be used inside it, but since constant gates are just marks, this is fine)
  • the block inside TimeEvolution serve as a Hamiltonian matrix rather than block

and as for apply!, the general control block (note this block is general, which means it should be able to control an arbitrary block) should use its subblock's apply! instead of its matrix when its subblock is too large (we do this in some old version of Yao, I can't remember).

In fact, I'm specializing those apply!s for specific gates to their own instruction. And would prefer to make control's apply! make use of other blocks' apply in the future (or it won't be possible to calculate a large controlled gate, which is necessary to my old project about algorithmic cooling technique: https://arxiv.org/abs/1208.2256)

@GiggleLiu
Copy link
Member Author

GiggleLiu commented Mar 20, 2019

re-writing a large amount of code

I don't think so, like RotationGate, the file is not much longer than ControlBlock.

to only make gate counting easier

The major difference is the subblocks interface, allowing access to sub-blocks may have the following trouble.

  • Gate Counting and Timing a circuit should be handled as special cases.
  • Make autodiff harder to implement, unlike Rz(theta) in other composite blocks, the gradient of C-Rz(theta) can not be obtained using the formula in this paper. Making Controlled Blocks composite ruined the simplicity of recursive implementation of autodiff.
  • Potential confusion in gate filtering. When people are filtering gates, is it expected to filter out an X gate out of a CNOT gate? CNOT is already an elementary gate, from both programming realization (apply! function of subblocks not called) and experimental realization (controlled-U is not composed of U).
  • The only composite block that bind to instruct directly?

@Roger-luo
Copy link
Member

Roger-luo commented Mar 20, 2019

Gate Counting and Timing a circuit should be handled as special cases.

I think is straight forward, and remember control gate has type parameters, you can/should dispatch it according to what's in it.

Make autodiff harder to implement, unlike Rz(theta) in other composite blocks, the gradient of C-Rz(theta) can not be obtained using the formula in this paper. Making Controlled Blocks

similar as above, you can just dispatch based on the type. And this could be why original autodiff is hard to support this and require a refactor against Flux.

Potential confusion in gate filtering. When people are filtering gates, is it expected to filter out an X gate out of a CNOT gate? CNOT is already an elementary gate, from both programming realization (apply! function of subblocks not called) and experimental realization (controlled-U is not composed of U).

If the controlled block is a parameterized block, e.g control(Rx(theta)), filter out a Rx(theta) is expected. If you want to filter out control(X) together, you should use our new postwalk / prewalk.

The only composite block that bind to instruct directly?

Again, composition is not about what methods it has.

@GiggleLiu
Copy link
Member Author

I would also suggest to make Daggered as a subtype of PrimitiveBlock. It also changes the behavior of apply!.

@Roger-luo
Copy link
Member

Roger-luo commented Mar 20, 2019

Daggered will be part of the symbolic computation (which are all special marks on block and are composite blocks), or it would be hard to optimize things like the following:

dag(X) * Y * dag(Z) * X * dag(dag(Z) * dag(Y))

@GiggleLiu
Copy link
Member Author

The example is not proper, dag is a function that can propagate through composite gates.

Daggered is a type.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants