Skip to content

"Simplify flipped CNOTs" exercise in intro colab has wrong solution #1

@amirebrahimi

Description

@amirebrahimi

This isn't an issue with fondq, but I'm new to colabs, so I'm not sure how to suggest a fix to a colab. If there is a repo where I can submit a PR, then let me know.

In tutorial_01, "Introduction - Colab" from Cirq for NISQ near the end there is an exercise to create a Point Optimizer for CNOTs sandwiched with two H gates. The solution is only a redundant Hadamard optimizer. Perhaps the exercise changed after or vice versa. Anyhow, I wrote a HCXHOptimizer that you can throw in the Solution panel:

class HCXHOptimizer(cirq.PointOptimizer):
    """Replaces a CNOT sandwiched by H gates with a flipped CNOT."""
    
    # The circuit to improve
    # The index of the moment with the operation to focus on
    # The operation to focus improvements upon
    def optimization_at(self, circuit, index, op):
        if isinstance(op, cirq.GateOperation) and (op.gate == cirq.H):
          
            # Finds the index of the next moment that touches the given qubits.
            next_op_index = circuit.next_moment_operating_on(op.qubits, index + 1)
            qubit = op.qubits[0]
            
            # If the next index exists
            if next_op_index is not None:
              
                # Get the operation at the existing index
                next_op = circuit.operation_at(qubit, next_op_index)
                
                if isinstance(next_op, cirq.GateOperation) and  (next_op.gate == cirq.CNOT):
                    other_qubit = next_op.qubits[1]
                    cnot_index = next_op_index
                    cnot_op = next_op

                    next_op_index = circuit.next_moment_operating_on(op.qubits, next_op_index + 1)
                    next_op = circuit.operation_at(qubit, next_op_index)

                    if isinstance(next_op, cirq.GateOperation) and (next_op.gate == cirq.H):
                      other_op_index = circuit.prev_moment_operating_on(cnot_op.qubits, cnot_index)
                      other_op = circuit.operation_at(other_qubit, other_op_index)
                      
                      if isinstance(other_op, cirq.GateOperation) and (other_op.gate == cirq.H):
                        other_op_index = circuit.next_moment_operating_on(cnot_op.qubits, cnot_index + 1)
                        other_op = circuit.operation_at(other_qubit, other_op_index)

                        if isinstance(other_op, cirq.GateOperation) and (other_op.gate == cirq.H):                      
                          new_op = cirq.CNOT(other_qubit, qubit)
                        
                          # see https://cirq.readthedocs.io/en/stable/generated/cirq.PointOptimizationSummary.html?highlight=pointoptimizationsummary
                          return cirq.PointOptimizationSummary(
                              clear_span = next_op_index - index + 1, # Range of moments to affect. 
                              clear_qubits = cnot_op.qubits, # The set of qubits that should be cleared with each affected moment
                              new_operations = [new_op] # The operations to replace
                          )
        return None
                        
        
# The optimizer
opt = HCXHOptimizer()

a = cirq.NamedQubit("a")
b = cirq.NamedQubit("b")

# Unoptimized circuit
circuit = cirq.Circuit(cirq.H(a), cirq.H(b), cirq.CNOT(a, b), cirq.H(a), cirq.H(b))
print('Before\n{}\n'. format(circuit))

# Optimized circuit
opt.optimize_circuit(circuit)
print('After HCX opt\n{}\n'.format(circuit))

# We can remove the empty moments
remempty = cirq.DropEmptyMoments()
remempty.optimize_circuit(circuit)
print('After Drop opt\n{}\n'.format(circuit))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions