def replace_var(self, old_variable, new_variable): """ Replaces a variable with another. """ return BaseOperator( replace_var(self._left, old_variable, new_variable), replace_var(self._right, old_variable, new_variable))
def test_replace_var_delta(): d1 = DeltaFunction('x', 'y') d1 = replace_var(d1, 'y', 'z') d2 = DeltaFunction('x', 'z') assert d1 == d2 with pytest.raises(ValueError): replace_var(d1, 'z', 'x')
def replace_var(self, old_variable, new_variable): """ Replaces a variable with another. """ new_op = Operator() for base_op, scalar in self._terms.items(): new_base_op = replace_var(base_op, old_variable, new_variable) new_scalar = replace_var(scalar, old_variable, new_variable) new_op._terms[new_base_op] = new_scalar return new_op
def replace_var(self, old_variable, new_variable): """ Replaces a variable with another. """ new_state = State() for base_state, scalar in self._terms.items(): new_base_state = replace_var(base_state, old_variable, new_variable) new_scalar = replace_var(scalar, old_variable, new_variable) new_state._terms[new_base_state] = new_scalar return new_state
def ultimate_example(indices, no_output=False): """Example for computing one of the POVMs (eq. (82) - (87) of https://arxiv.org/abs/1903.09778)""" def convert_scalars(scalar): visibility = 0.9 scalar = integrate(scalar) if is_number(scalar): return scalar for sequenced_class in [ProductOfScalars, SumOfScalars]: if isinstance(scalar, sequenced_class): return simplify( sequenced_class([convert_scalars(s) for s in scalar])) if isinstance(scalar, InnerProductFunction): if set(scalar._func_names) == set(['phi', 'psi']): return visibility raise RuntimeError(f"unknown scalar {scalar} of type {type(scalar)}") assert len(indices) == 2 u = construct_beam_splitter() p = construct_projector(*indices) m = u.dagger() * p * replace_var(u) m = simplify(m) if not no_output: # print(m) print(m.to_numpy_matrix(convert_scalars))
def replace_var(self, old_variable, new_variable): """ Replaces a variable with another. """ new_fock_op_product = FockOpProduct() for fock_op, count in self._fock_ops.items(): new_fock_op_product._fock_ops[replace_var(fock_op, old_variable, new_variable)] = count return new_fock_op_product
def test_fock_base_op(): bsaw = BaseFockState([FockOp("a", "w")]) bsav = BaseFockState([FockOp("a", "v")]) bopaw = BaseOperator(bsaw, bsaw) bopav = BaseOperator(bsav, bsav) assert get_variables(bopaw) == set(["w"]) assert get_variables(bopav) == set(["v"]) new = replace_var(bopaw, "w", "v") assert bopav == new
def test_operator_variables(): bsaw = BaseFockState([FockOp("a", "w")]) bsav = BaseFockState([FockOp("a", "v")]) opaw = BaseOperator(bsaw, bsaw).to_operator() opav = BaseOperator(bsav, bsav).to_operator() assert get_variables(opaw) == set(["w"]) assert get_variables(opav) == set(["v"]) new = replace_var(opaw, "w", "v") assert opav == new
def test_sum_vars(): a = SingleVarFunctionScalar('a', 'x') b = SingleVarFunctionScalar('b', 'x') c = SingleVarFunctionScalar('c', 'y') sm = a + b + c assert get_variables(sm) == set(['x', 'y']) sm = replace_var(sm, 'y', 'x') assert get_variables(sm) == set(['x']) assert not has_variable(sm, 'y')
def construct_beam_splitter(): """Construct the beam splitter operation (eq. (40)-(41) in https://arxiv.org/abs/1903.09778)""" fock_states = list(get_fock_states()) for i, state in enumerate(fock_states): for old, new in zip(['w1', 'w2'], ['b1', 'b2']): state = replace_var(state, old, new) fock_states[i] = state qubit_states = [ BaseQubitState(b).to_state() for b in ["00", "01", "10", "11"] ] beam_splitter = sum( (outer_product(fock_state, qubit_state) for fock_state, qubit_state in zip(fock_states, qubit_states)), Operator()) return beam_splitter.simplify()
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
def _evaluate_delta_function(integration_scalar): integrand = integration_scalar._scalar variable = integration_scalar._variable # Find the delta functions containing this variable deltas = [(i, d) for (i, d) in enumerate(integrand._factors) if isinstance(d, DeltaFunction) and variable in d._vars] if len(deltas) == 0: return integration_scalar # Replace variables with the variable to the other variable in the delta function i, delta = deltas[0] # Get the other variable in the delta function try: other_var = next(v for v in delta._vars if v != variable) except StopIteration: # TODO This should not happen anymore raise RuntimeError( f"Encountered delta function with the same variable: {delta}") # Replace the delta function with 1 (recall that replace_var creates a copy) integrand._factors[i] = 1 integrand = replace_var(integrand, old_variable=variable, new_variable=other_var) return integrand
def replace_var(self, old_variable, new_variable): """ Replaces a variable with another. """ return self.__class__( replace_var(self._fock_op_product, old_variable, new_variable))
def replace_var(self, old_variable, new_variable): new_terms = [] for s in self: new_terms.append(replace_var(s, old_variable, new_variable)) return self.__class__(new_terms)