Skip to content
Snippets Groups Projects
Commit ac9a0c8c authored by Andrew E. Torda's avatar Andrew E. Torda
Browse files

Added a switch to turn off adaptive move size.

parent 976e47c5
Branches
No related tags found
No related merge requests found
- in main MC, add a boolean to make move size adjustment optional. Otherwise the method works too well for an Uebung.
- Add radio button to input tab for adaptive move sizes
- Change the adaptive scheme so it looks more like weak coupling. Scale the adjustment by current rate / desired rate - Change the adaptive scheme so it looks more like weak coupling. Scale the adjustment by current rate / desired rate
- add testing to the ui directory - add testing to the ui directory
- Save the best found configuration, print out at end
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// where input_file is a set of name-value pairs. These are defined with defaults // where input_file is a set of name-value pairs. These are defined with defaults
// in rdprm.go. At the moment, we have // in rdprm.go. At the moment, we have
package main package main
// BUGS // BUGS
// A chart in png format from go-chart is no problem, but a file in svg format causes a parse error in fyne. // A chart in png format from go-chart is no problem, but a file in svg format causes a parse error in fyne.
/* /*
......
...@@ -189,10 +189,11 @@ func nRunAdj(mcPrm *McPrm, nstep int, runAcc float64, xDlta float64) float64 { ...@@ -189,10 +189,11 @@ func nRunAdj(mcPrm *McPrm, nstep int, runAcc float64, xDlta float64) float64 {
return xDlta return xDlta
} }
// doRun does a Monte Carlo run. Although single precision is fine for the // doRun does a Monte Carlo run.
// coordinates and function, we use double precision for the temperature. // We only need single precision for most things, except for function
// Unfortunately, the plotting functions want double precision, so we store // values, but the interface to the plot and interface packages mostly
// an awful lot of stuff as float64. // want double precision, so we have a lot of float64 that shoudl be
// float32.
func DoRun(mcPrm *McPrm) (MCresult, error) { func DoRun(mcPrm *McPrm) (MCresult, error) {
var cprm cprm var cprm cprm
broken := MCresult{} broken := MCresult{}
...@@ -204,8 +205,11 @@ func DoRun(mcPrm *McPrm) (MCresult, error) { ...@@ -204,8 +205,11 @@ func DoRun(mcPrm *McPrm) (MCresult, error) {
defer cprm.fOut.Flush() defer cprm.fOut.Flush()
} }
if c, ok := cprm.fplotWrt.(io.Closer); ok { // will also have to do for X values if c, ok := cprm.fplotWrt.(io.Closer); ok {
defer c.Close() defer c.Close() // file handle for function values
}
if c, ok := cprm.xplotWrt.(io.Closer); ok {
defer c.Close() // file handle for X trajectories
} }
var nAcc int // Counter, number of accepted moves var nAcc int // Counter, number of accepted moves
...@@ -213,32 +217,33 @@ func DoRun(mcPrm *McPrm) (MCresult, error) { ...@@ -213,32 +217,33 @@ func DoRun(mcPrm *McPrm) (MCresult, error) {
xT := make([]float32, len(mcPrm.XIni)) // trial position xT := make([]float32, len(mcPrm.XIni)) // trial position
runAcc := accRateIdeal // Running acceptance rate, exponentially weighted runAcc := accRateIdeal // Running acceptance rate, exponentially weighted
for i := range mcPrm.XIni { for i := range mcPrm.XIni { // Initial coordinates from
x[i] = float32(mcPrm.XIni[i]) x[i] = float32(mcPrm.XIni[i]) // the control structure
} }
// copy(x, mcPrm.XIni) I had to replace this with the loop above
fOld := ackley.Ackley(x) // Initial function value fOld := ackley.Ackley(x) // Initial function value
fTrial := fOld fTrial := fOld
tmprtr := float64(mcPrm.IniTmp) tmprtr := float64(mcPrm.IniTmp)
nRunAcc := nRunAccAdj // Every nRunAccAdj, try adjusting the step size. nRunAcc := nRunAccAdj // Every nRunAccAdj, try adjusting the step size.
const runMult = 0.99 const runMult = 0.99
xDlta := mcPrm.XDlta // Adaptable step size xDlta := mcPrm.XDlta // Step size which might be adjusted on the fly
saveStep(&cprm, 0, tmprtr, x, fOld) saveStep(&cprm, 0, tmprtr, x, fOld)
for n := 0; n < mcPrm.NStep; n++ { for n := 0; n < mcPrm.NStep; n++ {
var accept bool var accept bool
if mcPrm.AdaptStep {
nRunAcc-- nRunAcc--
if nRunAcc == 0 { // Do we want to try adjusting the step size ? if nRunAcc == 0 { // Do we want to try adjusting the step size ?
xDlta = nRunAdj(mcPrm, n, runAcc, xDlta) xDlta = nRunAdj(mcPrm, n, runAcc, xDlta)
nRunAcc = nRunAccAdj // Reset the counter nRunAcc = nRunAccAdj // Reset the counter
} }
}
newx(x, xT, cprm.rand, xDlta) newx(x, xT, cprm.rand, xDlta)
fTrial = ackley.Ackley(xT) fTrial = ackley.Ackley(xT)
if fTrial <= fOld { if fTrial <= fOld {
accept = true accept = true
} else { } else {
delta := fTrial - fOld // Make the decision as to whether to delta := fTrial - fOld // Decision as to whether to
t := math.Exp(-delta / tmprtr) // accept or reject the trial t := math.Exp(-delta / tmprtr) // accept or reject the trial
if cprm.rand.Float64() < t { if cprm.rand.Float64() < t {
accept = true accept = true
...@@ -246,12 +251,16 @@ func DoRun(mcPrm *McPrm) (MCresult, error) { ...@@ -246,12 +251,16 @@ func DoRun(mcPrm *McPrm) (MCresult, error) {
} }
if accept { if accept {
nAcc++ nAcc++
runAcc = runMult*runAcc + (1.0 - runMult)
copy(x, xT) copy(x, xT)
fOld = fTrial fOld = fTrial
saveStep(&cprm, n+1, tmprtr, x, fTrial) saveStep(&cprm, n+1, tmprtr, x, fTrial)
} else { // update the running estimate of acceptance if mcPrm.AdaptStep {
runAcc = runMult * runAcc runAcc = runMult*runAcc + (1.0 - runMult)
}
} else { // else don't really have to do anything, but update statistics
if mcPrm.AdaptStep {
runAcc = runMult * runAcc // update the running estimate of acceptance
}
} }
if cprm.coolme { if cprm.coolme {
tmprtr *= cprm.coolMult tmprtr *= cprm.coolMult
......
...@@ -15,6 +15,7 @@ type McPrm struct { ...@@ -15,6 +15,7 @@ type McPrm struct {
fOutName string // where we write output to fOutName string // where we write output to
fPltName string // where we plot to (function values) fPltName string // where we plot to (function values)
xPltName string // where we plot x trajectories to xPltName string // where we plot x trajectories to
AdaptStep bool // Adaptive step sizes
verbose bool verbose bool
dummy bool // for testing. If set, do not do a run dummy bool // for testing. If set, do not do a run
} }
......
...@@ -29,6 +29,7 @@ var cmdDflt = []struct { ...@@ -29,6 +29,7 @@ var cmdDflt = []struct {
{"foutname", ""}, {"foutname", ""},
{"fpltname", ""}, // empty means no plots of function {"fpltname", ""}, // empty means no plots of function
{"xpltname", ""}, {"xpltname", ""},
{"adaptstep", ""},
{"verbose", ""}, {"verbose", ""},
{"dummy", ""}, {"dummy", ""},
} }
...@@ -88,6 +89,9 @@ func digest(prmMap map[string]string, mcPrm *McPrm) error { ...@@ -88,6 +89,9 @@ func digest(prmMap map[string]string, mcPrm *McPrm) error {
if prmMap["verbose"] != "" { if prmMap["verbose"] != "" {
mcPrm.verbose = true mcPrm.verbose = true
} }
if prmMap["adaptstep"] != "" {
mcPrm.AdaptStep = true
}
if prmMap["dummy"] != "" { if prmMap["dummy"] != "" {
mcPrm.dummy = true mcPrm.dummy = true
} }
......
...@@ -86,6 +86,7 @@ func intItem(xAddr *int, label string, htext string) (*widget.FormItem, func()) ...@@ -86,6 +86,7 @@ func intItem(xAddr *int, label string, htext string) (*widget.FormItem, func())
} }
var xCoordHint = "The starting point. A comma-separated list of floats. It is used to set the dimensionality" var xCoordHint = "The starting point. A comma-separated list of floats. It is used to set the dimensionality"
// paramBox sets up a screen full of parameters we can adjust. // paramBox sets up a screen full of parameters we can adjust.
// It returns the screen and a function to be called to refresh it. // It returns the screen and a function to be called to refresh it.
// This is necessary, since there is a button to read parameters from // This is necessary, since there is a button to read parameters from
...@@ -115,6 +116,11 @@ func paramForm(genParams genParams) *widget.Form { ...@@ -115,6 +116,11 @@ func paramForm(genParams genParams) *widget.Form {
nStepItem, nStepReload := intItem(&mcPrm.NStep, "N steps", "number of steps in calculation") nStepItem, nStepReload := intItem(&mcPrm.NStep, "N steps", "number of steps in calculation")
seedItem, seedReload := intItem(&mcwork.Seed, "seed random numbers", "seed for random number generator") seedItem, seedReload := intItem(&mcwork.Seed, "seed random numbers", "seed for random number generator")
adaptbind := binding.BindBool(&mcPrm.AdaptStep)
adaptEntry := widget.NewCheckWithData("adaptive step size", adaptbind)
adaptItem := widget.NewFormItem("fI string", adaptEntry)
adaptItem.HintText = "Turn on adaptive moves to try to keep acceptance near 5%"
adaptReload := func() { _ = adaptbind.Reload() }
reloadPTab := func() { reloadPTab := func() {
iniTmpReload() iniTmpReload()
fnlTmpReload() fnlTmpReload()
...@@ -122,6 +128,7 @@ func paramForm(genParams genParams) *widget.Form { ...@@ -122,6 +128,7 @@ func paramForm(genParams genParams) *widget.Form {
xIniEntry.SetText(fslicestrng(mcPrm.XIni)) xIniEntry.SetText(fslicestrng(mcPrm.XIni))
nStepReload() nStepReload()
seedReload() seedReload()
adaptReload()
} }
rdfile := func() { rdwork(genParams, reloadPTab) } rdfile := func() { rdwork(genParams, reloadPTab) }
...@@ -130,7 +137,7 @@ func paramForm(genParams genParams) *widget.Form { ...@@ -130,7 +137,7 @@ func paramForm(genParams genParams) *widget.Form {
r := widget.NewForm( // Lays out the items in the form r := widget.NewForm( // Lays out the items in the form
iniTmpItem, fnlTmpItem, xDltaItem, xIniItem, iniTmpItem, fnlTmpItem, xDltaItem, xIniItem,
nStepItem, seedItem, rdFileItem) nStepItem, seedItem, adaptItem, rdFileItem)
r.SubmitText = "start calculation" r.SubmitText = "start calculation"
r.OnSubmit = func() { startrun(genParams, r, mcPrm) } r.OnSubmit = func() { startrun(genParams, r, mcPrm) }
reloadPTab() // does this help ? sometimes the form pops up with entries not ready reloadPTab() // does this help ? sometimes the form pops up with entries not ready
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment