コード例 #1
0
ファイル: region.py プロジェクト: BQSKit/bqskit
    def is_bounds(bounds: Any) -> bool:
        """Return true if bounds is a QuditBoundsLike."""
        if isinstance(bounds, QuditBounds):
            return True

        if not isinstance(bounds, tuple):
            _logger.debug('Bounds is not a tuple.')
            return False

        if len(bounds) != 2:
            _logger.debug(
                'Expected bounds to contain two values, got %d.' %
                len(bounds), )
            return False

        if not is_integer(bounds[0]):
            _logger.debug(
                'Expected integer values in bounds, got %s.' %
                type(bounds[0]), )
            return False

        if not is_integer(bounds[1]):
            _logger.debug(
                'Expected integer values in bounds, got %s.' %
                type(bounds[1]), )
            return False

        if bounds[1] < bounds[0]:
            _logger.debug('Upper bound is less than lower bound.')
            return False

        return True
コード例 #2
0
    def is_location(location: Any, num_qudits: int | None = None) -> bool:
        """
        Determines if the sequence of qudits form a valid location. A valid
        location is a set of qubit indices (integers) that are greater than or
        equal to zero, and if num_qudits is specified, less than num_qudits.

        Args:
            location (Any): The location to check.

            num_qudits (int | None): The total number of qudits.
                All qudit indices should be less than this. If None,
                don't check.

        Returns:
            (bool): True if the location is valid.
        """
        if isinstance(location, CircuitLocation):
            if num_qudits is not None:
                return max(location) < num_qudits
            return True

        if is_integer(location):
            location = [location]

        if not is_iterable(location):
            _logger.debug(
                'Expected iterable of integers for location'
                f', got {type(location)}.',
            )
            return False

        if not all(is_integer(qudit_index) for qudit_index in location):
            checks = [is_integer(qudit_index) for qudit_index in location]
            _logger.debug(
                'Expected iterable of integers for location'
                f', got atleast one {type(location[checks.index(False)])}.',
            )
            return False

        if not all(qudit_index >= 0 for qudit_index in location):
            checks = [qudit_index >= 0 for qudit_index in location]
            _logger.debug(
                'Expected iterable of positive integers for location'
                f', got atleast one {location[checks.index(False)]}.',
            )
            return False

        if len(set(location)) != len(location):
            _logger.debug('Location has duplicate qudit indices.')
            return False

        if num_qudits is not None:
            if not all([qudit < num_qudits for qudit in location]):
                _logger.debug('Location has an erroneously large qudit.')
                return False

        return True
コード例 #3
0
ファイル: scan.py プロジェクト: BQSKit/bqskit
    def __init__(
            self,
            block_size: int = 3,
            single_gate_score: int = 1,
            multi_gate_score:
        int = 1000,  # TODO: Pass callable scoring_fn instead
    ) -> None:
        """
        Construct a ScanPartitioner.

        Args:
            block_size (int): Maximum size of partitioned blocks.
                (Default: 3)

            single_gate_score (int): When evaluating potential blocks,
                use this number to score included single-qudit gates.
                (Default: 1)

            multi_gate_score (int): When evaluating potential blocks,
                use this number to score included multi-qudit gates.
                (Default: 1000)

        Raises:
            ValueError: If `block_size` is less than 2.
        """

        if not is_integer(block_size):
            raise TypeError(
                f'Expected integer for block_size, got {type(block_size)}.', )

        if block_size < 2:
            raise ValueError(
                f'Expected block_size to be greater than 2, got {block_size}.',
            )

        if not is_integer(single_gate_score):
            raise TypeError(
                'Expected integer for single_gate_score, '
                f'got {type(single_gate_score)}.', )

        if not is_integer(multi_gate_score):
            raise TypeError(
                'Expected integer for multi_gate_score, '
                f'got {type(multi_gate_score)}.', )

        self.block_size = block_size
        self.single_gate_score = single_gate_score
        self.multi_gate_score = multi_gate_score
コード例 #4
0
ファイル: window.py プロジェクト: BQSKit/bqskit
    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()
コード例 #5
0
ファイル: pauli.py プロジェクト: BQSKit/bqskit
    def __init__(self, size: int) -> None:
        """
        Construct the Pauli group for `size` number of qubits.

        Args:
            size (int): Power of the tensor product of the Pauli group.

        Raises:
            ValueError: If `size` is less than or equal to 0.
        """

        if not is_integer(size):
            raise TypeError('Expected integer for size, got %s.' % type(size))

        if size <= 0:
            raise ValueError(
                'Expected positive integer for size, got %s.' % type(size), )

        self.size = size

        if size == 1:
            self.paulis = [
                PauliMatrices.I,
                PauliMatrices.X,
                PauliMatrices.Y,
                PauliMatrices.Z,
            ]
        else:
            self.paulis = []
            matrices = it.product(PauliMatrices(size - 1), PauliMatrices(1))
            for pauli_n_1, pauli_1 in matrices:
                self.paulis.append(np.kron(pauli_n_1, pauli_1))
コード例 #6
0
    def random(size: int, radixes: Sequence[int] = []) -> UnitaryMatrix:
        """
        Sample a random unitary from the haar distribution.

        Args:
            size (np.ndarray): The number of qudits for the matrix. This
                is not the dimension.

            radixes (Sequence[int]): The radixes for the Unitary.

        Returns:
            (UnitaryMatrix): A random unitary matrix.
        """

        if not is_integer(size):
            raise TypeError('Expected int for size, got %s.' % type(size))

        if size <= 0:
            raise ValueError('Expected positive number for size.')

        radixes = tuple(radixes if len(radixes) > 0 else [2] * size)

        if not is_valid_radixes(radixes):
            raise TypeError('Invalid qudit radixes.')

        if len(radixes) != size:
            raise ValueError(
                'Expected length of radixes to be equal to size:'
                ' %d != %d' % (len(radixes), size), )

        U = unitary_group.rvs(int(np.prod(radixes)))
        return UnitaryMatrix(U, radixes, False)
コード例 #7
0
    def __eq__(self, other: object) -> bool:
        if isinstance(other, CircuitLocation):
            return self._location.__eq__(other._location)

        if is_integer(other):
            return len(self) == 1 and self[0] == other

        return self._location.__eq__(other)
コード例 #8
0
ファイル: region.py プロジェクト: BQSKit/bqskit
    def __contains__(self, cycle_index: object) -> bool:
        """Return true if `cycle_index` is inside this bounds."""
        if not is_integer(cycle_index):
            return False

        assert isinstance(cycle_index, int)  # TODO: Typeguards

        return self.lower <= cycle_index <= self.upper
コード例 #9
0
    def __init__(self, location: int | Iterable[int]) -> None:
        """
        Construct a CircuitLocation from `location`.

        Args:
            location (int | Iterable[int]): The qudit indices.

        Raises:
            ValueError: If any qudit index is negative.

            ValueError: If there are duplicates in location.
        """

        if is_integer(location):  # TODO: Typeguard
            location = [location]  # type: ignore

        assert not isinstance(location, int)  # TODO: Typeguard
        location = list(location)

        if not is_iterable(location):
            raise TypeError(
                'Expected iterable of integers for location'
                f', got {type(location)}.',
            )

        if not all(is_integer(qudit_index) for qudit_index in location):
            checks = [is_integer(qudit_index) for qudit_index in location]
            raise TypeError(
                'Expected iterable of integers for location'
                f', got atleast one {type(location[checks.index(False)])}.',
            )

        if not all(qudit_index >= 0 for qudit_index in location):
            checks = [qudit_index >= 0 for qudit_index in location]
            raise ValueError(
                'Expected iterable of positive integers for location'
                f', got atleast one {location[checks.index(False)]}.',
            )

        if len(set(location)) != len(location):
            raise ValueError('Location has duplicate qudit indices.')

        self._location: tuple[int, ...] = tuple(location)
コード例 #10
0
    def __init__(self, seed: int = 0) -> None:
        """
        Construct a SetRandomSeedPass.

        Args:
            seed (int): The value to set the random seed to.
        """

        if not is_integer(seed):
            raise TypeError('Expected integer seed, got %s.' % type(seed))

        self.seed = seed
コード例 #11
0
    def __init__(self, block_size: int = 3, num_points: int = 8) -> None:
        """
        Construct a ClusteringPartitioner.

        Args:
            block_size (int): Maximum size of partitioned blocks.
                (Default: 3)

            num_points (int): Total number of points to place and clusters
                to form. (Default: 8)

        Raises:
            ValueError: If `block_size` is less than 2.

            ValueError: if `num_points` is nonpositive.
        """

        if not is_integer(block_size):
            raise TypeError(
                f'Expected integer for block_size, got {type(block_size)}.',
            )

        if block_size < 2:
            raise ValueError(
                f'Expected block_size to be greater than 2, got {block_size}.',
            )

        if not is_integer(num_points):
            raise TypeError(
                f'Expected integer for num_points, got {type(num_points)}.',
            )

        if num_points < 1:
            raise ValueError(
                f'Expected num_points to positive, got {num_points}.',
            )

        self.block_size = block_size
        self.num_points = num_points
コード例 #12
0
ファイル: window.py プロジェクト: BQSKit/bqskit
    def __init__(
        self,
        window_size: int = 14,
        synthesispass: SynthesisPass = QSearchSynthesisPass(),
        replace_filter: Callable[[Circuit, Circuit], bool] | None = None,
    ) -> None:
        """
        Construct a WindowOptimizationPass.

        Args:
            window_size (int): The size of the window to surround each
                marker. (Default: 14)

            synthesispass (SynthesisPass): The configured synthesis algorithm
                to use during window synthesis.

            replace_filter (Callable[[Circuit, Circuit], bool] | None):
                A predicate that determines if the synthesis result should
                replace the original operation. The first parameter is the
                output from synthesis and the second parameter is the original
                window. If this returns true, the newly synthesized circuit
                will replace the original circuit. Defaults to always replace.

        Raises:
            ValueError: If `window_size` is <= 1.
        """

        if not is_integer(window_size):
            raise TypeError(
                'Expected integer for success_threshold'
                ', got %s' % type(window_size), )

        if window_size <= 1:
            raise ValueError(
                'Expected integer greater than 1 for window_size'
                ', got %d.' % window_size, )

        if not isinstance(synthesispass, SynthesisPass):
            raise TypeError(
                'Expected SynthesisPass, got %s.' % type(synthesispass), )

        self.replace_filter = replace_filter or default_replace_filter

        if not callable(self.replace_filter):
            raise TypeError(
                'Expected callable method for replace_filter'
                ', got %s.' % type(self.replace_filter), )

        self.window_size = window_size
        self.synthesispass = synthesispass
コード例 #13
0
    def __getitem__(
        self,
        index: int | slice | Sequence[int],
    ) -> int | tuple[int, ...]:
        """Retrieve one or multiple qudit indices from the location."""
        if is_integer(index):
            return self._location[index]  # type: ignore  # TODO: TypeGuards

        if isinstance(index, slice):
            return self._location[index]

        if not is_sequence(index):
            raise TypeError(f'Invalid index type, got {type(index)}.')

        # TODO: TypeGuards
        return tuple(self._location[idx] for idx in index)  # type: ignore
コード例 #14
0
ファイル: region.py プロジェクト: BQSKit/bqskit
    def is_region(region: Any) -> bool:
        """Return true if region is a CircuitRegionLike."""
        if isinstance(region, CircuitRegion):
            return True

        if not is_mapping(region):
            _logger.debug('Region is not a mapping.')
            return False

        if not all(is_integer(key) for key in region.keys()):
            _logger.debug('Region does not have integer keys.')
            return False

        if not all(QuditBounds.is_bounds(val) for val in region.values()):
            _logger.debug('Region does not have QuditBoundsLike values.')
            return False

        return True
コード例 #15
0
ファイル: region.py プロジェクト: BQSKit/bqskit
    def __contains__(self, other: object) -> bool:
        if is_integer(other):
            return other in self._bounds.keys()

        if CircuitPoint.is_point(other):  # TODO: TypeGuard
            return other[1] in self.keys() and other[0] in self[
                other[1]]  # type: ignore  # noqa

        if CircuitRegion.is_region(other):  # TODO: TypeGuard
            other = CircuitRegion(other)  # type: ignore
            return (
                all(qudit in self.keys() for qudit in other.keys()) and all(
                    self[qudit].lower <= other[qudit][0] <= self[qudit].upper
                    for qudit in self.keys()) and
                all(self[qudit].lower <= other[qudit][1] <= self[qudit].upper
                    for qudit in self.keys()))

        return NotImplemented
コード例 #16
0
ファイル: controlled.py プロジェクト: BQSKit/bqskit
    def __init__(
        self,
        gate: Gate,
        num_controls: int = 1,
        radixes: Sequence[int] = [],
    ) -> None:
        """Construct a ControlledGate."""

        if not isinstance(gate, Gate):
            raise TypeError('Expected gate object, got %s.' % type(gate))

        if not is_integer(num_controls):
            raise TypeError(
                'Expected integer for num_controls, got %s.'
                % type(num_controls),
            )

        if num_controls < 1:
            raise ValueError(
                'Expected positive integer for num_controls, got %d.'
                % num_controls,
            )

        if len(radixes) != 0 and not is_valid_radixes(radixes, num_controls):
            raise TypeError('Invalid radixes.')

        self.gate = gate
        self.size = gate.get_size() + num_controls
        self.num_controls = num_controls
        self.radixes = tuple(radixes or [2] * self.size) + gate.get_radixes()
        self.name = '%d-Controlled(%s)' % (num_controls, gate.get_name())
        self.num_params = gate.get_num_params()

        self.Ic = np.identity(2 ** num_controls)  # TODO: General radix support
        self.It = np.identity(gate.get_dim())
        self.OneProj = np.zeros(self.Ic.shape)
        self.OneProj[-1, -1] = 1
        self.left = np.kron((self.Ic - self.OneProj), self.It)

        # If input is a constant gate, we can cache the unitary.
        if self.num_params == 0:
            U = self.gate.get_unitary()
            right = np.kron(self.OneProj, U)
            self.utry = UnitaryMatrix(self.left + right, self.get_radixes())
コード例 #17
0
ファイル: pauli.py プロジェクト: BQSKit/bqskit
    def get_projection_matrices(
        self,
        q_set: Sequence[int],
    ) -> list[np.ndarray]:
        """
        Return the Pauli matrices that act only on qubits in `q_set`.

        Args:
            q_set (Sequence[int]): Active qubit indices

        Returns:
            (list(np.ndarray)): Pauli matrices from `self` acting only
                on qubits in `q_set`.

        Raises:
            ValueError: if `q_set` is an invalid set of qubit indices.
        """

        if not all(is_integer(q) for q in q_set):
            raise TypeError('Expected sequence of integers for qubit indices.')

        if any(q < 0 or q >= self.size for q in q_set):
            raise ValueError('Qubit indices must be in [0, n).')

        if len(q_set) != len(set(q_set)):
            raise ValueError('Qubit indices cannot have duplicates.')

        if len(q_set) == 0:
            raise ValueError('Need at least one qubit index.')

        # Nth Order Pauli Matrices can be thought of base 4 number
        # I = 0, X = 1, Y = 2, Z = 3
        # XXY = 1 * 4^2 + 1 * 4^1 + 2 * 4^0 = 22 (base 10)
        # This gives the idx of XXY in paulis
        # Note we read qubit index from the left,
        # so X in XII corresponds to q = 0
        pauli_n_qubit = []
        for ps in it.product([0, 1, 2, 3], repeat=len(q_set)):
            idx = 0
            for p, q in zip(ps, q_set):
                idx += p * (4**(self.size - q - 1))
            pauli_n_qubit.append(self.paulis[idx])

        return pauli_n_qubit
コード例 #18
0
ファイル: machine.py プロジェクト: BQSKit/bqskit
    def get_locations(self, block_size: int) -> list[CircuitLocation]:
        """
        Returns a list of locations that complies with the machine.

        Each location describes a valid spot for a `block_size`-sized gate,
        so the number of qudit_indices in each location is `block_size`.
        A location is only included if each pair of qudits is directly
        connected or connected through other qudits in the location.

        Args:
            block_size (int): The size of each location in the final list.

        Returns:
            (list[CircuitLocation]): The locations compliant with the machine.

        Raises:
            ValueError: If `block_size` is nonpositive or too large.

        Notes:
            Does a breadth first search on all pairs of qudits, keeps paths
            that have length equal to block_size. Note that the coupling map
            is assumed to be undirected.
        """

        if not is_integer(block_size):
            raise TypeError(
                f'Expected integer for block_size, got {type(block_size)}', )

        if block_size > self.num_qudits:
            raise ValueError(
                'The block_size is too large; '
                f'expected <= {self.num_qudits}, got {block_size}.', )

        if block_size <= 0:
            raise ValueError('Nonpositive block_size; got {block_size}.')

        locations: set[CircuitLocation] = set()

        for qudit in range(self.num_qudits):
            # Get every valid set containing `qudit` with size == block_size
            self._location_search(locations, set(), qudit, block_size)

        return list(locations)
コード例 #19
0
ファイル: machine.py プロジェクト: BQSKit/bqskit
    def __init__(
        self,
        num_qudits: int,
        coupling_graph: Iterable[tuple[int, int]] | None = None,
    ) -> None:
        """
        MachineModel Constructor.

        Args:
            num_qudits (int): The total number of qudits in the machine.

            coupling_graph (Iterable[tuple[int, int]] | None): A coupling
                graph describing which pairs of qudits can interact.
                Given as an undirected edge set. If left as None, then
                an all-to-all coupling graph is used as a default.
                (Default: None)

        Raises:
            ValueError: If `num_qudits` is nonpositive.
        """

        if not is_integer(num_qudits):
            raise TypeError(
                f'Expected integer num_qudits, got {type(num_qudits)}.', )

        if num_qudits <= 0:
            raise ValueError(
                f'Expected positive num_qudits, got {num_qudits}.')

        if coupling_graph is None:
            coupling_graph = set(it.combinations(range(num_qudits), 2))

        if not is_valid_coupling_graph(coupling_graph, num_qudits):
            raise TypeError('Invalid coupling graph.')

        self.coupling_graph = set(coupling_graph)
        self.num_qudits = num_qudits

        self._adjacency_list: list[list[int]] = [[] for _ in range(num_qudits)]
        for q0, q1 in self.coupling_graph:
            self._adjacency_list[q0].append(q1)
            self._adjacency_list[q1].append(q0)
コード例 #20
0
ファイル: unitarybuilder.py プロジェクト: BQSKit/bqskit
    def __init__(self, size: int, radixes: Sequence[int] = []) -> None:
        """
        UnitaryBuilder constructor.

        Args:
            size (int): The number of qudits to build a Unitary for.

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

        Raises:
            ValueError: if size is nonpositive.

        Examples:
            >>> builder = UnitaryBuilder(4)  # Creates a 4-qubit builder.
        """

        if not is_integer(size):
            raise TypeError('Expected int for size, got %s.' % type(size))

        if size <= 0:
            raise ValueError('Expected positive number for size.')

        self.size = size
        self.radixes = tuple(radixes if len(radixes) > 0 else [2] * self.size)

        if not is_valid_radixes(self.radixes):
            raise TypeError('Invalid qudit radixes.')

        if len(self.radixes) != self.size:
            raise ValueError(
                'Expected length of radixes to be equal to size:'
                ' %d != %d' % (len(self.radixes), self.size),
            )

        self.num_params = 0
        self.dim = int(np.prod(self.radixes))
        self.tensor = np.identity(self.get_dim())
        self.tensor = self.tensor.reshape(self.radixes * 2)
コード例 #21
0
ファイル: instantiater.py プロジェクト: BQSKit/bqskit
    def gen_starting_points(
        self,
        multistarts: int,
        circuit: Circuit,
        target: UnitaryMatrix | StateVector,
    ) -> list[np.ndarray]:
        """
        Generate `multistarts` starting points for instantiation.

        Args:
            multistarts (int): The number of starting points to generate.

            circuit (Circuit): The circuit to generate the points for.

            target (UnitaryMatrix | StateVector): The target.

        Return:
            (list[np.ndarray]): List of starting inputs for instantiation.

        Raises:
            ValueError: If `multistarts` is not a positive integer.
        """
        if not is_integer(multistarts):
            raise TypeError(
                'Expected int for multistarts, got %s.' % type(multistarts),
            )

        if multistarts <= 0:
            raise ValueError(
                'Expected positive integer for multistarts'
                ', got %d' % multistarts,
            )

        return [  # [ circuit.get_params() ] + [  # TODO: re-evaluate
            np.random.random(circuit.get_num_params())
            for i in range(multistarts)
        ]
コード例 #22
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_a_seq_float(self, a_seq_float: Any) -> None:
     assert is_sequence(a_seq_float)
     assert len(a_seq_float) >= 0
     assert all(
         is_numeric(f) and not is_integer(f) and not is_complex(f)
         for f in a_seq_float)
コード例 #23
0
    def __init__(
        self,
        heuristic_function: HeuristicFunction = AStarHeuristic(),
        layer_generator: LayerGenerator = SimpleLayerGenerator(),
        success_threshold: float = 1e-10,
        cost: CostFunctionGenerator = HilbertSchmidtResidualsGenerator(),
        max_layer: int | None = None,
        min_prefix_size: int = 3,
        instantiate_options: dict[str, Any] = {},
        **kwargs: Any,
    ) -> None:
        """
        Construct a search-based synthesis pass.

        Args:
            heuristic_function (HeuristicFunction): The heuristic to guide
                search.

            layer_generator (LayerGenerator): The successor function
                to guide node expansion.

            success_threshold (float): The distance threshold that
                determines successful termintation. Measured in cost
                described by the cost function. (Default: 1e-10)

            cost (CostFunction | None): The cost function that determines
                distance during synthesis. The goal of this synthesis pass
                is to implement circuits for the given unitaries that have
                a cost less than the `success_threshold`.
                (Default: HSDistance())

            max_layer (int): The maximum number of layers to append without
                success before termination. If left as None it will default
                 to unlimited. (Default: None)

            min_prefix_size (int): The minimum number of layers needed
                to prefix the circuit.

            instantiate_options (dict[str: Any]): Options passed directly
                to circuit.instantiate when instantiating circuit
                templates. (Default: {})

            kwargs (dict[str, Any]): Keyword arguments that are passed
                directly to SynthesisPass's constructor. See SynthesisPass
                for more info.

        Raises:
            ValueError: If `max_depth` or `min_prefix_size` is nonpositive.
        """
        if not isinstance(heuristic_function, HeuristicFunction):
            raise TypeError(
                'Expected HeursiticFunction, got %s.' %
                type(heuristic_function), )

        if not isinstance(layer_generator, LayerGenerator):
            raise TypeError(
                'Expected LayerGenerator, got %s.' % type(layer_generator), )

        if not is_real_number(success_threshold):
            raise TypeError(
                'Expected real number for success_threshold'
                ', got %s' % type(success_threshold), )

        if not isinstance(cost, CostFunctionGenerator):
            raise TypeError(
                'Expected cost to be a CostFunctionGenerator, got %s' %
                type(cost), )

        if max_layer is not None and not is_integer(max_layer):
            raise TypeError(
                'Expected max_layer to be an integer, got %s' %
                type(max_layer), )

        if max_layer is not None and max_layer <= 0:
            raise ValueError(
                'Expected max_layer to be positive, got %d.' %
                int(max_layer), )

        if min_prefix_size is not None and not is_integer(min_prefix_size):
            raise TypeError(
                'Expected min_prefix_size to be an integer, got %s' %
                type(min_prefix_size), )

        if min_prefix_size is not None and min_prefix_size <= 0:
            raise ValueError(
                'Expected min_prefix_size to be positive, got %d.' %
                int(min_prefix_size), )

        if not isinstance(instantiate_options, dict):
            raise TypeError(
                'Expected dictionary for instantiate_options, got %s.' %
                type(instantiate_options), )

        self.heuristic_function = heuristic_function
        self.layer_gen = layer_generator
        self.success_threshold = success_threshold
        self.cost = cost
        self.max_layer = max_layer
        self.min_prefix_size = min_prefix_size
        self.instantiate_options: dict[str, Any] = {'cost_fn_gen': self.cost}
        self.instantiate_options.update(instantiate_options)
        super().__init__(**kwargs)
コード例 #24
0
    def __init__(
        self,
        block_size_start: int = 2,
        block_size_limit: int | None = None,
        fail_limit: int = 3,
        success_threshold: float = 1e-6,
        progress_threshold_r: float = 5e-2,
        progress_threshold_a: float = 1e-4,
        cost: CostFunctionGenerator = HilbertSchmidtResidualsGenerator(),
        max_depth: int | None = None,
        instantiate_options: dict[str, Any] = {},
        **kwargs: dict[str, Any],
    ) -> None:
        """
        QPredictDecompositionPass Constructor.

        Args:
            block_size_start (int): The smallest block size to append
                each step. (Default: 2)

            block_size_limit (int | None): The largest block size to append
                each step. If left as None, the unitary being synthesized
                provides the limit. (Default: None)

            fail_limit (int): The amount of tries to make progress before
                increasing block size. (Default: 2)

            success_threshold (float): The distance threshold that
                determines successful termintation. Measured in cost
                described by the cost function. (Default: 1e-6)

            progress_threshold (float): The distance necessary to improve
                for the synthesis algorithm to complete a layer and move
                on. Lowering this will led to synthesis going deeper quicker,
                and raising it will force to algorithm to spend more time
                on each layer. Caution, changing this too much might break
                the synthesis algorithm. (Default: 5e-3)

            cost (CostFunction | None): The cost function that determines
                distance during synthesis. The goal of this synthesis pass
                is to implement circuits for the given unitaries that have
                a cost less than the `success_threshold`.
                (Default: HSDistance())

            max_depth (int): The maximum number of gates to append without
                success before termination. If left as None it will default
                 to unlimited. (Default: None)

            instantiate_options (dict[str: Any]): Options passed directly
                to circuit.instantiate when instantiating circuit
                templates. (Default: {})

            kwargs (dict[str, Any]): Keyword arguments that are passed
                directly to SynthesisPass's constructor. See SynthesisPass
                for more info.

        Raises:
            ValueError: If `block_size_start` is nonpositive.

            ValueError: If `block_size_limit` is less than `block_size_start`.

            ValueError: If `fail_limit` is nonpositive.

            ValueError: If `max_depth` is nonpositive.
        """

        if not is_integer(block_size_start):
            raise TypeError(
                'Expected block_size_start to be an integer, got %s' %
                type(block_size_start), )

        if block_size_start <= 0:
            raise ValueError(
                'Expected block_size_start to be positive, got %d.' %
                block_size_start, )

        if block_size_limit is not None and not is_integer(block_size_limit):
            raise TypeError(
                'Expected block_size_limit to be an integer, got %s' %
                type(block_size_limit), )

        if block_size_limit is not None and block_size_limit < block_size_start:
            raise ValueError(
                'Expected block_size_limit to be larger than block_size_start,'
                'got %d.' % block_size_limit, )

        if not is_integer(fail_limit):
            raise TypeError(
                'Expected fail_limit to be an integer, got %s' %
                type(fail_limit), )

        if fail_limit <= 0:
            raise ValueError(
                'Expected fail_limit to be positive, got %d.' % fail_limit, )

        if not is_real_number(success_threshold):
            raise TypeError(
                'Expected real number for success_threshold'
                ', got %s' % type(success_threshold), )

        if not is_real_number(progress_threshold_r):
            raise TypeError(
                'Expected real number for progress_threshold_r'
                ', got %s' % type(progress_threshold_r), )

        if not is_real_number(progress_threshold_a):
            raise TypeError(
                'Expected real number for progress_threshold_a'
                ', got %s' % type(progress_threshold_a), )

        if not isinstance(cost, CostFunctionGenerator):
            raise TypeError(
                'Expected cost to be a CostFunctionGenerator, got %s' %
                type(cost), )

        if max_depth is not None and not is_integer(max_depth):
            raise TypeError(
                'Expected max_depth to be an integer, got %s' %
                type(max_depth), )

        if max_depth is not None and max_depth <= 0:
            raise ValueError(
                'Expected max_depth to be positive, got %d.' %
                int(max_depth), )

        if not isinstance(instantiate_options, dict):
            raise TypeError(
                'Expected dictionary for instantiate_options, got %s.' %
                type(instantiate_options), )

        self.block_size_start = block_size_start
        self.block_size_limit = block_size_limit
        self.fail_limit = fail_limit
        self.success_threshold = success_threshold
        self.progress_threshold_r = progress_threshold_r
        self.progress_threshold_a = progress_threshold_a
        self.cost = cost
        self.max_depth = max_depth
        self.instantiate_options = {
            'min_iters': 25,
            'diff_tol_r': 1e-4,
        }
        self.instantiate_options.update(instantiate_options)
        super().__init__(**kwargs)  # type: ignore
コード例 #25
0
ファイル: test_properties.py プロジェクト: BQSKit/bqskit
 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())
コード例 #26
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_a_float(self, a_float: Any) -> None:
     assert (is_numeric(a_float) and not is_integer(a_float)
             and not is_complex(a_float))
コード例 #27
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_not_a_float(self, not_a_float: Any) -> None:
     assert (not is_numeric(not_a_float) or is_integer(not_a_float)
             or is_complex(not_a_float))
コード例 #28
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_a_seq_int(self, a_seq_int: Any) -> None:
     assert is_sequence(a_seq_int)
     assert len(a_seq_int) >= 0
     assert all(is_integer(i) for i in a_seq_int)
コード例 #29
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_not_a_seq_int(self, not_a_seq_int: Any) -> None:
     assert (not is_sequence(not_a_seq_int)
             or isinstance(not_a_seq_int, str)
             or any(not is_integer(i) for i in not_a_seq_int))
コード例 #30
0
ファイル: test_conftest.py プロジェクト: BQSKit/bqskit
 def test_not_a_seq_float(self, not_a_seq_float: Any) -> None:
     assert (not is_sequence(not_a_seq_float)
             or isinstance(not_a_seq_float, str)
             or any(not is_numeric(f) or is_integer(f) or is_complex(f)
                    for f in not_a_seq_float))