Пример #1
0
    def test_unroll_all_instructions(self):
        """Test unrolling a circuit containing all standard instructions.
        """
        qr = QuantumRegister(3, 'qr')
        cr = ClassicalRegister(3, 'cr')
        circuit = QuantumCircuit(qr, cr)
        circuit.ccx(qr[0], qr[1], qr[2])
        circuit.ch(qr[0], qr[2])
        circuit.crz(0.5, qr[1], qr[2])
        circuit.cswap(qr[1], qr[0], qr[2])
        circuit.cu1(0.1, qr[0], qr[2])
        circuit.cu3(0.2, 0.1, 0.0, qr[1], qr[2])
        circuit.cx(qr[1], qr[0])
        circuit.cy(qr[1], qr[2])
        circuit.cz(qr[2], qr[0])
        circuit.h(qr[1])
        circuit.iden(qr[0])
        circuit.rx(0.1, qr[0])
        circuit.ry(0.2, qr[1])
        circuit.rz(0.3, qr[2])
        circuit.rzz(0.6, qr[1], qr[0])
        circuit.s(qr[0])
        circuit.sdg(qr[1])
        circuit.swap(qr[1], qr[2])
        circuit.t(qr[2])
        circuit.tdg(qr[0])
        circuit.u0(1, qr[0])
        circuit.u1(0.1, qr[1])
        circuit.u2(0.2, -0.1, qr[0])
        circuit.u3(0.3, 0.0, -0.1, qr[2])
        circuit.x(qr[2])
        circuit.y(qr[1])
        circuit.z(qr[0])
        circuit.snapshot('0')
        circuit.measure(qr, cr)
        dag = circuit_to_dag(circuit)
        pass_ = Unroller(basis=['u3', 'cx'])
        unrolled_dag = pass_.run(dag)

        ref_circuit = QuantumCircuit(qr, cr)
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(0, 0, -pi / 4, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(0, 0, pi / 4, qr[1])
        ref_circuit.u3(0, 0, -pi / 4, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.cx(qr[0], qr[1])
        ref_circuit.u3(0, 0, pi / 4, qr[0])
        ref_circuit.u3(0, 0, -pi / 4, qr[1])
        ref_circuit.cx(qr[0], qr[1])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.u3(0, 0, -pi / 2, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, pi / 2, qr[0])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.u3(0, 0, pi / 2, qr[2])
        ref_circuit.u3(pi, 0, pi, qr[2])
        ref_circuit.u3(0, 0, 0.25, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(0, 0, -0.25, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, -pi / 4, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, pi / 4, qr[0])
        ref_circuit.u3(0, 0, -pi / 4, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.u3(0, 0, -pi / 4, qr[0])
        ref_circuit.u3(0, 0, pi / 4, qr[1])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[2])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.u3(0, 0, 0.05, qr[0])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, -0.05, qr[2])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.u3(0, 0, 0.05, qr[2])
        ref_circuit.u3(0, 0, -0.05, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(-0.1, 0, -0.05, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.u3(pi / 2, 0, pi, qr[0])
        ref_circuit.u3(0.1, 0.1, 0, qr[2])
        ref_circuit.u3(0, 0, -pi / 2, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(pi / 2, 0, pi, qr[1])
        ref_circuit.u3(0.2, 0, 0, qr[1])
        ref_circuit.u3(0, 0, pi / 2, qr[2])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.u3(pi / 2, 0, pi, qr[0])
        ref_circuit.u3(0, 0, 0, qr[0])
        ref_circuit.u3(0.1, -pi / 2, pi / 2, qr[0])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.u3(0, 0, 0.6, qr[0])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.u3(0, 0, pi / 2, qr[0])
        ref_circuit.u3(0, 0, -pi / 4, qr[0])
        ref_circuit.u3(0, 0, 0, qr[0])
        ref_circuit.u3(pi / 2, 0.2, -0.1, qr[0])
        ref_circuit.u3(0, 0, pi, qr[0])
        ref_circuit.u3(0, 0, -pi / 2, qr[1])
        ref_circuit.u3(0, 0, 0.3, qr[2])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[2], qr[1])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.u3(0, 0, 0.1, qr[1])
        ref_circuit.u3(pi, pi / 2, pi / 2, qr[1])
        ref_circuit.u3(0, 0, pi / 4, qr[2])
        ref_circuit.u3(0.3, 0.0, -0.1, qr[2])
        ref_circuit.u3(pi, 0, pi, qr[2])
        ref_circuit.snapshot('0')
        ref_circuit.measure(qr, cr)
        ref_dag = circuit_to_dag(ref_circuit)
        self.assertEqual(unrolled_dag, ref_dag)
Пример #2
0
def run(d, l):
    t = open(l, "w")
    csvwriter = csv.writer(t)
    csvwriter.writerow([
        "Name", "Before", "VOQC"
        "Qiskit+VOQC", "Before CNOT", "VOQC CNOT", "Qiskit+VOQC CNOT", "Time"
    ])
    t.close()
    for fname in os.listdir(d):
        print("Processing %s..." % fname)
        format_from_qasm(os.path.join(d, fname))
        circ = QuantumCircuit.from_qasm_file("copy.qasm")

        num_gates_before = count(circ.count_ops())
        cnot_count_before = 0
        for inst, _, _ in circ.data:
            if (inst.name == "cx"):
                cnot_count_before += 1

        print("Original:\t Total %d, CNOT %d" %
              (num_gates_before, cnot_count_before))

        pm = PassManager()
        pm.append(QisVOQC(["optimize"]))
        start = time.perf_counter()
        new_circ = pm.run(circ)
        stop = time.perf_counter()
        first = stop - start

        voqc_gates = count(new_circ.count_ops())
        cnot_voqc = 0
        for inst, _, _ in new_circ.data:
            if (inst.name == "cx"):
                cnot_voqc += 1
        print("After VOQC:\t Total %d, CNOT %d" % (voqc_gates, cnot_voqc))

        basis_gates = ['u1', 'u2', 'u3', 'cx']
        _unroll = Unroller(basis_gates)
        _depth_check = [Depth(), FixedPoint('depth')]

        def _opt_control(property_set):
            return not property_set['depth_fixed_point']

        _opt = [
            Collect2qBlocks(),
            ConsolidateBlocks(),
            Unroller(basis_gates),
            Optimize1qGates(),
            CommutativeCancellation()
        ]
        pm1 = PassManager()
        pm1.append(_unroll)
        pm1.append(_depth_check + _opt, do_while=_opt_control)
        start = time.perf_counter()  # start timer
        new_circ = pm1.run(new_circ)
        stop = time.perf_counter()  # stop timer
        second = stop - start

        num_gates_after = count(new_circ.count_ops())
        cnot_count_after = 0
        for inst, _, _ in new_circ.data:
            if (inst.name == "cx"):
                cnot_count_after += 1
        print("Final:\t Total %d, CNOT %d\n" %
              (num_gates_after, cnot_count_after))

        t = open(l, "a")
        csvwriter = csv.writer(t)
        csvwriter.writerow([
            fname, num_gates_before, voqc_gates, num_gates_after,
            cnot_count_before, cnot_voqc, cnot_count_after, first + second
        ])
        t.close()
Пример #3
0
def level_1_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 1 pass manager: light optimization by simple adjacent gate collapsing.

    This pass manager applies the user-given initial layout. If none is given,
    and a trivial layout (i-th virtual -> i-th physical) makes the circuit fit
    the coupling map, that is used.
    Otherwise, the circuit is mapped to the most densely connected coupling subgraph,
    and swaps are inserted to map. Any unused physical qubit is allocated as ancilla space.
    The pass manager then unrolls the circuit to the desired basis, and transforms the
    circuit to match the coupling map. Finally, optimizations in the form of adjacent
    gate collapse and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 1 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'dense'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    translation_method = pass_manager_config.translation_method or 'translator'
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Use trivial layout if no layout given
    _given_layout = SetLayout(initial_layout)

    _choose_layout_and_score = [
        TrivialLayout(coupling_map),
        Layout2qDistance(coupling_map, property_name='trivial_layout_score')
    ]

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    # 2. Use a better layout on densely connected qubits, if circuit needs swaps
    if layout_method == 'trivial':
        _improve_layout = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _improve_layout = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _improve_layout = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _improve_layout = SabreLayout(coupling_map,
                                      max_iterations=2,
                                      seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    def _not_perfect_yet(property_set):
        return property_set['trivial_layout_score'] is not None and \
               property_set['trivial_layout_score'] != 0

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Decompose so only 1-qubit and 2-qubit gates remain
    _unroll3q = Unroll3qOrMore()

    # 5. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=20, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=4, search_width=4)]
    elif routing_method == 'sabre':
        _swap += [
            SabreSwap(coupling_map,
                      heuristic='lookahead',
                      seed=seed_transpiler)
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 6. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates)
        ]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." %
                              translation_method)

    # 7. Fix any bad CX directions
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 8. Remove zero-state reset
    _reset = RemoveResetInZeroState()

    # 9. Merge 1q rotations and cancel CNOT gates iteratively until no more change in depth
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _opt = [Optimize1qGates(basis_gates), CXCancellation()]

    # Build pass manager
    pm1 = PassManager()
    if coupling_map:
        pm1.append(_given_layout)
        pm1.append(_choose_layout_and_score,
                   condition=_choose_layout_condition)
        pm1.append(_improve_layout, condition=_not_perfect_yet)
        pm1.append(_embed)
        pm1.append(_unroll3q)
        pm1.append(_swap_check)
        pm1.append(_swap, condition=_swap_condition)
    pm1.append(_unroll)
    if coupling_map and not coupling_map.is_symmetric:
        pm1.append(_direction_check)
        pm1.append(_direction, condition=_direction_condition)
    pm1.append(_reset)
    pm1.append(_depth_check + _opt, do_while=_opt_control)

    return pm1
Пример #4
0
def level_2_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 2 pass manager: medium optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules.

    This pass manager applies the user-given initial layout. If none is given, and
    device calibration information is available, the circuit is mapped to the qubits
    with best readouts and to CX gates with highest fidelity. Otherwise, a layout on
    the most densely connected qubits is used.
    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation and redundant
    reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 2 pass manager.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Unroll to the basis first, to prepare for noise-adaptive layout
    _unroll = Unroller(basis_gates)

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout = DenseLayout(coupling_map, backend_properties)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Unroll to 1q or 2q gates, swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [
        BarrierBeforeFinalMeasurements(),
        Unroll3qOrMore(),
        StochasticSwap(coupling_map, trials=20, seed=seed_transpiler),
        Decompose(SwapGate)
    ]

    # 5. Fix any bad CX directions
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 6. Remove zero-state reset
    _reset = RemoveResetInZeroState()

    # 7. 1q rotation merge and commutative cancellation iteratively until no more change in depth
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _opt = [Optimize1qGates(), CommutativeCancellation()]

    pm2 = PassManager()
    pm2.append(_unroll)
    if coupling_map:
        pm2.append(_given_layout)
        pm2.append(_choose_layout, condition=_choose_layout_condition)
        pm2.append(_embed)
        pm2.append(_swap_check)
        pm2.append(_swap, condition=_swap_condition)
        if not coupling_map.is_symmetric:
            pm2.append(_direction_check)
            pm2.append(_direction, condition=_direction_condition)
    pm2.append(_reset)
    pm2.append(_depth_check + _opt, do_while=_opt_control)

    return pm2
Пример #5
0
def level_3_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules and unitary synthesis.

    This pass manager applies the user-given initial layout. If none is given, a search
    for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted.
    If no such layout is found, and device calibration information is available, the
    circuit is mapped to the qubits with best readouts and to CX gates with highest fidelity.

    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation, resynthesis
    of two-qubit unitary blocks, and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 3 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'dense'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    translation_method = pass_manager_config.translation_method or 'translator'
    scheduling_method = pass_manager_config.scheduling_method
    instruction_durations = pass_manager_config.instruction_durations
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties
    approximation_degree = pass_manager_config.approximation_degree

    # 1. Unroll to 1q or 2q gates
    _unroll3q = Unroll3qOrMore()

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout_1 = [] if pass_manager_config.layout_method \
        else CSPLayout(coupling_map, call_limit=10000, time_limit=60, seed=seed_transpiler)
    if layout_method == 'trivial':
        _choose_layout_2 = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _choose_layout_2 = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _choose_layout_2 = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _choose_layout_2 = SabreLayout(coupling_map,
                                       max_iterations=4,
                                       seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=200, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=6)]
    elif routing_method == 'sabre':
        _swap += [
            SabreSwap(coupling_map, heuristic='decay', seed=seed_transpiler)
        ]
    elif routing_method == 'none':
        _swap += [
            Error(
                msg=
                'No routing method selected, but circuit is not routed to device. '
                'CheckMap Error: {check_map_msg}',
                action='raise')
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates)
        ]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates,
                             approximation_degree=approximation_degree),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." %
                              translation_method)

    # 6. Fix any CX direction mismatch
    _direction_check = [CheckGateDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [GateDirection(coupling_map)]

    # 8. Optimize iteratively until no more change in depth. Removes useless gates
    # after reset and before measure, commutes gates and optimizes contiguous blocks.
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _reset = [RemoveResetInZeroState()]

    _meas = [OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()]

    _opt = [
        Collect2qBlocks(),
        ConsolidateBlocks(basis_gates=basis_gates),
        UnitarySynthesis(basis_gates,
                         approximation_degree=approximation_degree),
        Optimize1qGatesDecomposition(basis_gates),
        CommutativeCancellation(),
    ]

    # 9. Unify all durations (either SI, or convert to dt if known)
    # Schedule the circuit only when scheduling_method is supplied
    _scheduling = [TimeUnitConversion(instruction_durations)]
    if scheduling_method:
        if scheduling_method in {'alap', 'as_late_as_possible'}:
            _scheduling += [ALAPSchedule(instruction_durations)]
        elif scheduling_method in {'asap', 'as_soon_as_possible'}:
            _scheduling += [ASAPSchedule(instruction_durations)]
        else:
            raise TranspilerError("Invalid scheduling method %s." %
                                  scheduling_method)

    # Build pass manager
    pm3 = PassManager()
    pm3.append(_unroll3q)
    pm3.append(_reset + _meas)
    if coupling_map or initial_layout:
        pm3.append(_given_layout)
        pm3.append(_choose_layout_1, condition=_choose_layout_condition)
        pm3.append(_choose_layout_2, condition=_choose_layout_condition)
        pm3.append(_embed)
        pm3.append(_swap_check)
        pm3.append(_swap, condition=_swap_condition)
    pm3.append(_unroll)
    if coupling_map and not coupling_map.is_symmetric:
        pm3.append(_direction_check)
        pm3.append(_direction, condition=_direction_condition)
        pm3.append(_unroll)
    pm3.append(_reset)
    pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
    pm3.append(_scheduling)

    return pm3
Пример #6
0
def run(d, fname):
    
    f = open(fname, "w")
    
    f.write("name,Orig. total,Orig. CNOT,Qiskit total,Qiskit CNOT,time\n")
    
    for fname in os.listdir(d):

        print("Processing %s..." % fname)
        
        # Some of the benchmarks contain 'ccz' and 'ccx' gates. For consistency, we
        # want to make sure Qiskit uses the same decomposition for these gates as VOQC.
        # Our (hacky) solution for now is to make a copy of the benchmark that contains
        # already-decomposed versions of ccx and ccz.
        
        inqasm = open(os.path.join(d, fname), "r")
        tmp = open("copy.qasm", "w") # hardcoded filename
        p_ccz = re.compile("ccz (.*), (.*), (.*);")
        p_ccx = re.compile("ccx (.*), (.*), (.*);")
        
        for line in inqasm:
            m1 = p_ccx.match(line)
            m2 = p_ccz.match(line)
            if m1:
                a = m1.group(1)
                b = m1.group(2)
                c = m1.group(3)
                tmp.write("h %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
                tmp.write("h %s;\n" % (c))
            elif m2:
                a = m2.group(1)
                b = m2.group(2)
                c = m2.group(3)
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("t %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (b, c))
                tmp.write("tdg %s;\n" % (c))
                tmp.write("cx %s, %s;\n" % (a, c))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("tdg %s;\n" % (b))
                tmp.write("cx %s, %s;\n" % (a, b))
                tmp.write("t %s;\n" % (a))
                tmp.write("t %s;\n" % (b))
                tmp.write("t %s;\n" % (c))
            else:
                tmp.write(line)
        tmp.close()
        circ = QuantumCircuit.from_qasm_file("copy.qasm")

        num_gates_before = count(circ.count_ops())
        cnot_count_before = 0
        for inst, _, _ in circ.data:
            if (inst.name == "cx"):
                cnot_count_before += 1
        print("Original:\t Total %d, CNOT %d" % (num_gates_before, cnot_count_before))
        
        basis_gates = ['u1', 'u2', 'u3', 'cx']
        _unroll = Unroller(basis_gates)
        _depth_check = [Depth(), FixedPoint('depth')]
        def _opt_control(property_set):
            return not property_set['depth_fixed_point']
        _opt = [Collect2qBlocks(), ConsolidateBlocks(),
                Unroller(basis_gates),  # unroll unitaries
                Optimize1qGates(), CommutativeCancellation()]
        pm = PassManager()
        pm.append(_unroll)
        pm.append(_depth_check + _opt, do_while=_opt_control)
        start = time.perf_counter() # start timer
        new_circ = pm.run(circ)
        stop = time.perf_counter() # stop timer
        num_gates_after = count(new_circ.count_ops())
        cnot_count_after = 0
        for inst, _, _ in new_circ.data:
            if (inst.name == "cx"):
                cnot_count_after += 1
        print("Final:\t Total %d, CNOT %d\n" % (num_gates_after, cnot_count_after))

        f.write("%s,%d,%d,%d,%d,%f\n" % (fname, num_gates_before, cnot_count_before, num_gates_after, cnot_count_after, stop - start))
        
    f.close()
    os.remove("copy.qasm")