class DiscreteDistr(Distr): """Discrete distribution""" def __init__(self, xi=[0.0, 1.0], pi=[0.5, 0.5]): super(DiscreteDistr, self).__init__([]) assert(len(xi) == len(pi)) px = zip(xi, pi) px.sort() self.px = px self.xi = [p[0] for p in px] self.pi = [p[1] for p in px] self.cumP = cumsum(self.pi) def pdf(self, x): x = array(x) """it override pdf() method to obtain discrete probabilities""" yy = zeros_like(x, dtype=float) for i in range(len(self.pi)): yy[x==self.xi[i]] += float(self.pi[i]) return yy def init_piecewise_pdf(self): self.piecewise_pdf = PiecewiseDistribution([]) for i in xrange(len(self.xi)): self.piecewise_pdf.addSegment(DiracSegment(self.xi[i], self.pi[i])) for i in xrange(len(self.xi)-1): self.piecewise_pdf.addSegment(ConstSegment(self.xi[i], self.xi[i+1], 0)) def rand_raw(self, n): u = uniform(0, 1, n) i = searchsorted(self.cumP, u) i[i > len(self.xi)] = len(self.xi) return array(self.xi)[i] def __str__(self): pstr = ", ".join("{0}:{1}".format(x, p) for x, p in self.px) return "Discrete({0})#{1}".format(pstr, self.id()) def getName(self): return "Di({0})".format(len(self.xi))
def convmodel(self): """Probabilistic operation defined by model """ op = self.symop #d.getSym() x = self.symvars[0] y = self.symvars[1] lop = my_lambdify([x, y], op, "numpy") F = self.vars[0] G = self.vars[1] #self.nddistr.setMarginals(F, G) f = self.vars[0].get_piecewise_pdf() g = self.vars[1].get_piecewise_pdf() bf = f.getBreaks() bg = g.getBreaks() bi = zeros(len(bf) * len(bg)) k = 0 for xi in bf: for yi in bg: if not isnan(lop(xi, yi)): bi[k] = lop(xi, yi) else: pass #print "not a number, xi=", xi, "yi=", yi, "result=", lop(xi,yi) k += 1 ub = array(unique(bi)) fun = lambda x: self.convmodelx(segList, x) fg = PiecewiseDistribution([]) if isinf(ub[0]): segList = _findSegList(f, g, ub[1] - 1, lop) seg = MInfSegment(ub[1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[1:] if isinf(ub[-1]): segList = _findSegList(f, g, ub[-2] + 1, lop) seg = PInfSegment(ub[-2], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[0:-1] for i in range(len(ub) - 1): segList = _findSegList(f, g, (ub[i] + ub[i + 1]) / 2, lop) seg = Segment(ub[i], ub[i + 1], partial(self.convmodelx, segList)) #seg = Segment(ub[i],ub[i+1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) # Discrete parts of distributions #fg_discr = convdiracs(f, g, fun = lambda x,y : x * p + y * q) #for seg in fg_discr.getDiracs(): # fg.addSegment(seg) return fg
def convmean(F, G, p=0.5, q=0.5, theta=1.0): """Probabilistic weighted mean of f and g """ f = F.get_piecewise_pdf() g = G.get_piecewise_pdf() if p + q <> 1.0: p1 = abs(p) / (abs(p) + abs(q)) q = abs(q) / (abs(p) + abs(q)) p = p1 if q == 0: return f bf = f.getBreaks() bg = g.getBreaks() b = add.outer(bf * p, bg * q) fun = lambda x: convmeanx(F, G, segList, x, p, q, theta=theta) ub = epsunique(b) fg = PiecewiseDistribution([]) op = lambda x, y: p * x + q * y if isinf(ub[0]): segList = _findSegList(f, g, ub[1] - 1, op) seg = MInfSegment(ub[1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[1:] if isinf(ub[-1]): segList = _findSegList(f, g, ub[-2] + 1, op) seg = PInfSegment(ub[-2], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[0:-1] for i in range(len(ub) - 1): segList = _findSegList(f, g, (ub[i] + ub[i + 1]) / 2, op) seg = Segment(ub[i], ub[i + 1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) # Discrete parts of distributions fg_discr = convdiracs(f, g, fun=lambda x, y: x * p + y * q) for seg in fg_discr.getDiracs(): fg.addSegment(seg) return fg
def convmodel(self): """Probabilistic operation defined by model """ op = self.symop#d.getSym() x = self.symvars[0] y = self.symvars[1] lop = my_lambdify([x, y], op, "numpy") F = self.vars[0] G = self.vars[1] #self.nddistr.setMarginals(F, G) f = self.vars[0].get_piecewise_pdf() g = self.vars[1].get_piecewise_pdf() bf = f.getBreaks() bg = g.getBreaks() bi = zeros(len(bf) * len(bg)) k = 0; for xi in bf: for yi in bg: if not isnan(lop(xi, yi)): bi[k] = lop(xi, yi) else: pass #print "not a number, xi=", xi, "yi=", yi, "result=", lop(xi,yi) k += 1 ub = array(unique(bi)) fun = lambda x : self.convmodelx(segList, x) fg = PiecewiseDistribution([]); if isinf(ub[0]): segList = _findSegList(f, g, ub[1] -1, lop) seg = MInfSegment(ub[1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub=ub[1:] if isinf(ub[-1]): segList = _findSegList(f, g, ub[-2] + 1, lop) seg = PInfSegment(ub[-2], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub=ub[0:-1] for i in range(len(ub) - 1) : segList = _findSegList(f, g, (ub[i] + ub[i + 1]) / 2, lop) seg = Segment(ub[i], ub[i + 1], partial(self.convmodelx, segList)) #seg = Segment(ub[i],ub[i+1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) # Discrete parts of distributions #fg_discr = convdiracs(f, g, fun = lambda x,y : x * p + y * q) #for seg in fg_discr.getDiracs(): # fg.addSegment(seg) return fg
def convmean(F, G, p=0.5, q=0.5, theta=1.0): """Probabilistic weighted mean of f and g """ f = F.get_piecewise_pdf() g = G.get_piecewise_pdf() if p + q != 1.0 : p1 = abs(p) / (abs(p) + abs(q)) q = abs(q) / (abs(p) + abs(q)) p = p1; if q == 0: return f; bf = f.getBreaks() bg = g.getBreaks() b = add.outer(bf * p, bg * q) fun = lambda x : convmeanx(F, G, segList, x, p, q, theta=theta) ub = epsunique(b) fg = PiecewiseDistribution([]); op = lambda x, y : p * x + q * y; if isinf(ub[0]): segList = _findSegList(f, g, ub[1] - 1, op) seg = MInfSegment(ub[1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[1:] if isinf(ub[-1]): segList = _findSegList(f, g, ub[-2] + 1, op) seg = PInfSegment(ub[-2], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) ub = ub[0:-1] for i in range(len(ub) - 1) : segList = _findSegList(f, g, (ub[i] + ub[i + 1]) / 2, op) seg = Segment(ub[i], ub[i + 1], fun) segint = seg.toInterpolatedSegment() fg.addSegment(segint) # Discrete parts of distributions fg_discr = convdiracs(f, g, fun=lambda x, y : x * p + y * q) for seg in fg_discr.getDiracs(): fg.addSegment(seg) return fg
def init_piecewise_pdf(self): self.piecewise_pdf = PiecewiseDistribution([]) for i in xrange(len(self.xi)): self.piecewise_pdf.addSegment(DiracSegment(self.xi[i], self.pi[i])) for i in xrange(len(self.xi)-1): self.piecewise_pdf.addSegment(ConstSegment(self.xi[i], self.xi[i+1], 0))
#! How to use PaCal #! ================ from pacal import * from pacal.segments import PiecewiseDistribution, Segment from pacal.standard_distr import PDistr from pylab import figure, show if __name__ == "__main__": #! User defined piecewise distribution #! ----------------------------------- #! Let consider triangular distribution, it consists two smooth segments. fun = PiecewiseDistribution([]) fun.addSegment(Segment(0, 1, lambda x: x)) fun.addSegment(Segment(1, 2, lambda x: 2 - x)) distr = PDistr(fun) #! Here we have summary statistics and accuracies distr.summary() #! Another way to do it: distr = FunDistr(fun=lambda x: 1 - abs(1 - x), breakPoints=[0, 1, 2]) distr.summary() #$ Notice that we set the break point at point 1 and User have to care #$ about $L_1$ nor of distribution. #! The same one obtain using sum of two uniform distributions u = UniformDistr(0, 1) tri = u + u tri.summary() #! Users API for distr object:
#! How to use PaCal #! ================ from __future__ import print_function from pacal import * from pacal.segments import PiecewiseDistribution, Segment from pacal.standard_distr import PDistr from pylab import figure, show if __name__ == "__main__": #! User defined piecewise distribution #! ----------------------------------- #! Let consider triangular distribution, it consists two smooth segments. fun = PiecewiseDistribution([]) fun.addSegment(Segment(0, 1, lambda x:x)) fun.addSegment(Segment(1, 2, lambda x:2 - x)) distr = PDistr(fun) #! Here we have summary statistics and accuracies distr.summary() #! Another way to do it: distr = FunDistr(fun=lambda x: 1 - abs(1 - x), breakPoints=[0, 1, 2]) distr.summary() #$ Notice that we set the break point at point 1 and User have to care #$ about $L_1$ nor of distribution. #! The same one obtain using sum of two uniform distributions u = UniformDistr(0, 1) tri = u + u