Exemplo n.º 1
0
    def simplify(self, full=True):
        new_scalar = 1
        for factor in self:
            if is_zero(factor):
                return 0
            if not is_one(factor):
                new_scalar *= simplify(factor)
        new_scalar = expand(new_scalar)
        if isinstance(new_scalar, SumOfScalars):
            return simplify(new_scalar)

        if _is_sequenced_scalar(new_scalar):
            if len(new_scalar) == 0:
                return 0
            if len(new_scalar) == 1:
                return simplify(new_scalar[0])

        if isinstance(new_scalar, ProductOfScalars):
            if any(isinstance(s, ProductOfScalars) for s in new_scalar):
                raise RuntimeError("factors of product should not be products")
            if full:
                changed = True
                while changed:
                    changed = new_scalar._combine_factors()
        return new_scalar
Exemplo n.º 2
0
    def simplify(self, full=True):
        new_scalar = 0
        expanded = self.expand()

        if not isinstance(expanded, SumOfScalars):
            return simplify(expanded)
        if is_number(expanded):
            return expanded
        for term in expanded:
            if not is_zero(term):
                new_scalar += simplify(term)

        if _is_sequenced_scalar(new_scalar):
            if len(new_scalar) == 0:
                new_scalar = 0
            if len(new_scalar) == 1:
                new_scalar = simplify(new_scalar[0])

        if isinstance(new_scalar, SumOfScalars):
            if any(isinstance(s, SumOfScalars) for s in new_scalar):
                raise RuntimeError("terms of sum should not be sum after expand")
            if full:
                changed = True
                while changed:
                    changed = new_scalar._combine_terms()
        return new_scalar
Exemplo n.º 3
0
    def _mul_state(self, state):
        # compute output state for each term of the operator
        new_state = State([])
        for base_op, scalar in self._terms.items():
            if is_zero(scalar):
                continue
            new_state += scalar * (base_op * state)

        return new_state
Exemplo n.º 4
0
 def is_zero(self):
     for f in self._factors:
         if isinstance(f, float):
             if math.isclose(f, 0, abs_tol=1e-16):
                 return True
         else:
             if is_zero(f):
                 return True
     return False
Exemplo n.º 5
0
    def __add__(self, other):
        # Check if one is zero
        if is_zero(other):
            return copy(self)
        if is_zero(self):
            return copy(other)

        if not is_scalar(other):
            return NotImplemented
        if isinstance(other, SumOfScalars):
            return other + self
        # Check if multiples
        self_multiple, self_scalar = _get_multiple_of_scalar(self)
        other_multiple, other_scalar = _get_multiple_of_scalar(other)
        if self_scalar == other_scalar:
            return copy(self_scalar) * (self_multiple + other_multiple)

        return SumOfScalars([self, other])
Exemplo n.º 6
0
def test_iszero_prod():
    a = SingleVarFunctionScalar('a', 'x')
    b = SingleVarFunctionScalar('b', 'x')

    prod = a * b
    prod[1] = 1e-17
    prod = simplify(prod)

    assert prod == 0
    assert is_zero(prod)
Exemplo n.º 7
0
 def __mul__(self, other):
     if is_zero(other):
         return 0
     if is_one(other):
         return copy(self)
     if not is_scalar(other):
         return NotImplemented
     if isinstance(other, ProductOfScalars):
         return other * self
     return ProductOfScalars([self, other])
Exemplo n.º 8
0
    def __add__(self, other):
        # Check if one is zero
        if is_zero(other):
            return copy(self)
        if is_zero(self):
            return copy(other)

        if not is_scalar(other):
            return NotImplemented
        if is_number(other):
            return SumOfScalars([self._terms[0] + other] + self._terms[1:])
        if isinstance(other, SumOfScalars):
            new_scalar = copy(self)
            for term in other:
                new_scalar += term
            return new_scalar
        # Check if the addition between other and any term can be simplified
        for i, term in enumerate(self._terms):
            if i == 0:
                continue
            sm = term + other
            if not isinstance(sm, SumOfScalars):
                return SumOfScalars([sm] + self._terms[:i] + self._terms[i + 1:])
        return SumOfScalars(self._terms + [other])
Exemplo n.º 9
0
    def inner_product(self, other, first_replace_var=True):
        """
        Takes the inner product with another :class:`~.State`.

        Parameters
        ----------
        other : :class:`.State`
            The right hand side of the inner product.
        first_replace_var (optional) : bool
            Whether to replace all varibles of the right hand side with
            new ones (only done for `SingleVarFunctionScalar`).
            This can be useful when the two states are actually integrals
            over the variables and should therefore be different.

        Returns
        -------
        :class`~.scalar.Scalar`
            The inner product
        """
        if not isinstance(other, self.__class__):
            raise NotImplementedError(
                f"inner product is not implemented for {type(other)}")
        if not self._compatible(other):
            raise ValueError(
                f"other ({other}) is not compatible with self ({self})")
        # NOTE if BaseState are assumed to be orthogonal be don't need to do the
        # product of base states.
        if first_replace_var:
            other = replace_var(other)
        inner = 0
        for self_base_state, self_scalar in self._terms.items():
            for other_base_state, other_scalar in other._terms.items():
                factors = [
                    self_scalar.conjugate(),
                    other_scalar,
                    self_base_state.inner_product(other_base_state),
                ]
                if any(is_zero(factor) for factor in factors):
                    continue
                inner += (self_scalar.conjugate() * other_scalar
                          ) * self_base_state.inner_product(other_base_state)

        return inner
Exemplo n.º 10
0
    def _mul_operator(self, operator):
        new_op = Operator()
        for self_base_op, self_scalar in self._terms.items():
            for other_base_op, other_scalar in operator._terms.items():
                new_base_op = BaseOperator(self_base_op._left,
                                           other_base_op._right)
                new_scalar = self_base_op._right.inner_product(
                    other_base_op._left) * self_scalar * other_scalar

                # Integrate out variables which are not in base operator
                # TODO, should this be optional?
                scalar_variables = get_variables(new_scalar) - get_variables(
                    new_base_op)
                new_scalar = integrate(new_scalar, scalar_variables)

                if is_zero(new_scalar):
                    continue
                new_op._terms[new_base_op] += new_scalar

        return new_op
Exemplo n.º 11
0
 def is_zero(self):
     return all(is_zero(s) for s in self)