Ejemplo n.º 1
0
 def test_append_gate_5(self) -> None:
     circuit = Circuit(4)
     circuit.append_gate(CNOTGate(), [0, 1])
     circuit.append_gate(CNOTGate(), [1, 2])
     circuit.append_gate(CNOTGate(), [2, 3])
     circuit.insert_qudit(4)
     circuit.append_gate(CNOTGate(), [0, 3])
     assert circuit.get_size() == 5
     assert len(circuit.get_radixes()) == 5
     assert circuit.get_radixes().count(2) == 5
     assert circuit[3, 0].gate == CNOTGate()
     assert circuit[3, 0].location == (0, 3)
     assert circuit[0, 1].gate == CNOTGate()
     assert circuit[0, 1].location == (0, 1)
     assert circuit[1, 2].gate == CNOTGate()
     assert circuit[1, 2].location == (1, 2)
     assert circuit[2, 3].gate == CNOTGate()
     assert circuit[2, 3].location == (2, 3)
     assert circuit[3, 3].gate == CNOTGate()
     assert circuit[3, 3].location == (0, 3)
     assert circuit[0, 0].gate == CNOTGate()
     assert circuit[0, 0].location == (0, 1)
     assert circuit[1, 1].gate == CNOTGate()
     assert circuit[1, 1].location == (1, 2)
     assert circuit[2, 2].gate == CNOTGate()
     assert circuit[2, 2].location == (2, 3)
Ejemplo n.º 2
0
 def test_append_gate_4(self, qudit_index: int) -> None:
     circuit = Circuit(4)
     circuit.append_gate(CNOTGate(), [0, 1])
     circuit.append_gate(CNOTGate(), [1, 2])
     circuit.append_gate(CNOTGate(), [2, 3])
     circuit.append_gate(CNOTGate(), [0, 1])
     circuit.append_gate(CNOTGate(), [1, 2])
     circuit.append_gate(CNOTGate(), [2, 3])
     circuit.append_gate(CNOTGate(), [0, 1])
     circuit.append_gate(CNOTGate(), [1, 2])
     circuit.append_gate(CNOTGate(), [2, 3])
     circuit.pop_qudit(qudit_index)
     assert circuit.get_size() == 3
     assert len(circuit.get_radixes()) == 3
     assert circuit.get_radixes().count(2) == 3
     assert circuit.get_num_operations() == 6
     assert circuit[0, 0].gate == CNOTGate()
     assert circuit[0, 0].location == (0, 1)
     assert circuit[1, 1].gate == CNOTGate()
     assert circuit[1, 1].location == (1, 2)
     assert circuit[2, 0].gate == CNOTGate()
     assert circuit[2, 0].location == (0, 1)
     assert circuit[3, 1].gate == CNOTGate()
     assert circuit[3, 1].location == (1, 2)
     assert circuit[4, 0].gate == CNOTGate()
     assert circuit[4, 0].location == (0, 1)
     assert circuit[5, 1].gate == CNOTGate()
     assert circuit[5, 1].location == (1, 2)
Ejemplo n.º 3
0
 def test_qubits(self) -> None:
     circuit = Circuit(1, [2])
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 2
     assert len(circuit.get_radixes()) == 1
     circuit.extend_qudits([2, 2])
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 8
     assert len(circuit.get_radixes()) == 3
     circuit.extend_qudits([2, 2])
     assert circuit.get_size() == 5
     assert circuit.get_dim() == 32
     assert len(circuit.get_radixes()) == 5
Ejemplo n.º 4
0
 def test_qutrits(self) -> None:
     circuit = Circuit(1, [3])
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 3
     assert len(circuit.get_radixes()) == 1
     circuit.extend_qudits([3, 3])
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 27
     assert len(circuit.get_radixes()) == 3
     circuit.extend_qudits([3, 3])
     assert circuit.get_size() == 5
     assert circuit.get_dim() == 243
     assert len(circuit.get_radixes()) == 5
Ejemplo n.º 5
0
 def test_qutrit(self) -> None:
     circuit = Circuit(1, [3])
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 3
     assert len(circuit.get_radixes()) == 1
     circuit.insert_qudit(0, 3)
     assert circuit.get_size() == 2
     assert circuit.get_dim() == 9
     assert len(circuit.get_radixes()) == 2
     circuit.insert_qudit(0, 3)
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 27
     assert len(circuit.get_radixes()) == 3
Ejemplo n.º 6
0
 def test_default(self) -> None:
     circuit = Circuit(1)
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 2
     assert len(circuit.get_radixes()) == 1
     circuit.append_qudit()
     assert circuit.get_size() == 2
     assert circuit.get_dim() == 4
     assert len(circuit.get_radixes()) == 2
     circuit.append_qudit()
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 8
     assert len(circuit.get_radixes()) == 3
Ejemplo n.º 7
0
 def test_multi_gate_3(self, gen_random_utry_np: Any) -> None:
     circuit = Circuit(4)
     three_qubit_gate = ConstantUnitaryGate(
         gen_random_utry_np(12), [2, 2, 3],
     )
     circuit.insert_qudit(2, 3)
     assert circuit.get_size() == 5
     assert len(circuit.get_radixes()) == 5
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 2
     assert circuit.get_radixes()[2] == 3
     assert circuit.get_radixes()[3] == 2
     assert circuit.get_radixes()[4] == 2
     circuit.append_gate(three_qubit_gate, [0, 1, 2])
     assert circuit[0, 0].gate == three_qubit_gate
     assert circuit[0, 0].location == (0, 1, 2)
Ejemplo n.º 8
0
    def run(self, circuit: Circuit, data: dict[str, Any]) -> None:
        """Perform the pass's operation, see BasePass for more info."""

        # Check data for windows markers
        if 'window_markers' not in data:
            _logger.warning('Did not find any window markers.')
            return

        window_markers = data['window_markers']
        _logger.debug('Found window_markers: %s.' % str(window_markers))

        if not is_iterable(window_markers):
            _logger.debug('Invalid type for window_markers.')
            return

        if not all(is_integer(marker) for marker in window_markers):
            _logger.debug('Invalid type for window_markers.')
            return

        # Resynthesis each window
        index_shift = 0
        for marker in window_markers:
            marker -= index_shift

            # Slice window
            begin_cycle = int(marker - self.window_size // 2)
            end_cycle = int(marker + np.ceil(self.window_size / 2))

            if begin_cycle < 0:
                begin_cycle = 0

            if end_cycle > circuit.get_num_cycles():
                end_cycle = circuit.get_num_cycles() - 1

            window = Circuit(circuit.get_size(), circuit.get_radixes())
            window.extend(circuit[begin_cycle:end_cycle])

            _logger.info(
                'Resynthesizing window from cycle '
                f'{begin_cycle} to {end_cycle}.', )

            # Synthesize
            utry = window.get_unitary()
            new_window = self.synthesispass.synthesize(utry, data)

            # Replace
            if self.replace_filter(new_window, window):
                _logger.debug('Replacing window with synthesized circuit.')

                actual_window_size = end_cycle - begin_cycle
                for _ in range(actual_window_size):
                    circuit.pop_cycle(begin_cycle)

                circuit.insert_circuit(
                    begin_cycle,
                    new_window,
                    list(range(circuit.get_size())),
                )

                index_shift += actual_window_size - new_window.get_num_cycles()
Ejemplo n.º 9
0
 def test_multi_gate_1(self, gen_random_utry_np: Any) -> None:
     circuit = Circuit(4)
     three_qubit_gate = ConstantUnitaryGate(gen_random_utry_np(8))
     circuit.append_gate(three_qubit_gate, [1, 2, 3])
     circuit.append_gate(three_qubit_gate, [0, 2, 3])
     circuit.append_gate(three_qubit_gate, [0, 1, 3])
     circuit.append_gate(three_qubit_gate, [0, 1, 2])
     circuit.insert_qudit(0)
     assert circuit.get_size() == 5
     assert len(circuit.get_radixes()) == 5
     assert circuit.get_radixes().count(2) == 5
     assert circuit[0, 2].gate == three_qubit_gate
     assert circuit[0, 2].location == (2, 3, 4)
     assert circuit[1, 1].gate == three_qubit_gate
     assert circuit[1, 1].location == (1, 3, 4)
     assert circuit[2, 1].gate == three_qubit_gate
     assert circuit[2, 1].location == (1, 2, 4)
     assert circuit[3, 1].gate == three_qubit_gate
     assert circuit[3, 1].location == (1, 2, 3)
Ejemplo n.º 10
0
 def test_multi_gate_1(
         self, qudit_index: int, gen_random_utry_np: Any,
 ) -> None:
     circuit = Circuit(4)
     three_qubit_gate = ConstantUnitaryGate(gen_random_utry_np(8))
     circuit.append_gate(three_qubit_gate, [1, 2, 3])
     circuit.append_gate(three_qubit_gate, [0, 2, 3])
     circuit.append_gate(three_qubit_gate, [0, 1, 3])
     circuit.append_gate(three_qubit_gate, [0, 1, 2])
     circuit.pop_qudit(qudit_index)
     assert circuit.get_size() == 3
     assert len(circuit.get_radixes()) == 3
     assert circuit.get_radixes().count(2) == 3
     assert circuit.get_num_operations() == 1
     assert circuit.get_num_cycles() == 1
     assert circuit[0, 0].gate == three_qubit_gate
     assert circuit[0, 0].location == (0, 1, 2)
     assert circuit[0, 1].gate == three_qubit_gate
     assert circuit[0, 1].location == (0, 1, 2)
     assert circuit[0, 2].gate == three_qubit_gate
     assert circuit[0, 2].location == (0, 1, 2)
Ejemplo n.º 11
0
 def test_empty(self) -> None:
     circuit = Circuit(1)
     assert len(circuit.get_radixes()) == 1
     assert circuit.get_radixes()[0] == 2
     circuit = Circuit(4)
     assert len(circuit.get_radixes()) == 4
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 2
     assert circuit.get_radixes()[2] == 2
     assert circuit.get_radixes()[3] == 2
     circuit = Circuit(4, [2, 2, 3, 3])
     assert len(circuit.get_radixes()) == 4
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 2
     assert circuit.get_radixes()[2] == 3
     assert circuit.get_radixes()[3] == 3
Ejemplo n.º 12
0
 def test_hybrid(self) -> None:
     circuit = Circuit(1)
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 2
     assert len(circuit.get_radixes()) == 1
     circuit.extend_qudits([3, 4])
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 24
     assert len(circuit.get_radixes()) == 3
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 3
     assert circuit.get_radixes()[2] == 4
     circuit.extend_qudits([3, 2])
     assert circuit.get_size() == 5
     assert circuit.get_dim() == 144
     assert len(circuit.get_radixes()) == 5
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 3
     assert circuit.get_radixes()[2] == 4
     assert circuit.get_radixes()[3] == 3
     assert circuit.get_radixes()[4] == 2
Ejemplo n.º 13
0
 def test_hybrid(self) -> None:
     circuit = Circuit(1)
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 2
     assert len(circuit.get_radixes()) == 1
     circuit.insert_qudit(0, 4)
     assert circuit.get_size() == 2
     assert circuit.get_dim() == 8
     assert len(circuit.get_radixes()) == 2
     assert circuit.get_radixes()[0] == 4
     assert circuit.get_radixes()[1] == 2
     circuit.insert_qudit(-1, 3)
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 24
     assert len(circuit.get_radixes()) == 3
     assert circuit.get_radixes()[0] == 4
     assert circuit.get_radixes()[1] == 3
     assert circuit.get_radixes()[2] == 2
Ejemplo n.º 14
0
 def test_hybrid(self) -> None:
     circuit = Circuit(1)
     assert circuit.get_size() == 1
     assert circuit.get_dim() == 2
     assert len(circuit.get_radixes()) == 1
     circuit.append_qudit(4)
     assert circuit.get_size() == 2
     assert circuit.get_dim() == 8
     assert len(circuit.get_radixes()) == 2
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 4
     circuit.append_qudit(3)
     assert circuit.get_size() == 3
     assert circuit.get_dim() == 24
     assert len(circuit.get_radixes()) == 3
     assert circuit.get_radixes()[0] == 2
     assert circuit.get_radixes()[1] == 4
     assert circuit.get_radixes()[2] == 3
Ejemplo n.º 15
0
 def test_get_radixes(self, toffoli_circuit: Circuit) -> None:
     assert len(toffoli_circuit.get_radixes()) == toffoli_circuit.get_size()
     assert isinstance(toffoli_circuit.get_radixes(), tuple)
     assert all(r == 2 for r in toffoli_circuit.get_radixes())
Ejemplo n.º 16
0
 def test_type(self, r6_qudit_circuit: Circuit) -> None:
     assert isinstance(r6_qudit_circuit.get_radixes(), tuple)
     assert all(is_integer(r) for r in r6_qudit_circuit.get_radixes())
Ejemplo n.º 17
0
    def run(self, circuit: Circuit, data: dict[str, Any]) -> None:
        """
        Partition gates in a circuit into a series of CircuitGates.

        Args:
            circuit (Circuit): Circuit to be partitioned.

            data (dict[str,Any]): Optional data unique to specific run.
        """

        if self.block_size > circuit.get_size():
            _logger.warning(
                'Configured block size is greater than circuit size; '
                'blocking entire circuit.', )
            circuit.fold({
                qudit_index: (0, circuit.get_num_cycles())
                for qudit_index in range(circuit.get_size())
            })
            return

        # If a MachineModel is provided in the data dict, it will be used.
        # Otherwise all-to-all connectivity is assumed.
        model = None

        if 'machine_model' in data:
            model = data['machine_model']

        if (not isinstance(model, MachineModel)
                or model.num_qudits < circuit.get_size()):
            _logger.warning(
                'MachineModel not specified or invalid;'
                ' defaulting to all-to-all.', )
            model = MachineModel(circuit.get_size())

        # Find all connected, `block_size`-sized groups of qudits
        # NOTE: This assumes circuit and topology qudit numbers are equal
        qudit_groups = model.get_locations(self.block_size)
        # Prune unused qudit groups
        used_qudits = [
            q for q in range(circuit.get_size())
            if not circuit.is_qudit_idle(q)
        ]
        for qudit_group in qudit_groups:
            if all([q not in used_qudits for q in qudit_group]):
                qudit_groups.remove(qudit_group)

        # divider splits the circuit into partitioned and unpartitioned spaces.
        active_qudits = circuit.get_active_qudits()
        num_cycles = circuit.get_num_cycles()
        divider = [
            0 if q in active_qudits else num_cycles
            for q in range(circuit.get_size())
        ]

        # Form regions until there are no more gates to partition
        regions: list[CircuitRegion] = []
        while any(cycle < num_cycles for cycle in divider):

            # Move past/skip any gates that are larger than block size
            qudits_to_increment: list[int] = []
            for qudit, cycle in enumerate(divider):
                if qudit in qudits_to_increment or cycle >= num_cycles:
                    continue

                if not circuit.is_point_idle((cycle, qudit)):
                    op = circuit[cycle, qudit]
                    if len(op.location) > self.block_size:
                        if all(divider[q] == cycle for q in op.location):
                            qudits_to_increment.extend(op.location)
                            _logger.warning(
                                'Skipping gate larger than block size.', )

            if len(qudits_to_increment) > 0:
                regions.append(
                    CircuitRegion(
                        {
                            qudit: (divider[qudit], divider[qudit])
                            for qudit in qudits_to_increment
                        }, ), )

            for qudit in qudits_to_increment:
                divider[qudit] += 1

            # Skip any idle qudit-cycles
            amount_to_add_to_each_qudit = [
                0 for _ in range(circuit.get_size())
            ]
            for qudit, cycle in enumerate(divider):
                while (cycle < num_cycles and circuit.is_point_idle(
                    (cycle, qudit))):
                    amount_to_add_to_each_qudit[qudit] += 1
                    cycle += 1

            for qudit, amount in enumerate(amount_to_add_to_each_qudit):
                divider[qudit] += amount

            # Find the scores of the qudit groups.
            best_score = None
            best_region = None

            for qudit_group in qudit_groups:

                ops_and_cycles = circuit.operations_with_cycles(
                    qudits_or_region=CircuitRegion({
                        qudit_index: (divider[qudit_index], num_cycles)
                        for qudit_index in qudit_group
                    }), )

                in_qudits = list(q for q in qudit_group)
                stopped_cycles = {q: num_cycles for q in qudit_group}
                score = 0

                for cycle, op in ops_and_cycles:
                    if len(op.location.union(in_qudits)) != len(in_qudits):
                        for qudit_index in op.location.intersection(in_qudits):
                            stopped_cycles[qudit_index] = cycle
                            in_qudits.remove(qudit_index)
                    else:
                        if len(op.location) > 1:
                            score += self.multi_gate_score
                        else:
                            score += self.single_gate_score

                    if len(in_qudits) == 0:
                        break

                if best_score is None or score > best_score:
                    best_score = score
                    best_region = CircuitRegion({
                        qudit: (
                            divider[qudit],
                            # Might have errors if below is removed
                            stopped_cycles[qudit] - 1,
                        )
                        for qudit in qudit_group
                        # This statement
                        # if stopped_cycles[qudit] - 1 >= divider[qudit]
                    })

            if best_score is None or best_region is None:
                raise RuntimeError('No valid block found.')

            _logger.info('Found block with score: %d.' % (best_score))
            regions.append(best_region)

            # Update divider
            for qudit_index in best_region:
                divider[qudit_index] = best_region[qudit_index].upper + 1

        # Fold the circuit
        folded_circuit = Circuit(circuit.get_size(), circuit.get_radixes())
        # Option to keep a block's idle qudits as part of the CircuitGate
        if 'keep_idle_qudits' in data and data['keep_idle_qudits'] is True:
            for region in regions:
                small_region = circuit.downsize_region(region)
                cgc = circuit.get_slice(small_region.points)
                if len(region.location) > len(small_region.location):
                    for i in range(len(region.location)):
                        if region.location[i] not in small_region.location:
                            cgc.insert_qudit(i)
                folded_circuit.append_gate(
                    CircuitGate(cgc, True),
                    sorted(list(region.keys())),
                    list(cgc.get_params()),
                )
        else:
            for region in regions:
                region = circuit.downsize_region(region)
                if 0 < len(region) <= self.block_size:
                    cgc = circuit.get_slice(region.points)
                    folded_circuit.append_gate(
                        CircuitGate(cgc, True),
                        sorted(list(region.keys())),
                        list(cgc.get_params()),
                    )
                else:
                    folded_circuit.extend(circuit[region])
        circuit.become(folded_circuit)
Ejemplo n.º 18
0
 def test_get_radixes(self, simple_circuit: Circuit) -> None:
     assert len(simple_circuit.get_radixes()) == simple_circuit.get_size()
     assert isinstance(simple_circuit.get_radixes(), tuple)
     assert all(r == 2 for r in simple_circuit.get_radixes())
Ejemplo n.º 19
0
 def test_value(self, r6_qudit_circuit: Circuit) -> None:
     if r6_qudit_circuit.get_radixes().count(3) == 6:
         assert r6_qudit_circuit.is_qutrit_only()
     else:
         assert not r6_qudit_circuit.is_qutrit_only()
Ejemplo n.º 20
0
 def test_value(self, r6_qudit_circuit: Circuit) -> None:
     assert is_valid_radixes(r6_qudit_circuit.get_radixes(), 6)
Ejemplo n.º 21
0
def circuit_gen(
    size: int,
    radixes: Sequence[int] = [],
    depth: int = 10,
    constant: bool = False,
    gateset: list[Gate] = BQSKIT_GATES,
) -> Circuit:
    """
    Generate a random circuit according to input specifications.

    Args:
        size (int): The number of qudits in the circuit.

        radixes (Sequence[int]): A sequence with its length equal
            to `size`. Each element specifies the base of a
            qudit. Defaults to qubits.

        depth (int): The number of gates in the circuit. (Default: 10)

        constant (bool): True implies the circuit will only consist of
            constant gates. (Default: False)

    Returns:
        (Circuit): The randomly generated circuit.
    """
    if not isinstance(depth, int):
        raise TypeError('Expected int for depth, got: %s.' % type(depth))

    if not isinstance(constant, bool):
        raise TypeError(
            'Expected bool for constant, got: %s.' % type(constant), )

    circuit = Circuit(size, radixes)

    # Apply a random gate to a random location `depth` times
    for d in range(depth):

        # 1. Select random qudit
        qudit_selected = np.random.randint(0, size)
        qudit_radix = circuit.get_radixes()[qudit_selected]

        # 2. Select random gate and location
        gate_selected = None
        location_selected = None

        # 2a. Shuffle gates
        shuffled_gates = gateset
        np.random.shuffle(shuffled_gates)

        # 2b. Find first gate that is compatible
        for gate in shuffled_gates:

            # must be compatible with qudit
            if qudit_radix not in gate.get_radixes():
                continue

            # must be compatible with the constant flag
            if constant and gate.is_parameterized():
                continue

            # must be compatible with circuit size
            if gate.get_size() > size:
                continue

            # must be compatible with circuit radix
            if not all(gate.get_radixes().count(unique_radix) <=
                       circuit.get_radixes().count(unique_radix)
                       for unique_radix in set(gate.get_radixes())):
                continue

            gate_selected = gate
            break

        if gate_selected is None:  # IdentityGate(1) should always be valid
            raise RuntimeError('Should never be reached.')

        # 3. Select location for gate
        location_selected = []
        qudit_selected_index = gate.get_radixes().index(qudit_radix)

        for i, radix in enumerate(gate.get_radixes()):
            # One qudit has already been matched
            if i == qudit_selected_index:
                location_selected.append(qudit_selected)
                continue

            # Find matching circuit qudit
            iter = 0
            qudit = None
            while (qudit is None or qudit in location_selected
                   or qudit == qudit_selected):
                qudit = circuit.get_radixes()[iter:].index(radix) + iter
                iter = qudit + 1
            location_selected.append(qudit)

        # 4. Append gate
        params = np.random.random(gate_selected.get_num_params())
        circuit.append_gate(gate_selected, location_selected, params)

    return circuit
Ejemplo n.º 22
0
 def test_r6_radix(self, r6_qudit_circuit: Circuit) -> None:
     count = r6_qudit_circuit.get_radixes().count(2)
     count += r6_qudit_circuit.get_radixes().count(3)
     assert count == r6_qudit_circuit.get_size()