Example #1
0
 def test_coupling_map(self):
     self.assertEqual(
         CouplingMap().get_edges(), self.empty_target.build_coupling_map().get_edges()
     )
     self.assertEqual(
         set(CouplingMap.from_full(5).get_edges()),
         set(self.aqt_target.build_coupling_map().get_edges()),
     )
     self.assertEqual(
         {(0, 1), (1, 0)}, set(self.fake_backend_target.build_coupling_map().get_edges())
     )
     self.assertEqual(
         {
             (3, 4),
             (4, 3),
             (3, 1),
             (1, 3),
             (1, 2),
             (2, 1),
             (0, 1),
             (1, 0),
         },
         set(self.ibm_target.build_coupling_map().get_edges()),
     )
     self.assertEqual(None, self.ideal_sim_target.build_coupling_map())
Example #2
0
def random_circuit(n_qubits,
                   depth,
                   coupling_map=None,
                   basis_gates=None,
                   prob_one_q_op=0.5,
                   reset=False,
                   seed=None):
    """Generate RQC faithfully according to the given coupling_map and basis_gates.

    Args:
        n_qubits (int):                     the number of qubits, must > largest qubit label in coupling_map
        depth (int):                        the number of the layers of operations
        coupling_map (CouplingMap or list): coupling map specifies allowed CNOTs
            default:                        fully connected graph coupling n_qubits
        basis_gates (list):                 the list of labels of basis gates used in construction
            default:                        all available gates in gate_set
        prob_one_q_op (float):              the probability of selecting a one-qubit operation when two_q_op is allowed
            default:                        equal probability 0.5
        reset (bool):                       if True, insert middle resets
        seed (int):                         sets random seed (optional)

    Returns:
        QuantumCircuit: constructed circuit

    Raises:
        CircuitError: when invalid options given
    """
    max_operands = 2
    assert max_operands == 2

    if isinstance(coupling_map, list):
        coupling_map = CouplingMap(coupling_map)
    if coupling_map != None and n_qubits < max(
            coupling_map.physical_qubits) + 1:
        raise CircuitError("n_qubits is not enough to accomodate CouplingMap")

    if basis_gates == None:
        basis_gates = gate_set

    one_q_ops = [
        label2gate[name] for name in one_q_ops_label & set(basis_gates)
    ]
    two_q_ops = [
        label2gate[name] for name in two_q_ops_label & set(basis_gates)
    ]
    one_param = [
        label2gate[name] for name in one_param_label & set(basis_gates)
    ]
    two_param = [
        label2gate[name] for name in two_param_label & set(basis_gates)
    ]
    three_param = [
        label2gate[name] for name in three_param_label & set(basis_gates)
    ]

    if len(one_q_ops) == 0:
        raise CircuitError("no available one-qubit gate")
    if len(two_q_ops) == 0:
        raise CircuitError("CNOT is not available")

    qreg = QuantumRegister(n_qubits, 'q')
    qc = QuantumCircuit(n_qubits)
    # default coupling_map is fully connected
    if coupling_map == None:
        coupling_map = CouplingMap.from_full(n_qubits)

    if reset:
        one_q_ops += [Reset]

    if seed is None:
        seed = np.random.randint(0, np.iinfo(np.int32).max)
    rng = np.random.RandomState(seed)

    for _ in range(depth):
        remaining_qubits = coupling_map.physical_qubits
        remaining_edges = coupling_map.get_edges()
        if remaining_edges:
            allow_two_q_op = True
        while remaining_qubits:
            if allow_two_q_op:
                max_possible_operands = min(len(remaining_qubits),
                                            max_operands)
            else:
                max_possible_operands = 1
            if max_possible_operands == 1:
                possible_operands_set = [1]
                num_operands = 1
            else:
                possible_operands_set = [1, 2]
                num_operands = (not (rng.uniform() < prob_one_q_op)) + 1
            if num_operands == 1:
                operation = rng.choice(one_q_ops)
                operands = rng.choice(remaining_qubits)
                register_operands = [qreg[int(operands)]]
                operands = [operands]
            elif num_operands == 2:
                operation = rng.choice(two_q_ops)
                operands = remaining_edges[rng.choice(
                    range(len(remaining_edges)))]
                register_operands = [qreg[i] for i in operands]
            remaining_qubits = [
                q for q in remaining_qubits if q not in operands
            ]
            if remaining_edges:
                remaining_edges = [
                    pair for pair in remaining_edges
                    if pair[0] not in operands and pair[1] not in operands
                ]
            if allow_two_q_op and not remaining_edges:
                allow_two_q_op = False
            if operation in one_param:
                num_angles = 1
            elif operation in two_param:
                num_angles = 2
            elif operation in three_param:
                num_angles = 3
            else:
                num_angles = 0
            angles = [rng.uniform(0, 2 * np.pi) for x in range(num_angles)]

            op = operation(*angles)

            qc.append(op, register_operands)

    return qc