def test_two_annotation_swap(self): """SWAP gate after different annotation should be optimized |phi> --annotation------x- |phi> -- | => |phi>---annotation----x- |phi> -- """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.append(StateAnnotation(0.1, 0.2, 0.3), [qr[0]]) circuit.append(StateAnnotation(0.4, 0.5, 0.6), [qr[1]]) circuit.swap(qr[0], qr[1]) expected = QuantumCircuit(qr) expected.u3(0.4, 0.5, 0.6, qr[0]) expected.u3(0.1, 0.2, 0.3, qr[1]) passmanager = PassManager() passmanager.append(PureStateOnU()) result = passmanager.run(circuit) self.assertEqual(expected, result)
def test_two_const_swap(self): """Input states are the different pure states, replace the swap with two single qubit gates |phi> --X---- |phi> --U3-- | => |psi>--X---- |psi> --U3^-- """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.u3(1.23, 3.34, 3.04, qr[0]) circuit.u3(2.22, 1.67, 0.66, qr[1]) circuit.swap(qr[0], qr[1]) expected = QuantumCircuit(qr) expected.u3(2.22, 1.67, 0.66, qr[0]) expected.u3(1.23, 3.34, 3.04, qr[1]) passmanager = PassManager() passmanager.append(PureStateOnU()) passmanager.append(Optimize1qGates()) result = passmanager.run(circuit) self.assertEqual(expected, result)
def test_two_unknown_swap(self): """Input states are the same, remove the swap gate |phi> --X---- |phi> -- | => |phi>--X---- |phi> -- """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.reset(qr[0]) circuit.reset(qr[1]) circuit.swap(qr[0], qr[1]) expected = QuantumCircuit(qr) expected.reset(qr[0]) expected.reset(qr[1]) expected.swap(qr[0], qr[1]) passmanager = PassManager() passmanager.append(PureStateOnU()) result = passmanager.run(circuit) self.assertEqual(expected, result)
def test_empty_annotation(self): """Empty circuit with annotation |phi> --annotation---- |phi> -- => |phi>-------------- phi> -- """ qr = QuantumRegister(2, 'qr') circuit = QuantumCircuit(qr) circuit.u3(1.23, 2.34, 3.04, qr[0]) circuit.u3(1.23, 2.34, 3.04, qr[1]) circuit.swap(qr[0], qr[1]) circuit.append(StateAnnotation(0.1, 0.2, 0.3), [qr[0]]) expected = QuantumCircuit(qr) expected.u3(1.23, 2.34, 3.04, qr[0]) expected.u3(1.23, 2.34, 3.04, qr[1]) passmanager = PassManager() passmanager.append(PureStateOnU()) result = passmanager.run(circuit) self.assertEqual(expected, result)
def level_3_with_contant_pure(pass_manager_config: PassManagerConfig) -> PassManager: """ Args: pass_manager_config: configuration of the pass manager. Returns: a level 3 pass manager. """ 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' 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 + ['annotation']) # 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 = CSPLayout(coupling_map, call_limit=10000, time_limit=60) 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) 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. 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()] 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)] else: raise TranspilerError("Invalid routing method %s." % routing_method) # 5. 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 = [RemoveResetInZeroState(), Collect2qBlocks(), ConsolidateBlocks(), Unroller(basis_gates), # unroll unitaries Optimize1qGates(basis_gates), CommutativeCancellation(), OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()] # 6. Fix any CX direction mismatch _direction_check = [CheckCXDirection(coupling_map)] def _direction_condition(property_set): return not property_set['is_direction_mapped'] _direction = [CXDirection(coupling_map)] # Build pass manager pm = PassManager() pm.append(ConstantsStateOptimization()) pm.append(_unroll) if coupling_map: pm.append(_given_layout) pm.append(_choose_layout_1, condition=_choose_layout_condition) pm.append(_choose_layout_2, condition=_choose_layout_condition) pm.append(_embed) pm.append(_swap_check) pm.append(_swap, condition=_swap_condition) pm.append(ConstantsStateOptimization()) pm.append([Unroller(basis_gates+['swap', 'aswap', 'annotation']), Optimize1qGates(), PureStateOnU()]) pm.append(_depth_check + _opt, do_while=_opt_control) if coupling_map and not coupling_map.is_symmetric: pm.append(_direction_check) pm.append(_direction, condition=_direction_condition) return pm