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
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
def test_inner_product(): aw = FockOp('a', 'w') av = FockOp('a', 'v') cw = FockOp('c', 'w') saw = BaseFockState([aw]) sav = BaseFockState([av]) scw = BaseFockState([cw]) assert simplify(saw.inner_product(sav)) == DeltaFunction('w', 'v') assert simplify(saw.inner_product(scw)) == 0
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 test_setitem(): a = SingleVarFunctionScalar('a', 'x') sm = 2 + a sm[1] = 1 print(sm) sm = simplify(sm) assert sm == 3
def simplify(self): """Tries to simplify the state.""" new_state = State() for base_state, scalar in self._terms.items(): new_state._terms[base_state] = simplify(scalar) new_state._prune_zero_terms() return new_state
def test_simplify_operator(): bs0 = BaseQubitState("0") bs1 = BaseQubitState("1") op = Operator([BaseOperator(bs0, bs0)]) op._terms[BaseOperator(bs1, bs1)] = 0 assert len(op) == 2 op = simplify(op) assert len(op) == 1
def test_simplify(): prod = ProductOfScalars() prod._factors = [2, 3, 5] bs = BaseQubitState('0') s = State([bs], scalars=[prod]) assert s.get_scalar(bs) != 30 s = simplify(s) assert s.get_scalar(bs) == 30
def test_combine_factors(): a = SingleVarFunctionScalar('a', 'x') b = SingleVarFunctionScalar('b', 'x') c = SingleVarFunctionScalar('c', 'x') prod = a * b * c prod[0] = 2 prod[2] = 5 prod = simplify(prod) assert prod == 10 * b
def test_variable(): a = Variable('a') b = Variable('b') expr = a * b + b * a print(expr) expr = simplify(expr) assert expr == 2 * a * b
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)
def example_states(no_output=False): """Example showing how the states can be constructed""" s0, sphi, spsi, sphipsi = get_fock_states() if not no_output: print(f"State is: {sphi}\n") inner = sphi.inner_product(sphi) if not no_output: print(f"inner product is: {inner}\n") simplify(inner) if not no_output: print(f"after simplify: {simplify(inner)}\n") inner = integrate(inner) if not no_output: print(f"after integrate: {inner}\n") return inner = simplify(sphipsi.inner_product(sphipsi)) if not no_output: print(inner) print(integrate(inner))
def simplify(self): """ Tries to simplify the operator, returning a new one. """ new_op = Operator() for base_op, scalar in self._terms.items(): new_op._terms[base_op] = simplify(scalar) new_op._prune_zero_terms() return new_op
def test_expand_variable(): a = Variable('a') b = Variable('b') c = Variable('c') d = Variable('d') expr = (a + b) * (c + d) expr = expand(expr) assert len(expr) == 9 expr = simplify(expr) assert len(expr) == 4 assert isinstance(expr, SumOfScalars)
def test_inner_product_multi_photon(): cw1 = FockOp('c', 'w1') cw2 = FockOp('c', 'w2') cw3 = FockOp('c', 'w3') state = BaseFockState([cw1, cw2, cw3]).to_state() print(state) print() inp = simplify(state.inner_product(state)) print(inp) assert len(inp) == 6 print(inp[0]) assert len(inp[0]) == 3
def test_expand(): a = SingleVarFunctionScalar('a', 'x') b = SingleVarFunctionScalar('b', 'x') c = SingleVarFunctionScalar('c', 'x') d = SingleVarFunctionScalar('d', 'x') expr = (a + b) * (c + d) expr = simplify(expr.expand()) print(expr) assert isinstance(expr, SumOfScalars) assert len(expr) == 4 print(expr[0]) assert len(expr[0]) == 2
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)}")
def integrate(scalar, variable=None): """ Integrates a scalar over a given variable or variables. Parameters ---------- scalar : :class:`~.scalar.Scalar` The scalar to integrate. variable : None or str or set of str The variable(s) to integrate over. Can be: * `None`: Then all variables in the scalar are integrated out. * `str`: Then a single variable is integrated out. * `set` of `str`: Then all the variables in the set are integrated out. Returns ------- :class:`~.scalar.Scalar` The output of the integration. """ # TODO needed? scalar = simplify(scalar) if variable is None: return integrate(scalar, get_variables(scalar)) if isinstance(variable, set): new_scalar = scalar for v in variable: new_scalar = integrate(new_scalar, v) return new_scalar assert_str(variable) if isinstance(scalar, SumOfScalars): new_scalar = sum(integrate(s, variable) for s in scalar._terms) # elif isinstance(scalar, ProductOfScalars): elif isinstance(scalar, Scalar): if isinstance(scalar, ProductOfScalars): factors = scalar._factors else: factors = [scalar] # Split factors based on if they contain the integration variable or not var_factors = [] other_factors = [] for factor in factors: if isinstance(factor, Scalar) and has_variable(factor, variable): var_factors.append(factor) else: other_factors.append(factor) if len(var_factors) > 0: integration_part = [ _Integration(ProductOfScalars(var_factors), variable) ] else: integration_part = [] new_scalar = ProductOfScalars(other_factors + integration_part) elif is_number(scalar): new_scalar = scalar else: raise NotImplementedError( f"integrate not implemented for type {type(scalar)}") return simplify(new_scalar)