ProjectQ-Framework / ProjectQ

ProjectQ: An open source software framework for quantum computing
https://projectq.ch
Apache License 2.0
888 stars 274 forks source link

circuitdrawer reordering gates? #333

Closed alexandrupaler closed 5 years ago

alexandrupaler commented 5 years ago

I am using the tikz output for a circuit, but the gates are not drawn in the order I am sending them. How can I force the gates to be in the specified order?

Takishima commented 5 years ago

Could you post a minimal working example that reproduces your issue ? Without context it is difficult to understand your exact problem.

That being said, the CircuitDrawer does not perform any gate reordering. This probably occurs because you have an optimiser (or other) engine somewhere in your engine list that may cache gates before sending them further down the pipeline.

alexandrupaler commented 5 years ago

I am using MainEngine(CircuitDrawer()) to draw, and nothing else. I will post an example, but away from the source code.

Takishima commented 5 years ago

So you do have by default a few optimiser engines that may cache some gates on some qubits but not on others.

One solution would be to insert eng.flush() statements after each gates or simply remove all the optimisers from your engine list:

import projectq.setups.decompositions
from projectq.cengines import TagRemover, AutoReplacer, DecompositionRuleSet
eng = MainEngine(CircuitDrawer(), 
                               [TagRemover(), 
                                AutoReplacer(DecompositionRuleSet(modules=[
                                        projectq.setups.decompositions])), 
                                TagRemover()])
alexandrupaler commented 5 years ago

I see. Thank you.

alexandrupaler commented 5 years ago

I made sure that only the CircuitDrawer is used in the MainEngine.

drawing_engine = CircuitDrawer()
eng = MainEngine(drawing_engine, engine_list=[])

U = eng.allocate_qureg(8)
with Compute(eng):
        CNOT | (U[0],U[5])
        CNOT | (U[3],U[5])
        CNOT | (U[6],U[5])
        CNOT | (U[0],U[4])
        CNOT | (U[3],U[4])
        CNOT | (U[6],U[4])

Uncompute(eng)

for k in range(8):
        Measure | S[k]
        eng.flush()

The circuit look like in the attached figure. image

Is it because of the ComputeEngine?

alexandrupaler commented 5 years ago

@Takishima: Please reopen this issue.

_to_latex.py is the source of evil in the reordering of gates. (see line 269) The gates are not drawn in the order they were appended to the circuit, but on a line-by-line basis (wire-by-wire basis). If a certain gates are left undrawn (due to its precedence in the gate - list), then the preceding gates are drawn.

This is like a topological sort of drawing the circuit, and not the user specified order.