Пример #1
0
    def dot_product(self, alpha: Sequence[float] | np.ndarray) -> np.ndarray:
        """
        Computes the standard dot product of `alpha` with the paulis.

        Args:
            alpha (Sequence[float] | np.ndarray): The pauli coefficients.

        Returns:
            (np.ndarray): Sum of element-wise multiplication of `alpha`
                and `self.paulis`.

        Raises:
            ValueError: If `alpha` and `self.paulis` are incompatible.
        """

        if not is_sequence(alpha) or not all(is_numeric(a) for a in alpha):
            raise TypeError(
                'Expected a sequence of numbers, got %s.' % type(alpha), )

        if len(alpha) != len(self):
            raise ValueError(
                'Incorrect number of alpha values, expected %d, got %d.' %
                (len(self), len(alpha)), )

        return np.array(np.sum([a * s for a, s in zip(alpha, self.paulis)], 0))
Пример #2
0
    def __init__(
        self,
        loop_body: BasePass | Sequence[BasePass],
        replace_filter: Callable[[Circuit, Operation], bool] | None = None,
    ) -> None:
        """
        Construct a ForEachBlockPass.

        Args:
            loop_body (BasePass | Sequence[BasePass]): The pass or passes
                to execute on every block.

            replace_filter (Callable[[Circuit, Operation], bool] | None):
                A predicate that determines if the resulting circuit, after
                calling `loop_body` on a block, should replace the original
                operation. Called with the circuit output from `loop_body`
                and the original operation. If this returns true, the
                operation will be replaced with the new circuit.
                Defaults to always replace.

        Raises:
            ValueError: If a Sequence[BasePass] is given, but it is empty.
        """

        if not is_sequence(loop_body) and not isinstance(loop_body, BasePass):
            raise TypeError(
                'Expected Pass or sequence of Passes, got %s.' %
                type(loop_body), )

        if is_sequence(loop_body):
            truth_list = [isinstance(elem, BasePass) for elem in loop_body]
            if not all(truth_list):
                raise TypeError(
                    'Expected Pass or sequence of Passes, got %s.' %
                    type(loop_body[truth_list.index(False)]), )
            if len(loop_body) == 0:
                raise ValueError('Expected at least one pass.')

        self.loop_body = loop_body if is_sequence(loop_body) else [loop_body]
        self.replace_filter = replace_filter or default_replace_filter

        if not callable(self.replace_filter):
            raise TypeError(
                'Expected callable method that maps Circuit and Operations to'
                ' booleans for replace_filter'
                ', got %s.' % type(self.replace_filter), )
Пример #3
0
    def run(self, circuit: Circuit, data: dict[str, Any]) -> None:
        """Perform the pass's operation, see BasePass for more info."""
        if self.condition(circuit, data):
            _logger.debug('True branch taken.')
            if is_sequence(self.on_true):
                for true_pass in self.on_true:
                    true_pass.run(circuit, data)
            else:
                self.on_true.run(circuit, data)

        elif self.on_false is not None:
            _logger.debug('False branch taken.')
            if is_sequence(self.on_false):
                for false_pass in self.on_false:
                    false_pass.run(circuit, data)
            else:
                self.on_false.run(circuit, data)
Пример #4
0
 def run(self, circuit: Circuit, data: dict[str, Any]) -> None:
     """Perform the pass's operation, see BasePass for more info."""
     while self.condition(circuit, data):
         _logger.debug('Loop body executing...')
         if is_sequence(self.loop_body):
             for loop_pass in self.loop_body:
                 loop_pass.run(circuit, data)
         else:
             self.loop_body.run(circuit, data)
Пример #5
0
    def __call__(self, params: Sequence[float] | np.ndarray) -> float:
        """Return the cost value given the input parameters."""

        if not is_sequence(params):
            raise TypeError(
                'Expected sequence for params, got %s.' % type(params), )

        if not all(is_real_number(param) for param in params):
            raise TypeError('Expected sequence of floats for params.', )

        return self.get_cost(params)
Пример #6
0
    def __init__(
        self,
        condition: PassPredicate,
        loop_body: BasePass | Sequence[BasePass],
    ) -> None:
        """
        Construct a DoWhileLoopPass.

        Args:
            condition (PassPredicate): The condition checked.

            loop_body (BasePass | Sequence[BasePass]): The pass or passes
                to execute while `condition` is true.

        Raises:
            ValueError: If a Sequence[BasePass] is given, but it is empty.
        """

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

        if not is_sequence(loop_body) and not isinstance(loop_body, BasePass):
            raise TypeError(
                'Expected Pass or sequence of Passes, got %s.' %
                type(loop_body), )

        if is_sequence(loop_body):
            truth_list = [isinstance(elem, BasePass) for elem in loop_body]
            if not all(truth_list):
                raise TypeError(
                    'Expected Pass or sequence of Passes, got %s.' %
                    type(loop_body[truth_list.index(False)]), )
            if len(loop_body) == 0:
                raise ValueError('Expected at least one pass.')

        self.condition = condition
        self.loop_body = loop_body if is_sequence(loop_body) else [loop_body]
Пример #7
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
Пример #8
0
    def __call__(  # type: ignore
        self,
        params: Sequence[float] | np.ndarray,
    ) -> np.ndarray:
        """Return the vector of residuals given the input parameters."""

        if not is_sequence(params):
            raise TypeError(
                'Expected sequence for params, got %s.' % type(params),
            )

        if not all(is_real_number(param) for param in params):
            raise TypeError(
                'Expected sequence of floats for params.',
            )

        return self.get_residuals(params)
Пример #9
0
    def check_parameters(self, params: Sequence[float] | np.ndarray) -> None:
        """Checks to ensure parameters are valid and match the unitary."""
        if not is_sequence(params):
            raise TypeError(
                'Expected a sequence type for params, got %s.' %
                type(params), )

        if not all(is_numeric(p) for p in params):
            typechecks = [is_numeric(p) for p in params]
            fail_idx = typechecks.index(False)
            raise TypeError(
                'Expected params to be floats, got %s.' %
                type(params[fail_idx]), )

        if len(params) != self.get_num_params():
            raise ValueError(
                'Expected %d params, got %d.' %
                (self.get_num_params(), len(params)), )
Пример #10
0
def invalid_utry_gen(dims: int | Sequence[int]) -> np.ndarray:
    """
    Generate a random invalid unitary.

    dims (int | Sequence[int]): The dimension of the matrix. If multiple
        are given then the dimension is randomly chosen from the ones given.

    Returns:
        (np.ndarray): The randomly generated invalid unitary matrix.
    """
    if isinstance(dims, int):
        return unitary_group.rvs(dims) + np.identity(dims)

    elif is_sequence(dims):
        if not all(isinstance(dim, int) for dim in dims):
            raise TypeError('Expected integer dimension.')

        dim = np.random.choice(dims, 1)[0]
        return unitary_group.rvs(dim) + np.identity(dim)

    else:
        raise TypeError(
            'Expected integer or sequence of integers'
            ' for dimension, got: %s' % type(dims), )
Пример #11
0
 def test_a_seq_complex(self, a_seq_complex: Any) -> None:
     assert is_sequence(a_seq_complex)
     assert len(a_seq_complex) >= 0
     assert all(is_complex(c) for c in a_seq_complex)
Пример #12
0
    def __init__(
        self,
        condition: PassPredicate,
        on_true: BasePass | Sequence[BasePass],
        on_false: BasePass | Sequence[BasePass] | None = None,
    ) -> None:
        """
        Construct a IfThenElsePass.

        Args:
            condition (PassPredicate): The condition checked.

            on_true (BasePass | Sequence[BasePass]): The pass or passes
                to execute if `condition` is true.

            on_false (BasePass | Sequence[BasePass] | None): If specified,
                the pass or passes to execute if `condition` is false.

        Raises:
            ValueError: If a Sequence[BasePass] is given, but it is empty.
        """

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

        if not is_sequence(on_true) and not isinstance(on_true, BasePass):
            raise TypeError(
                'Expected Pass or sequence of Passes, got %s.' % type(on_true),
            )

        if is_sequence(on_true):
            truth_list = [isinstance(elem, BasePass) for elem in on_true]
            if not all(truth_list):
                raise TypeError(
                    'Expected Pass or sequence of Passes, got %s.'
                    % type(on_true[truth_list.index(False)]),
                )
            if len(on_true) == 0:
                raise ValueError('Expected at least one pass for true branch.')

        if on_false is not None:
            if not is_sequence(on_false) and not isinstance(on_false, BasePass):
                raise TypeError(
                    'Expected Pass or sequence of Passes, got %s.'
                    % type(on_false),
                )

            if is_sequence(on_false):
                truth_list = [isinstance(elem, BasePass) for elem in on_false]
                if not all(truth_list):
                    raise TypeError(
                        'Expected Pass or sequence of Passes, got %s.'
                        % type(on_false[truth_list.index(False)]),
                    )
                if len(on_false) == 0:
                    raise ValueError(
                        'Expected at least one pass for false branch.',
                    )

        self.condition = condition
        self.on_true = on_true if is_sequence(on_true) else [on_true]
        self.on_false = on_false if is_sequence(on_false) else [on_false]
Пример #13
0
    def __init__(
        self,
        circuit: Circuit,
        start: CircuitPointLike = CircuitPoint(0, 0),
        end: CircuitPointLike | None = None,
        qudits_or_region: CircuitRegionLike | Sequence[int] | None = None,
        exclude: bool = False,
        reverse: bool = False,
        and_cycles: bool = False,
    ) -> None:
        """
        Construct a CircuitIterator.

        Args:
            circuit (Circuit): The circuit to iterate through.

            start (CircuitPointLike): Only iterate through points greater
                than or equal to `start`. Defaults to start at the beginning
                of the circuit. (Default: (0, 0))

            end (CircuitPointLike | None): Only iterate through points
                less than or equal to this. If left as None, iterates
                until the end of the circuit. (Default: None)

            qudits_or_region (CircuitRegionLike | Sequence[int] | None):
                Determines the way the circuit is iterated. If a region
                is given, then iterate through operations in the region.
                If a sequence of qudit indices is given, then only iterate
                the operations touching those qudits. If left as None,
                then iterate through the entire circuit in simulation order.
                (Default: None)

            exclude (bool): If iterating through a region or only some
                qudits and `exclude` is true, then do not yield operations
                that are only partially in the region or on the desired
                qudits. This may result in a sequence of operations that
                does not occur in simulation order in the circuit.
                (Default: False)

            reverse (bool): Reverse the ordering. If true, then end acts
                as start and vice versa. (Default: False)

            and_cycles (bool): If true, in addition to the operation,
                return the cycle index where it was found. (Default: False)
        """
        if not CircuitPoint.is_point(start):
            raise TypeError(f'Expected point for start, got {type(start)}.')

        if end is not None and not CircuitPoint.is_point(end):
            raise TypeError(f'Expected point for end, got {type(end)}.')

        if end is None:
            end = CircuitPoint(
                circuit.get_num_cycles() - 1,
                circuit.get_size() - 1,
            )

        self.circuit = circuit
        self.start = CircuitPoint(*start)
        self.end = CircuitPoint(*end)
        self.exclude = exclude
        self.reverse = reverse
        self.and_cycles = and_cycles

        # Set mode of iteration:
        if qudits_or_region is None:
            # iterate through the entire circuit normally
            self.qudits = list(range(self.circuit.get_size()))
            self.region = CircuitRegion({
                qudit: (0, self.circuit.get_num_cycles())
                for qudit in self.qudits
            })

        elif CircuitRegion.is_region(qudits_or_region):  # TODO: Typeguard
            # iterate through the region in the circuit
            self.qudits = list(qudits_or_region.keys())  # type: ignore
            self.region = CircuitRegion(qudits_or_region)  # type: ignore

        elif is_sequence(qudits_or_region):
            # iterate through the circuit but only on the specified qudits
            if not all(is_integer(qudit) for qudit in qudits_or_region):
                raise TypeError('Expected region or sequence of indices.')

            if not all(0 <= qudit < self.circuit.get_size()
                       for qudit in qudits_or_region):
                raise ValueError('Invalid sequence of qudit indices.')

            self.qudits = list(qudits_or_region)
            self.region = CircuitRegion({
                qudit: (0, self.circuit.get_num_cycles())
                for qudit in self.qudits
            })

        self.max_qudit = max(self.qudits)
        self.min_qudit = min(self.qudits)
        self.min_cycle = self.region.min_cycle
        self.max_cycle = self.region.max_cycle

        if start < (self.min_cycle, self.min_qudit):
            start = CircuitPoint(self.min_cycle, self.min_qudit)

        if end > (self.max_cycle, self.max_qudit):
            end = CircuitPoint(self.max_cycle, self.max_qudit)

        assert isinstance(start, CircuitPoint)  # TODO: Typeguard
        assert isinstance(end, CircuitPoint)  # TODO: Typeguard

        # Pointer into the circuit structure
        self.cycle = start.cycle if not self.reverse else end.cycle
        self.qudit = start.qudit if not self.reverse else end.qudit

        # Used to track changes to circuit structure
        self.num_ops = self.circuit.get_num_operations()
        self.num_cycles = self.circuit.get_num_cycles()
        self.num_qudits = self.circuit.get_size()

        # Ensure operations are only returned once
        self.qudits_to_skip: set[int] = set()
Пример #14
0
 def test_not_a_complex(self, not_a_complex: Any) -> None:
     assert is_sequence(not_a_complex) or not is_complex(not_a_complex)
Пример #15
0
 def test_not_a_seq_bool(self, not_a_seq_bool: Any) -> None:
     assert (not is_sequence(not_a_seq_bool)
             or isinstance(not_a_seq_bool, str)
             or any(not isinstance(b, (bool, np.bool_))
                    for b in not_a_seq_bool))
Пример #16
0
 def test_a_seq_str(self, a_seq_str: Any) -> None:
     assert is_sequence(a_seq_str)
     assert len(a_seq_str) >= 0
     assert all(isinstance(s, str) for s in a_seq_str)
Пример #17
0
 def test_not_a_seq_complex(self, not_a_seq_complex: Any) -> None:
     assert (not is_sequence(not_a_seq_complex)
             or isinstance(not_a_seq_complex, str)
             or any(not is_complex(c) for c in not_a_seq_complex))
Пример #18
0
 def test_a_seq_bool(self, a_seq_bool: Any) -> None:
     assert is_sequence(a_seq_bool)
     assert len(a_seq_bool) >= 0
     assert all(isinstance(b, (bool, np.bool_)) for b in a_seq_bool)
Пример #19
0
 def test_not_a_seq_str(self, not_a_seq_str: Any) -> None:
     assert (not is_sequence(not_a_seq_str)
             or isinstance(not_a_seq_str, str)
             or any(not isinstance(s, str) for s in not_a_seq_str))
Пример #20
0
 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))
Пример #21
0
 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)
Пример #22
0
 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))
Пример #23
0
 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)