diff --git a/README.md b/README.md index 4588c33..109b8b6 100644 --- a/README.md +++ b/README.md @@ -193,11 +193,13 @@ Done: - [x] Make -n flag work - [x] Add flag to repeat input lines (useful when reading from files) - [x] Add percentages +- [x] Consider adding an understanding of percentages To (possibly) do: +- [ ] Consider implications of sampling strategy for operating variables in this case. +- [ ] Document mixture distributions - [ ] Fix lognormal multiplication and division by 0 or < 0 -- [ ] Consider adding an understanding of percentages - [ ] With the -f command line option, the program doesn't read from stdin after finishing reading the file - [ ] Add functions. Now easier to do with an explicit representation of the stakc - [ ] Think about how to draw a histogram from samples diff --git a/fermi b/fermi index e73217f..1e308de 100755 Binary files a/fermi and b/fermi differ diff --git a/fermi.go b/fermi.go index 90ca722..60c5611 100644 --- a/fermi.go +++ b/fermi.go @@ -20,7 +20,6 @@ type Stack struct { } type Dist interface { - Samples() []float64 Sampler(int, sample.State) float64 } @@ -42,44 +41,22 @@ type FilledSamples struct { /* Dist interface functions */ // https://go.dev/tour/methods/9 -func (p Scalar) Samples() []float64 { - xs := make([]float64, N_SAMPLES) - for i := 0; i < N_SAMPLES; i++ { - xs[i] = float64(p) - } - return xs -} func (p Scalar) Sampler(i int, r sample.State) float64 { return float64(p) } -func (ln Lognormal) Samples() []float64 { - sampler := func(r sample.State) float64 { return sample.Sample_to(ln.low, ln.high, r) } - // Can't do parallel because then I'd have to await throughout the code - return sample.Sample_serially(sampler, N_SAMPLES) -} func (ln Lognormal) Sampler(i int, r sample.State) float64 { return sample.Sample_to(ln.low, ln.high, r) } -func (beta Beta) Samples() []float64 { - sampler := func(r sample.State) float64 { return sample.Sample_beta(beta.a, beta.b, r) } - return sample.Sample_serially(sampler, N_SAMPLES) -} func (beta Beta) Sampler(i int, r sample.State) float64 { return sample.Sample_beta(beta.a, beta.b, r) } -func (fs FilledSamples) Samples() []float64 { - return fs.xs -} func (fs FilledSamples) Sampler(i int, r sample.State) float64 { // This is a bit subtle, because sampling from FilledSamples randomly iteratively converges // to something different than the initial distribution // So instead we have an i parameter. - // Not sure how I feel about it - // n := len(fs.xs) - // i := sample.Sample_int(n, r) return fs.xs[i] } @@ -180,7 +157,7 @@ func printAndReturnErr(err_msg string) error { } func prettyPrintStats(dist Dist) { - xs := dist.Samples() + xs := sample.Sample_serially(dist.Sampler, N_SAMPLES) n := len(xs) mean := 0.0 @@ -221,8 +198,8 @@ func prettyPrintStats(dist Dist) { // Generic operations with samples func operateDistsAsSamples(dist1 Dist, dist2 Dist, op string) (Dist, error) { - xs := dist1.Samples() - ys := dist2.Samples() + xs := sample.Sample_serially(dist1.Sampler, N_SAMPLES) + ys := sample.Sample_serially(dist2.Sampler, N_SAMPLES) zs := make([]float64, N_SAMPLES) for i := 0; i < N_SAMPLES; i++ { @@ -379,9 +356,7 @@ func parseMixture(words []string, vars map[string]Dist) (Dist, error) { return nil, printAndReturnErr("Not a mixture. \nMixture syntax: \nmx x 2.5 y 8 z 10\ni.e.: mx var weight var2 weight2 ... var_n weight_n") } - var dists []Dist var fs []func(int, sample.State) float64 - // var ss [][]float64 var weights []float64 for i, word := range words { @@ -390,12 +365,8 @@ func parseMixture(words []string, vars map[string]Dist) (Dist, error) { if !exists { return nil, printAndReturnErr("Expected mixture variable but didn't get a variable. \nMixture syntax: \nmx x 2.5 y 8 z 10\ni.e.: mx var weight var2 weight2 ... var_n weight_n") } - // samples := dist.Samples() f := dist.Sampler - // Inefficient to draw N_SAMPLES for each of the distributions, but conceptually simpler. - dists = append(dists, dist) fs = append(fs, f) - // ss = append(ss, samples) } else { weight, err := pretty.ParseFloat(word) if err != nil { diff --git a/sample/sample.go b/sample/sample.go index 19b5725..33364e5 100644 --- a/sample/sample.go +++ b/sample/sample.go @@ -149,11 +149,11 @@ func Sample_mixture_once(fs []func64, weights []float64, r State) float64 { } -func Sample_serially(f func64, n_samples int) []float64 { +func Sample_serially(f func64i, n_samples int) []float64 { xs := make([]float64, n_samples) // var global_state = rand.New(rand.NewPCG(uint64(1), uint64(2))) for i := 0; i < n_samples; i++ { - xs[i] = f(global_state) + xs[i] = f(i, global_state) } return xs }