def __getitem__(self, indices, **kw_args): if is_sequence(indices): # Special case needed because M[*my_tuple] is a syntax error. return Indexed(self, *indices, **kw_args) else: return Indexed(self, indices, **kw_args)
def test_Indexed_func_args(): i, j = symbols('i j', integer=True) a = symbols('a') A = Indexed(a, i, j) assert A == A.func(*A.args)
def test_Lambda(): e = Lambda(x, x**2) assert e(4) == 16 assert e(x) == x**2 assert e(y) == y**2 assert Lambda((), 42)() == 42 assert unchanged(Lambda, (), 42) assert Lambda((), 42) != Lambda((), 43) assert Lambda((), f(x))() == f(x) assert Lambda((), 42).nargs == FiniteSet(0) assert unchanged(Lambda, (x,), x**2) assert Lambda(x, x**2) == Lambda((x,), x**2) assert Lambda(x, x**2) != Lambda(x, x**2 + 1) assert Lambda((x, y), x**y) != Lambda((y, x), y**x) assert Lambda((x, y), x**y) != Lambda((x, y), y**x) assert Lambda((x, y), x**y)(x, y) == x**y assert Lambda((x, y), x**y)(3, 3) == 3**3 assert Lambda((x, y), x**y)(x, 3) == x**3 assert Lambda((x, y), x**y)(3, y) == 3**y assert Lambda(x, f(x))(x) == f(x) assert Lambda(x, x**2)(e(x)) == x**4 assert e(e(x)) == x**4 x1, x2 = (Indexed('x', i) for i in (1, 2)) assert Lambda((x1, x2), x1 + x2)(x, y) == x + y assert Lambda((x, y), x + y).nargs == FiniteSet(2) p = x, y, z, t assert Lambda(p, t*(x + y + z))(*p) == t * (x + y + z) eq = Lambda(x, 2*x) + Lambda(y, 2*y) assert eq != 2*Lambda(x, 2*x) assert eq.as_dummy() == 2*Lambda(x, 2*x).as_dummy() assert Lambda(x, 2*x) not in [ Lambda(x, x) ] raises(BadSignatureError, lambda: Lambda(1, x)) assert Lambda(x, 1)(1) is S.One raises(BadSignatureError, lambda: Lambda((x, x), x + 2)) raises(BadSignatureError, lambda: Lambda(((x, x), y), x)) raises(BadSignatureError, lambda: Lambda(((y, x), x), x)) raises(BadSignatureError, lambda: Lambda(((y, 1), 2), x)) with warns_deprecated_sympy(): assert Lambda([x, y], x+y) == Lambda((x, y), x+y) flam = Lambda( ((x, y),) , x + y) assert flam((2, 3)) == 5 flam = Lambda( ((x, y), z) , x + y + z) assert flam((2, 3), 1) == 6 flam = Lambda( (((x,y),z),) , x+y+z) assert flam( ((2,3),1) ) == 6 raises(BadArgumentsError, lambda: flam(1, 2, 3)) flam = Lambda( (x,), (x, x)) assert flam(1,) == (1, 1) assert flam((1,)) == ((1,), (1,)) flam = Lambda( ((x,),) , (x, x)) raises(BadArgumentsError, lambda: flam(1)) assert flam((1,)) == (1, 1) # Previously TypeError was raised so this is potentially needed for # backwards compatibility. assert issubclass(BadSignatureError, TypeError) assert issubclass(BadArgumentsError, TypeError) # These are tested to see they don't raise: hash(Lambda(x, 2*x)) hash(Lambda(x, x)) # IdentityFunction subclass
def test_Idx_limits(): i = symbols("i", cls=Idx) r = Indexed("r", i) assert SeqFormula(r, (i, 0, 5))[:] == [r.subs(i, j) for j in range(6)] assert SeqPer((1, 2), (i, 0, 5))[:] == [1, 2, 1, 2, 1, 2]
def test_not_interable(): i, j = symbols('i j', integer=True) A = Indexed('A', i, i + j) assert not iterable(A)
def test_complex_indices(): i, j = symbols('i j', integer=True) A = Indexed('A', i, i + j) assert A.rank == 2 assert A.indices == (i, i + j)
def pdf(self): sym = [Indexed(self.symbol, i) for i in range(self.component_count)] return self.distribution(*sym)
def _eliminate_inter_stencil_redundancies(self, cluster, **kwargs): """ Search for redundancies across the expressions and expose them to the later stages of the optimisation pipeline by introducing new temporaries of suitable rank. Two type of redundancies are sought: * Time-invariants, and * Across different space points Examples ======== Let ``t`` be the time dimension, ``x, y, z`` the space dimensions. Then: 1) temp = (a[x,y,z]+b[x,y,z])*c[t,x,y,z] >>> ti[x,y,z] = a[x,y,z] + b[x,y,z] temp = ti[x,y,z]*c[t,x,y,z] 2) temp1 = 2.0*a[x,y,z]*b[x,y,z] temp2 = 3.0*a[x,y,z+1]*b[x,y,z+1] >>> ti[x,y,z] = a[x,y,z]*b[x,y,z] temp1 = 2.0*ti[x,y,z] temp2 = 3.0*ti[x,y,z+1] """ if cluster.is_sparse: return cluster # For more information about "aliases", refer to collect_aliases.__doc__ mapper, aliases = collect_aliases(cluster.exprs) # Redundancies will be stored in space-varying temporaries g = cluster.trace indices = g.space_indices shape = g.space_shape # Template for captured redundancies name = self.conventions['redundancy'] + "%d" template = lambda i: TensorFunction( name=name % i, shape=shape, dimensions=indices).indexed # Find the candidate expressions processed = [] candidates = OrderedDict() for k, v in g.items(): # Cost check (to keep the memory footprint under control) naliases = len(mapper.get(v.rhs, [])) cost = estimate_cost(v, True) * naliases if cost >= self.thresholds[ 'min-cost-time-hoist'] and g.time_invariant(v): candidates[v.rhs] = k elif cost >= self.thresholds[ 'min-cost-space-hoist'] and naliases > 1: candidates[v.rhs] = k else: processed.append(Eq(k, v.rhs)) # Create temporaries capturing redundant computation found = [] rules = OrderedDict() stencils = [] for c, (origin, alias) in enumerate(aliases.items()): temporary = Indexed(template(c), *indices) found.append(Eq(temporary, origin)) # Track the stencil of each TensorFunction introduced stencils.append(alias.anti_stencil.anti(cluster.stencil)) for aliased, distance in alias.with_distance: coordinates = [ sum([i, j]) for i, j in distance.items() if i in indices ] rules[candidates[aliased]] = Indexed(template(c), *tuple(coordinates)) # Create the alias clusters alias_clusters = clusterize(found, stencils) alias_clusters = sorted(alias_clusters, key=lambda i: i.is_dense) # Switch temporaries in the expression trees processed = [e.xreplace(rules) for e in processed] return alias_clusters + [cluster.rebuild(processed)]
def A(i): if isinstance(i, IdxSym): return OperatorSymbol(StrLabel(Indexed('A', i)), hs=0) else: return OperatorSymbol("A_%s" % i, hs=0)
def __getitem__(self, key): if isinstance(self.pspace, JointPSpace): if (self.pspace.component_count <= key) == True: raise ValueError("Index keys for %s can only up to %s." % (self.name, self.pspace.component_count - 1)) return Indexed(self, key)
def probability(self, condition, given_condition=None, evaluate=True, **kwargs): """ Handles probability queries for discrete Markov chains. Parameters ========== condition: Relational given_condition: Relational/And Returns ======= Probability If the transition probabilities are not available Expr If the transition probabilities is MatrixSymbol or Matrix Note ==== Any information passed at the time of query overrides any information passed at the time of object creation like transition probabilities, state space. Pass the transition matrix using TransitionMatrixOf and state space using StochasticStateSpaceOf in given_condition using & or And. """ check, trans_probs, state_space, given_condition = \ self._preprocess(given_condition, evaluate) if check: return Probability(condition, given_condition) if isinstance(condition, Eq) and \ isinstance(given_condition, Eq) and \ len(given_condition.atoms(RandomSymbol)) == 1: # handles simple queries like P(Eq(X[i], dest_state), Eq(X[i], init_state)) lhsc, rhsc = condition.lhs, condition.rhs lhsg, rhsg = given_condition.lhs, given_condition.rhs if not isinstance(lhsc, RandomIndexedSymbol): lhsc, rhsc = (rhsc, lhsc) if not isinstance(lhsg, RandomIndexedSymbol): lhsg, rhsg = (rhsg, lhsg) keyc, statec, keyg, stateg = (lhsc.key, rhsc, lhsg.key, rhsg) if Lt(stateg, trans_probs.shape[0]) == False or Lt( statec, trans_probs.shape[1]) == False: raise IndexError( "No information is available for (%s, %s) in " "transition probabilities of shape, (%s, %s). " "State space is zero indexed." % (stateg, statec, trans_probs.shape[0], trans_probs.shape[1])) if keyc < keyg: raise ValueError( "Incorrect given condition is given, probability " "of past state cannot be computed from future state.") nsteptp = trans_probs**(keyc - keyg) if hasattr(nsteptp, "__getitem__"): return nsteptp.__getitem__((stateg, statec)) return Indexed(nsteptp, stateg, statec) info = TransitionMatrixOf(self, trans_probs) & StochasticStateSpaceOf( self, state_space) new_gc = given_condition & info if isinstance(condition, And): # handle queries like, # P(Eq(X[i+k], s1) & Eq(X[i+m], s2) . . . & Eq(X[i], sn), Eq(P(Eq(X[i], si)), prob)) conds = condition.args idx2state = dict() for cond in conds: idx, state = (cond.lhs, cond.rhs) if isinstance(cond.lhs, RandomIndexedSymbol) else \ (cond.rhs, cond.lhs) idx2state[idx] = cond if idx2state.get(idx, None) is None else \ idx2state[idx] & cond if any( len(Intersection(idx2state[idx].as_set(), state_space)) != 1 for idx in idx2state): return S.Zero # a RandomIndexedSymbol cannot go to different states simultaneously i, result = -1, 1 conds = And.fromiter( Intersection(idx2state[idx].as_set(), state_space).as_relational(idx) for idx in idx2state) if not isinstance(conds, And): return self.probability(conds, new_gc) conds = conds.args while i > -len(conds): result *= self.probability(conds[i], conds[i - 1] & info) i -= 1 if isinstance(given_condition, (TransitionMatrixOf, StochasticStateSpaceOf)): return result * Probability(conds[i]) if isinstance(given_condition, And): idx_sym = conds[i].atoms(RandomIndexedSymbol) prob, count = S(0), 0 for gc in given_condition.args: if gc.atoms(RandomIndexedSymbol) == idx_sym: prob += gc.rhs if isinstance(gc.lhs, Probability) else gc.lhs count += 1 if isinstance(state_space, FiniteSet) and \ count == len(state_space) - 1: given_condition = Eq(Probability(conds[i]), S(1) - prob) if isinstance(given_condition, Eq): if not isinstance(given_condition.lhs, Probability) or \ given_condition.lhs.args[0] != conds[i]: raise ValueError("Probability for %s needed", conds[i]) return result * given_condition.rhs if isinstance(condition, Or): conds, prob_sum = condition.args, S(0) idx2state = dict() for cond in conds: idx, state = (cond.lhs, cond.rhs) if isinstance(cond.lhs, RandomIndexedSymbol) else \ (cond.rhs, cond.lhs) idx2state[idx] = cond if idx2state.get(idx, None) is None else \ idx2state[idx] | cond conds = Or.fromiter( Intersection(idx2state[idx].as_set(), state_space).as_relational(idx) for idx in idx2state) if not isinstance(conds, Or): return self.probability(conds, new_gc) return sum([self.probability(cond, new_gc) for cond in conds.args]) if isinstance(condition, Ne): prob = self.probability(Not(condition), new_gc) return S(1) - prob raise NotImplementedError( "Mechanism for handling (%s, %s) queries hasn't been " "implemented yet." % (condition, given_condition))
def __getitem__(self, key): from sympy.stats.joint_rv import JointPSpace if isinstance(self.pspace, JointPSpace): return Indexed(self, key)
def test_MarginalDistribution(): a1, p1, p2 = symbols('a1 p1 p2', positive=True) C = Multinomial('C', 2, p1, p2) B = MultivariateBeta('B', a1, C[0]) MGR = MarginalDistribution(B, (C[0], )) mgrc = Mul( Symbol('B'), Piecewise( ExprCondPair( Mul( Integer(2), Pow(Symbol('p1', positive=True), Indexed(IndexedBase(Symbol('C')), Integer(0))), Pow(Symbol('p2', positive=True), Indexed(IndexedBase(Symbol('C')), Integer(1))), Pow( factorial(Indexed(IndexedBase(Symbol('C')), Integer(0))), Integer(-1)), Pow( factorial(Indexed(IndexedBase(Symbol('C')), Integer(1))), Integer(-1))), Eq( Add(Indexed(IndexedBase(Symbol('C')), Integer(0)), Indexed(IndexedBase(Symbol('C')), Integer(1))), Integer(2))), ExprCondPair(Integer(0), True)), Pow(gamma(Symbol('a1', positive=True)), Integer(-1)), gamma( Add(Symbol('a1', positive=True), Indexed(IndexedBase(Symbol('C')), Integer(0)))), Pow(gamma(Indexed(IndexedBase(Symbol('C')), Integer(0))), Integer(-1)), Pow(Indexed(IndexedBase(Symbol('B')), Integer(0)), Add(Symbol('a1', positive=True), Integer(-1))), Pow(Indexed(IndexedBase(Symbol('B')), Integer(1)), Add(Indexed(IndexedBase(Symbol('C')), Integer(0)), Integer(-1)))) assert MGR(C) == mgrc
def Psi(*args): return KetSymbol(StrLabel(Indexed(IndexedBase('Psi'), *args)), hs=0)
def probability(self, condition, given_condition=None, evaluate=True, **kwargs): """ Handles probability queries for discrete Markov chains. Parameters ========== condition: Relational given_condition: Relational/And Returns ======= Probability If the transition probabilities are not available Expr If the transition probabilities is MatrixSymbol or Matrix Note ==== Any information passed at the time of query overrides any information passed at the time of object creation like transition probabilities, state space. Pass the transition matrix using TransitionMatrixOf and state space using StochasticStateSpaceOf in given_condition using & or And. """ check, trans_probs, state_space, given_condition = \ self._preprocess(given_condition, evaluate) if check: return Probability(condition, given_condition) if isinstance(condition, Eq) and \ isinstance(given_condition, Eq) and \ len(given_condition.atoms(RandomSymbol)) == 1: # handles simple queries like P(Eq(X[i], dest_state), Eq(X[i], init_state)) lhsc, rhsc = condition.lhs, condition.rhs lhsg, rhsg = given_condition.lhs, given_condition.rhs if not isinstance(lhsc, RandomIndexedSymbol): lhsc, rhsc = (rhsc, lhsc) if not isinstance(lhsg, RandomIndexedSymbol): lhsg, rhsg = (rhsg, lhsg) keyc, statec, keyg, stateg = (lhsc.key, rhsc, lhsg.key, rhsg) if Lt(stateg, trans_probs.shape[0]) == False or Lt(statec, trans_probs.shape[1]) == False: raise IndexError("No information is avaliable for (%s, %s) in " "transition probabilities of shape, (%s, %s). " "State space is zero indexed." %(stateg, statec, trans_probs.shape[0], trans_probs.shape[1])) if keyc < keyg: raise ValueError("Incorrect given condition is given, probability " "of past state cannot be computed from future state.") nsteptp = trans_probs**(keyc - keyg) if hasattr(nsteptp, "__getitem__"): return nsteptp.__getitem__((stateg, statec)) return Indexed(nsteptp, stateg, statec) if isinstance(condition, And): # handle queries like, # P(Eq(X[i+k], s1) & Eq(X[i+m], s2) . . . & Eq(X[i], sn), Eq(P(X[i]), prob)) conds = condition.args i, result = -1, 1 while i > -len(conds): result *= self.probability(conds[i], conds[i-1] & \ TransitionMatrixOf(self, trans_probs) & \ StochasticStateSpaceOf(self, state_space)) i -= 1 if isinstance(given_condition, (TransitionMatrixOf, StochasticStateSpaceOf)): return result * Probability(conds[i]) if isinstance(given_condition, Eq): if not isinstance(given_condition.lhs, Probability) or \ given_condition.lhs.args[0] != conds[i]: raise ValueError("Probability for %s needed", conds[i]) return result * given_condition.rhs raise NotImplementedError("Mechanism for handling (%s, %s) queries hasn't been " "implemented yet."%(condition, given_condition))