[docs]classRandomDomain(Basic):""" Represents a set of variables and the values which they can take See Also ======== sympy.stats.crv.ContinuousDomain sympy.stats.frv.FiniteDomain """is_ProductDomain=Falseis_Finite=Falseis_Continuous=Falsedef__new__(cls,symbols,*args):symbols=FiniteSet(*symbols)returnBasic.__new__(cls,symbols,*args)@propertydefsymbols(self):returnself.args[0]@propertydefset(self):returnself.args[1]def__contains__(self,other):raiseNotImplementedError()defintegrate(self,expr):raiseNotImplementedError()

[docs]classSingleDomain(RandomDomain):""" A single variable and its domain See Also ======== sympy.stats.crv.SingleContinuousDomain sympy.stats.frv.SingleFiniteDomain """def__new__(cls,symbol,set):assertsymbol.is_SymbolreturnBasic.__new__(cls,symbol,set)@propertydefsymbol(self):returnself.args[0]@propertydefsymbols(self):returnFiniteSet(self.symbol)def__contains__(self,other):iflen(other)!=1:returnFalsesym,val=tuple(other)[0]returnself.symbol==symandvalinself.set

[docs]classConditionalDomain(RandomDomain):""" A RandomDomain with an attached condition See Also ======== sympy.stats.crv.ConditionalContinuousDomain sympy.stats.frv.ConditionalFiniteDomain """def__new__(cls,fulldomain,condition):condition=condition.xreplace(dict((rs,rs.symbol)forrsinrandom_symbols(condition)))returnBasic.__new__(cls,fulldomain,condition)@propertydefsymbols(self):returnself.fulldomain.symbols@propertydeffulldomain(self):returnself.args[0]@propertydefcondition(self):returnself.args[1]@propertydefset(self):raiseNotImplementedError("Set of Conditional Domain not Implemented")defas_boolean(self):returnAnd(self.fulldomain.as_boolean(),self.condition)

[docs]classPSpace(Basic):""" A Probability Space Probability Spaces encode processes that equal different values probabalistically. These underly Random Symbols which occur in SymPy expressions and contain the mechanics to evaluate statistical statements. See Also ======== sympy.stats.crv.ContinuousPSpace sympy.stats.frv.FinitePSpace """is_Finite=Noneis_Continuous=Noneis_real=None@propertydefdomain(self):returnself.args[0]@propertydefdensity(self):returnself.args[1]@propertydefvalues(self):returnfrozenset(RandomSymbol(self,sym)forsyminself.domain.symbols)@propertydefsymbols(self):returnself.domain.symbolsdefwhere(self,condition):raiseNotImplementedError()defcompute_density(self,expr):raiseNotImplementedError()defsample(self):raiseNotImplementedError()defprobability(self,condition):raiseNotImplementedError()defintegrate(self,expr):raiseNotImplementedError()

[docs]classSinglePSpace(PSpace):""" Represents the probabilities of a set of random events that can be attributed to a single variable/symbol. """def__new__(cls,s,distribution):ifisinstance(s,str):s=Symbol(s)ifnotisinstance(s,Symbol):raiseTypeError("s should have been string or Symbol")returnBasic.__new__(cls,s,distribution)@propertydefvalue(self):returnRandomSymbol(self,self.symbol)@propertydefsymbol(self):returnself.args[0]@propertydefdistribution(self):returnself.args[1]@propertydefpdf(self):returnself.distribution.pdf(self.symbol)

[docs]classRandomSymbol(Expr):""" Random Symbols represent ProbabilitySpaces in SymPy Expressions In principle they can take on any value that their symbol can take on within the associated PSpace with probability determined by the PSpace Density. Random Symbols contain pspace and symbol properties. The pspace property points to the represented Probability Space The symbol is a standard SymPy Symbol that is used in that probability space for example in defining a density. You can form normal SymPy expressions using RandomSymbols and operate on those expressions with the Functions E - Expectation of a random expression P - Probability of a condition density - Probability Density of an expression given - A new random expression (with new random symbols) given a condition An object of the RandomSymbol type should almost never be created by the user. They tend to be created instead by the PSpace class's value method. Traditionally a user doesn't even do this but instead calls one of the convenience functions Normal, Exponential, Coin, Die, FiniteRV, etc.... """def__new__(cls,pspace,symbol):ifnotisinstance(symbol,Symbol):raiseTypeError("symbol should be of type Symbol")ifnotisinstance(pspace,PSpace):raiseTypeError("pspace variable should be of type PSpace")returnBasic.__new__(cls,pspace,symbol)is_bounded=Trueis_finite=Trueis_Symbol=Trueis_Atom=True_diff_wrt=Truepspace=property(lambdaself:self.args[0])symbol=property(lambdaself:self.args[1])name=property(lambdaself:self.symbol.name)is_positive=property(lambdaself:self.symbol.is_positive)is_integer=property(lambdaself:self.symbol.is_integer)is_real=property(lambdaself:self.symbol.is_realorself.pspace.is_real)@propertydefis_commutative(self):returnself.symbol.is_commutativedef_hashable_content(self):returnself.pspace,self.symbol@propertydeffree_symbols(self):returnset([self])

[docs]classProductPSpace(PSpace):""" A probability space resulting from the merger of two independent probability spaces. Often created using the function, pspace """def__new__(cls,*spaces):rs_space_dict={}forspaceinspaces:forvalueinspace.values:rs_space_dict[value]=spacesymbols=FiniteSet(val.symbolforvalinrs_space_dict.keys())# Overlapping symbolsiflen(symbols)<sum(len(space.symbols)forspaceinspaces):raiseValueError("Overlapping Random Variables")ifall(space.is_Finiteforspaceinspaces):fromsympy.stats.frvimportProductFinitePSpacecls=ProductFinitePSpaceifall(space.is_Continuousforspaceinspaces):fromsympy.stats.crvimportProductContinuousPSpacecls=ProductContinuousPSpaceobj=Basic.__new__(cls,*FiniteSet(*spaces))returnobj@propertydefrs_space_dict(self):d={}forspaceinself.spaces:forvalueinspace.values:d[value]=spacereturnd@propertydefsymbols(self):returnFiniteSet(val.symbolforvalinself.rs_space_dict.keys())@propertydefspaces(self):returnFiniteSet(*self.args)@propertydefvalues(self):returnsumsets(space.valuesforspaceinself.spaces)defintegrate(self,expr,rvs=None,**kwargs):rvs=rvsorself.valuesrvs=frozenset(rvs)forspaceinself.spaces:expr=space.integrate(expr,rvs&space.values,**kwargs)returnexpr@propertydefdomain(self):returnProductDomain(*[space.domainforspaceinself.spaces])@propertydefdensity(self):raiseNotImplementedError("Density not available for ProductSpaces")defsample(self):returndict([(k,v)forspaceinself.spacesfork,vinspace.sample().items()])

[docs]classProductDomain(RandomDomain):""" A domain resulting from the merger of two independent domains See Also ======== sympy.stats.crv.ProductContinuousDomain sympy.stats.frv.ProductFiniteDomain """is_ProductDomain=Truedef__new__(cls,*domains):symbols=sumsets([domain.symbolsfordomainindomains])# Flatten any product of productsdomains2=[]fordomainindomains:ifnotdomain.is_ProductDomain:domains2.append(domain)else:domains2.extend(domain.domains)domains2=FiniteSet(domains2)ifall(domain.is_Finitefordomainindomains2):fromsympy.stats.frvimportProductFiniteDomaincls=ProductFiniteDomainifall(domain.is_Continuousfordomainindomains2):fromsympy.stats.crvimportProductContinuousDomaincls=ProductContinuousDomainreturnBasic.__new__(cls,*domains2)@propertydefsym_domain_dict(self):returndict((symbol,domain)fordomaininself.domainsforsymbolindomain.symbols)@propertydefsymbols(self):returnFiniteSet(symfordomaininself.domainsforsymindomain.symbols)@propertydefdomains(self):returnself.args@propertydefset(self):returnProductSet(domain.setfordomaininself.domains)def__contains__(self,other):# Split event into each subdomainfordomaininself.domains:# Collect the parts of this event which associate to this domainelem=frozenset([itemforiteminotherifitem[0]indomain.symbols])# Test this sub-eventifelemnotindomain:returnFalse# All subevents passedreturnTruedefas_boolean(self):returnAnd(*[domain.as_boolean()fordomaininself.domains])

[docs]defrandom_symbols(expr):""" Returns all RandomSymbols within a SymPy Expression. """try:returnlist(expr.atoms(RandomSymbol))exceptAttributeError:return[]

[docs]defrs_swap(a,b):""" Build a dictionary to swap RandomSymbols based on their underlying symbol. i.e. if ``X = ('x', pspace1)`` and ``Y = ('x', pspace2)`` then ``X`` and ``Y`` match and the key, value pair ``{X:Y}`` will appear in the result Inputs: collections a and b of random variables which share common symbols Output: dict mapping RVs in a to RVs in b """d={}forrsaina:d[rsa]=[rsbforrsbinbifrsa.symbol==rsb.symbol][0]returnd