Skip to content

Commit 1a495eb

Browse files
committed
Refactor to IID Random Variable hierarchy
1 parent 23eb1ab commit 1a495eb

File tree

3 files changed

+104
-18
lines changed

3 files changed

+104
-18
lines changed

dynaml-core/src/main/scala-2.11/io/github/mandar2812/dynaml/probability/IIDRandomVariable.scala

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ under the License.
1818
* */
1919
package io.github.mandar2812.dynaml.probability
2020

21-
import breeze.stats.distributions.{ContinuousDistr, Density, Rand}
21+
import breeze.stats.distributions.{ContinuousDistr, Density, DiscreteDistr, Rand}
2222
import io.github.mandar2812.dynaml.pipes.DataPipe
23-
import io.github.mandar2812.dynaml.probability.distributions.{AbstractContinuousDistr, GenericDistribution}
23+
import io.github.mandar2812.dynaml.probability.distributions.{AbstractContinuousDistr, AbstractDiscreteDistr, GenericDistribution}
2424

2525
/**
2626
* An independent and identically distributed
@@ -86,6 +86,16 @@ D, +Dist <: Density[D] with Rand[D],
8686
}
8787
}
8888

89+
object IIDRandomVarDistr {
90+
def apply[D, Dist <: Density[D] with Rand[D]](base : RandomVarWithDistr[D, Dist])(n: Int)
91+
: IIDRandomVarDistr[D, Dist, RandomVarWithDistr[D, Dist]] =
92+
new IIDRandomVarDistr[D, Dist, RandomVarWithDistr[D, Dist]] {
93+
val baseRandomVariable = base
94+
val num = n
95+
}
96+
97+
}
98+
8999
/**
90100
* An IID Random variable constructed
91101
* from a continuous random variable having
@@ -113,19 +123,39 @@ D, +Distr <: ContinuousDistr[D],
113123

114124
}
115125

116-
object IIDRandomVarDistr {
117-
def apply[D, Dist <: Density[D] with Rand[D]](base : RandomVarWithDistr[D, Dist])(n: Int) =
118-
new IIDRandomVarDistr[D, Dist, RandomVarWithDistr[D, Dist]] {
119-
val baseRandomVariable = base
120-
val num = n
121-
}
126+
object IIDContinuousRVDistr {
122127

123128
def apply[
124129
D, Distr <: ContinuousDistr[D],
125-
R <: ContinuousRVWithDistr[D, Distr]](base: R)(n: Int) = new IIDContinuousRVDistr[D, Distr, R] {
126-
override val baseRandomVariable = base
127-
override val num = n
130+
R <: ContinuousRVWithDistr[D, Distr]](base: R)(n: Int): IIDContinuousRVDistr[D, Distr, R] =
131+
new IIDContinuousRVDistr[D, Distr, R] {
132+
override val baseRandomVariable = base
133+
override val num = n
134+
}
135+
136+
137+
}
138+
139+
trait IIDDiscreteRVDistr[
140+
D, +Distr <: DiscreteDistr[D],
141+
+R <: DiscreteRVWithDistr[D, Distr]] extends
142+
IIDRandomVarDistr[D, Distr, R] {
143+
144+
override val underlyingDist = new AbstractDiscreteDistr[Stream[D]] {
145+
override def probabilityOf(x: Stream[D]) = x.map(baseRandomVariable.underlyingDist.probabilityOf).product
146+
147+
override def draw() = Stream.tabulate[D](num)(_ => baseRandomVariable.underlyingDist.draw())
128148
}
149+
}
150+
151+
object IIDDiscreteRVDistr {
152+
def apply[
153+
D, Distr <: DiscreteDistr[D],
154+
R <: DiscreteRVWithDistr[D, Distr]](base: R)(n: Int): IIDDiscreteRVDistr[D, Distr, R] =
155+
new IIDDiscreteRVDistr[D, Distr, R] {
156+
override val baseRandomVariable = base
157+
override val num = n
158+
}
129159

130160
}
131161

dynaml-core/src/main/scala-2.11/io/github/mandar2812/dynaml/probability/RandomVariable.scala

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,22 +235,76 @@ trait RandomVarWithDistr[Domain, +Dist <: Density[Domain] with Rand[Domain]]
235235

236236
}
237237

238+
/**
239+
* A continuous random variable that has an associated
240+
* probability density function.
241+
*
242+
* @tparam Domain Support/Sample space of the random variable
243+
* @tparam Distr Type of the probability density as a subtype of breeze [[ContinuousDistr]]
244+
* */
238245
trait ContinuousRVWithDistr[Domain, +Distr <: ContinuousDistr[Domain]] extends
239246
ContinuousRandomVariable[Domain] with
240247
RandomVarWithDistr[Domain, Distr] {
241248

249+
self =>
250+
242251
override val underlyingDist: Distr
243252

244253
override val sample = DataPipe(() => underlyingDist.sample())
245254

246-
override def iid(n: Int) = IIDRandomVarDistr[Domain, Distr, this.type](this)(n)
255+
override def iid(n: Int) = IIDContinuousRVDistr[Domain, Distr, self.type](self)(n)
256+
257+
def :*[OtherDomain, OtherDistr <: ContinuousDistr[OtherDomain]](
258+
other: ContinuousRVWithDistr[OtherDomain, OtherDistr]) = {
259+
260+
val productDensity = new ContinuousDistr[(Domain, OtherDomain)] {
261+
262+
override def unnormalizedLogPdf(x: (Domain, OtherDomain)) =
263+
self.underlyingDist.logPdf(x._1) + other.underlyingDist.logPdf(x._2)
264+
265+
override def logNormalizer = self.underlyingDist.logNormalizer + other.underlyingDist.logNormalizer
266+
267+
override def draw() = (self.underlyingDist.draw, other.underlyingDist.draw)
268+
}
269+
270+
RandomVariable(productDensity)
271+
}
272+
273+
}
274+
275+
trait DiscreteRVWithDistr[Domain, +Distr <: DiscreteDistr[Domain]] extends
276+
RandomVarWithDistr[Domain, Distr] {
277+
278+
self =>
279+
280+
override val underlyingDist: Distr
281+
282+
override val sample = DataPipe(() => underlyingDist.sample())
283+
284+
override def iid(n: Int) = IIDDiscreteRVDistr[Domain, Distr, self.type](self)(n)
285+
286+
def :*[OtherDomain, OtherDistr <: DiscreteDistr[OtherDomain]](
287+
other: DiscreteRVWithDistr[OtherDomain, OtherDistr]) = {
288+
289+
val productDensity = new DiscreteDistr[(Domain, OtherDomain)] {
290+
291+
override def probabilityOf(x: (Domain, OtherDomain)) =
292+
self.underlyingDist.probabilityOf(x._1)*other.underlyingDist.probabilityOf(x._2)
293+
294+
override def draw() = (self.underlyingDist.draw, other.underlyingDist.draw)
295+
}
296+
297+
RandomVariable(productDensity)
298+
}
299+
247300
}
248301

249302
/**
250303
* A continuous random variable that has an associated
251304
* probability density function.
252305
*
253306
* */
307+
@deprecated("ContinuousDistrRV is deprecated as of DynaML v1.5, prefer ContinuousRVWithDistr")
254308
trait ContinuousDistrRV[Domain] extends
255309
ContinuousRVWithDistr[Domain, ContinuousDistr[Domain]] { self =>
256310

@@ -356,9 +410,10 @@ object RandomVariable {
356410
* @param d A breeze discrete distribution
357411
* @return A discrete random variable instance.
358412
* */
359-
def apply[O](d: DiscreteDistr[O]): DiscreteDistrRV[O] = new DiscreteDistrRV[O] {
360-
override val underlyingDist = d
361-
}
413+
def apply[O](d: DiscreteDistr[O]): DiscreteRVWithDistr[O, DiscreteDistr[O]] =
414+
new DiscreteRVWithDistr[O, DiscreteDistr[O]] {
415+
override val underlyingDist = d
416+
}
362417

363418
def apply[O](g: ThreadedBufferedRand[O]) = new ThreadedRandomVariable[O](g)
364419

dynaml-core/src/main/scala-2.11/io/github/mandar2812/dynaml/probability/StudentsTRV.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ object MultStudentsTRV {
4444
}
4545
}
4646

47-
case class MultStudentsTPRV(mu: Double,
48-
mean: PartitionedVector,
49-
covariance: PartitionedPSDMatrix)(
47+
case class MultStudentsTPRV(
48+
mu: Double,
49+
mean: PartitionedVector,
50+
covariance: PartitionedPSDMatrix)(
5051
implicit ev: Field[PartitionedVector])
5152
extends AbstractStudentsTRandVar[PartitionedVector, PartitionedPSDMatrix, BlockedMultivariateStudentsT](mu) {
5253

0 commit comments

Comments
 (0)