simplify fermi.go again

This commit is contained in:
NunoSempere 2024-12-24 17:05:53 +01:00
parent 2314bf5db2
commit e93316446c
4 changed files with 8 additions and 35 deletions

View File

@ -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

BIN
fermi

Binary file not shown.

View File

@ -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 {

View File

@ -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
}