def test_iadd_overload(self): """Test the overloaded + operator.""" num_qubits, depth = 2, 2 # construct two circuits for adding first_circuit = random_circuit(num_qubits, depth, seed=4242) circuit = random_circuit(num_qubits, depth, seed=4242) # get a reference reference = first_circuit + circuit # convert the object to be appended to different types others = [ circuit, circuit.to_instruction(), circuit.to_gate(), NLocal(circuit) ] # try adding each type for other in others: nlocal = NLocal(num_qubits, entanglement_blocks=first_circuit, reps=1) nlocal += other with self.subTest(msg='type: {}'.format(type(other))): self.assertCircuitEqual(nlocal, reference)
def test_skip_unentangled_qubits(self): """Test skipping the unentangled qubits.""" num_qubits = 6 entanglement_1 = [[0, 1, 3], [1, 3, 5], [0, 1, 5]] skipped_1 = [2, 4] entanglement_2 = [entanglement_1, [[0, 1, 2], [2, 3, 5]]] skipped_2 = [4] for entanglement, skipped in zip([entanglement_1, entanglement_2], [skipped_1, skipped_2]): with self.subTest(entanglement=entanglement, skipped=skipped): nlocal = NLocal( num_qubits, rotation_blocks=XGate(), entanglement_blocks=CCXGate(), entanglement=entanglement, reps=3, skip_unentangled_qubits=True, ) skipped_set = set(nlocal.qubits[i] for i in skipped) dag = circuit_to_dag(nlocal) idle = set(dag.idle_wires()) self.assertEqual(skipped_set, idle)
def test_entanglement_by_str(self, entanglement): """Test setting the entanglement of the layers by str.""" reps = 3 nlocal = NLocal(5, rotation_blocks=XGate(), entanglement_blocks=CCXGate(), entanglement=entanglement, reps=reps) def get_expected_entangler_map(rep_num, mode): if mode == 'linear': return [(0, 1, 2), (1, 2, 3), (2, 3, 4)] elif mode == 'full': return [(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)] else: circular = [(3, 4, 0), (0, 1, 2), (1, 2, 3), (2, 3, 4)] if mode == 'circular': return circular sca = circular[-rep_num:] + circular[:-rep_num] if rep_num % 2 == 1: sca = [tuple(reversed(indices)) for indices in sca] return sca for rep_num in range(reps): entangler_map = nlocal.get_entangler_map(rep_num, 0, 3) if isinstance(entanglement, list): mode = entanglement[rep_num % len(entanglement)] else: mode = entanglement expected = get_expected_entangler_map(rep_num, mode) with self.subTest(rep_num=rep_num): # using a set here since the order does not matter self.assertEqual(set(entangler_map), set(expected))
def test_pairwise_entanglement_raises(self): """Test choosing pairwise entanglement raises an error for too large blocks.""" nlocal = NLocal(3, XGate(), CCXGate(), entanglement='pairwise', reps=1) # pairwise entanglement is only defined if the entangling gate has 2 qubits with self.assertRaises(ValueError): print(nlocal.draw())
def test_initial_state_as_circuit_object(self): """Test setting `initial_state` to `QuantumCircuit` object""" # ┌───┐ ┌───┐ # q_0: ──■──┤ X ├───────■──┤ X ├ # ┌─┴─┐├───┤┌───┐┌─┴─┐├───┤ # q_1: ┤ X ├┤ H ├┤ X ├┤ X ├┤ X ├ # └───┘└───┘└───┘└───┘└───┘ ref = QuantumCircuit(2) ref.cx(0, 1) ref.x(0) ref.h(1) ref.x(1) ref.cx(0, 1) ref.x(0) ref.x(1) qc = QuantumCircuit(2) qc.cx(0, 1) qc.h(1) expected = NLocal( num_qubits=2, rotation_blocks=XGate(), entanglement_blocks=CXGate(), initial_state=qc, reps=1, ) self.assertCircuitEqual(ref, expected)
def test_pairwise_entanglement(self): """Test pairwise entanglement.""" nlocal = NLocal(5, rotation_blocks=XGate(), entanglement_blocks=CXGate(), entanglement='pairwise', reps=1) entangler_map = nlocal.get_entangler_map(0, 0, 2) pairwise = [(0, 1), (2, 3), (1, 2), (3, 4)] self.assertEqual(pairwise, entangler_map)
def test_add_layer_to_empty_nlocal(self, block, entangler_map): """Test appending gates to an empty nlocal.""" nlocal = NLocal() nlocal.add_layer(block, entangler_map) max_num_qubits = max(max(indices) for indices in entangler_map) reference = QuantumCircuit(max_num_qubits + 1) for indices in entangler_map: reference.append(block, indices) self.assertCircuitEqual(nlocal, reference)
def test_parameter_getter_from_automatic_repetition(self): """Test getting and setting of the nlocal parameters.""" circuit = QuantumCircuit(2) circuit.ry(Parameter('a'), 0) circuit.crx(Parameter('b'), 0, 1) # repeat circuit and check that parameters are duplicated reps = 3 nlocal = NLocal(2, entanglement_blocks=circuit, reps=reps) self.assertTrue(nlocal.num_parameters, 6) self.assertTrue(len(nlocal.parameters), 6)
def test_empty_nlocal(self): """Test the creation of an empty NLocal.""" nlocal = NLocal() self.assertEqual(nlocal.num_qubits, 0) self.assertEqual(nlocal.num_parameters_settable, 0) self.assertEqual(nlocal.reps, 1) self.assertEqual(nlocal, QuantumCircuit()) for attribute in [nlocal.rotation_blocks, nlocal.entanglement_blocks]: self.assertEqual(len(attribute), 0)
def test_entanglement_by_list(self): """Test setting the entanglement by list. This is the circuit we test (times 2, with final X layer) ┌───┐ ┌───┐┌───┐ ┌───┐ q_0: |0>┤ X ├──■────■───X────┤ X ├┤ X ├──■───X─────── .. ┤ X ├ ├───┤ │ │ │ ├───┤└─┬─┘ │ │ ├───┤ q_1: |0>┤ X ├──■────┼───┼──X─┤ X ├──■────┼───X──X──── .. ┤ X ├ ├───┤┌─┴─┐ │ │ │ ├───┤ │ │ │ x2 ├───┤ q_2: |0>┤ X ├┤ X ├──■───┼──X─┤ X ├──■────■──────X──X─ .. ┤ X ├ ├───┤└───┘┌─┴─┐ │ ├───┤ ┌─┴─┐ │ ├───┤ q_3: |0>┤ X ├─────┤ X ├─X────┤ X ├─────┤ X ├───────X─ .. ┤ X ├ └───┘ └───┘ └───┘ └───┘ └───┘ """ circuit = QuantumCircuit(4) for _ in range(2): circuit.x([0, 1, 2, 3]) circuit.barrier() circuit.ccx(0, 1, 2) circuit.ccx(0, 2, 3) circuit.swap(0, 3) circuit.swap(1, 2) circuit.barrier() circuit.x([0, 1, 2, 3]) circuit.barrier() circuit.ccx(2, 1, 0) circuit.ccx(0, 2, 3) circuit.swap(0, 1) circuit.swap(1, 2) circuit.swap(2, 3) circuit.barrier() circuit.x([0, 1, 2, 3]) layer_1_ccx = [(0, 1, 2), (0, 2, 3)] layer_1_swap = [(0, 3), (1, 2)] layer_1 = [layer_1_ccx, layer_1_swap] layer_2_ccx = [(2, 1, 0), (0, 2, 3)] layer_2_swap = [(0, 1), (1, 2), (2, 3)] layer_2 = [layer_2_ccx, layer_2_swap] entanglement = [layer_1, layer_2] nlocal = NLocal( 4, rotation_blocks=XGate(), entanglement_blocks=[CCXGate(), SwapGate()], reps=4, entanglement=entanglement, insert_barriers=True, ) self.assertCircuitEqual(nlocal, circuit)
def test_add_nlocal(self, num_qubits): """Test adding an nlocal to an nlocal (using add_layer).""" # fixed depth of 3 gates per circuit depth = 3 # keep track of a reference circuit reference = QuantumCircuit(max(num_qubits)) # construct the NLocal from the first circuit first_circuit = random_circuit(num_qubits[0], depth, seed=4220) # TODO Terra bug: if this is to_gate it fails, since the QC adds an instruction not gate nlocal = NLocal(max(num_qubits), entanglement_blocks=first_circuit.to_instruction(), reps=1) reference.append(first_circuit, list(range(num_qubits[0]))) # append the rest for num in num_qubits[1:]: circuit = random_circuit(num, depth, seed=4220) nlocal.add_layer(NLocal(num, entanglement_blocks=circuit, reps=1)) reference.append(circuit, list(range(num))) self.assertCircuitEqual(nlocal, reference)
def test_parameter_setter_from_automatic_repetition(self, params): """Test getting and setting of the nlocal parameters.""" circuit = QuantumCircuit(2) circuit.ry(Parameter('a'), 0) circuit.crx(Parameter('b'), 0, 1) # repeat circuit and check that parameters are duplicated reps = 3 nlocal = NLocal(2, entanglement_blocks=circuit, reps=reps) nlocal.assign_parameters(params, inplace=True) param_set = set(p for p in params if isinstance(p, ParameterExpression)) with self.subTest(msg='Test the parameters of the non-transpiled circuit'): # check the parameters of the final circuit self.assertEqual(nlocal.parameters, param_set) with self.subTest(msg='Test the parameters of the transpiled circuit'): basis_gates = ['id', 'u1', 'u2', 'u3', 'cx'] transpiled_circuit = transpile(nlocal, basis_gates=basis_gates) self.assertEqual(transpiled_circuit.parameters, param_set)
def test_repetetive_parameter_setting(self): """Test alternate setting of parameters and circuit construction.""" x = Parameter('x') circuit = QuantumCircuit(1) circuit.rx(x, 0) nlocal = NLocal(1, entanglement_blocks=circuit, reps=3, insert_barriers=True) with self.subTest(msg='immediately after initialization'): self.assertEqual(len(nlocal.parameters), 3) with self.subTest(msg='after circuit construction'): self.assertEqual(len(nlocal.parameters), 3) q = Parameter('q') nlocal.assign_parameters([x, q, q], inplace=True) with self.subTest(msg='setting parameter to Parameter objects'): self.assertEqual(nlocal.parameters, set({x, q})) nlocal.assign_parameters([0, -1], inplace=True) with self.subTest(msg='setting parameter to numbers'): self.assertEqual(nlocal.parameters, set())
def test_parameters_setter(self, params): """Test setting the parameters via list.""" # construct circuit with some parameters initial_params = ParameterVector('p', length=6) circuit = QuantumCircuit(1) for i, initial_param in enumerate(initial_params): circuit.ry(i * initial_param, 0) # create an NLocal from the circuit and set the new parameters nlocal = NLocal(1, entanglement_blocks=circuit, reps=1) nlocal.assign_parameters(params, inplace=True) param_set = set(p for p in params if isinstance(p, ParameterExpression)) with self.subTest(msg='Test the parameters of the non-transpiled circuit'): # check the parameters of the final circuit self.assertEqual(nlocal.parameters, param_set) with self.subTest(msg='Test the parameters of the transpiled circuit'): basis_gates = ['id', 'u1', 'u2', 'u3', 'cx'] transpiled_circuit = transpile(nlocal, basis_gates=basis_gates) self.assertEqual(transpiled_circuit.parameters, param_set)
def test_reps_setter_when_negative(self): """Test to check if setter raises error for reps <=0""" nlocal = NLocal(reps=1) with self.assertRaises(ValueError): nlocal.reps = -1
def test_if_reps_is_zero(self): """Test to check if error is raised for 0 or negative value of reps""" with self.assertRaises(ValueError): _ = NLocal(reps=-1)
def test_if_reps_is_str(self): """Test to check if proper error is raised for str value of reps""" with self.assertRaises(TypeError): _ = NLocal(reps="3")
def test_if_reps_is_float(self): """Test to check if proper error is raised for float value of reps""" with self.assertRaises(TypeError): _ = NLocal(reps=5.6)
def test_if_reps_is_npint64(self): """Equality test for reps with int value and np.int64 value""" self.assertEqual(NLocal(reps=3), NLocal(reps=np.int64(3)))