From efbd0c80e4e745c3d999adc7248b807aa83fef66 Mon Sep 17 00:00:00 2001
From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de>
Date: Tue, 4 Jan 2022 16:56:52 +0100
Subject: [PATCH] Trying to simplify main loop. Moved a few lines into their
 own function.

---
 ackwork/dorun.go | 66 ++++++++++++++++++++++++++++--------------------
 ackwork/rdprm.go |  6 ++---
 2 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/ackwork/dorun.go b/ackwork/dorun.go
index 1412afc..4e4b4d4 100644
--- a/ackwork/dorun.go
+++ b/ackwork/dorun.go
@@ -12,6 +12,12 @@ import (
 	"ackley_mc/ackwork/ackley"
 )
 
+const (
+	accRateIdeal = 0.05 // target of 5% acceptance rate
+	nRunAccAdj   = 200  // every n steps, check acceptance rate
+	maxxDlta     = 2.   // max step size
+)
+
 var seedLocker sync.Mutex
 
 // getSeed returns the random number seed, but we have to put a lock
@@ -28,8 +34,8 @@ type cprm struct { // parameters calculated from input
 	rand     *rand.Rand
 	coolMult float64        // multiplier for temperature
 	coolme   bool           // Are we cooling or just doing constant temperature ?
-	fplotme   bool           // Are we making output for plotting func values
-	xplotme bool            // Are we plotting X trajectories
+	fplotme  bool           // Are we making output for plotting func values
+	xplotme  bool           // Are we plotting X trajectories
 	nEvery   uint32         // Output every nEvery steps
 	fOut     io.WriteCloser // csv file for plotting
 	fPlt     io.WriteCloser // for function values
@@ -65,9 +71,11 @@ func setupRun(mcPrm *mcPrm, cprm *cprm) error {
 	}
 
 	cprm.nEvery = uint32(math.Ceil(float64(mcPrm.nStep) / float64(mcPrm.nOutput)))
-	// change the next line to handle the case of multiple runs
-	ntmp := mcPrm.fOutName + ".csv"
-	if cprm.fOut, err = os.Create(ntmp); err != nil {
+
+	if mcPrm.fOutName, err = setSuffix(mcPrm.fOutName, ".csv"); err != nil {
+		return err
+	}
+	if cprm.fOut, err = os.Create(mcPrm.fOutName); err != nil {
 		return err
 	}
 	if mcPrm.fPltName != "" {
@@ -97,10 +105,10 @@ func newx(xold []float32, xT []float32, rand *rand.Rand, xDlta float32) {
 }
 func breaker() {}
 
-// plotPnt adds a point to the data to be plotted. At the start, we check
+// plotFval adds a point to the data to be plotted. At the start, we check
 // if we have to plot at all. This is done here, to make the main loop
 // below a  bit shorter.
-func plotPnt(n uint32, fTrial float64, plotx, ploty *[]float64, plotme bool) {
+func plotFval(n uint32, fTrial float64, plotx, ploty *[]float64, plotme bool) {
 	if !plotme {
 		return
 	}
@@ -108,6 +116,24 @@ func plotPnt(n uint32, fTrial float64, plotx, ploty *[]float64, plotme bool) {
 	*ploty = append(*ploty, float64(fTrial))
 }
 
+// nRunAdj will try to adjust the step size, given our history of accept/reject.
+func nRunAdj(mcPrm *mcPrm, runAcc float64, xDlta float32) float32 {
+	const step = "step"
+
+	if runAcc < accRateIdeal-0.01 { // acceptance rate too low
+		xDlta *= 0.9
+		if mcPrm.verbose {
+			fmt.Println(step, xDlta, "decrease")
+		}
+	} else if (xDlta < maxxDlta) && (runAcc > accRateIdeal+0.01) {
+		xDlta *= 1.1
+		if mcPrm.verbose {
+			fmt.Println(step, xDlta, "increase")
+		}
+	}
+	return xDlta
+}
+
 // doRun does a Monte Carlo run. Although single precision is fine for the
 // coordinates and function, we use double precision for the temperature.
 func doRun(mcPrm *mcPrm) error {
@@ -124,9 +150,6 @@ func doRun(mcPrm *mcPrm) error {
 	if cprm.xPlt != nil {
 		defer cprm.xPlt.Close()
 	}
-	const accRateIdeal = 0.05              // Arbitrary target of 5% acceptance
-	const nRunAccAdj = 200                 // every n steps, check acceptance rate
-	const maxxDlta = 2.                    // max step size
 	var nAcc int                           // Counter of number of accepted moves
 	x := make([]float32, len(mcPrm.xIni))  // current position
 	xT := make([]float32, len(mcPrm.xIni)) // trial position
@@ -138,7 +161,7 @@ func doRun(mcPrm *mcPrm) error {
 	nRunAcc := nRunAccAdj // Every nRunAccAdj, try adjusting the step size.
 	const runMult = 0.99
 	xDlta := mcPrm.xDlta // Adaptable step size
-	plotPnt(0, fOld, &cprm.plotx, &cprm.ploty, cprm.fplotme)
+	plotFval(0, fOld, &cprm.plotx, &cprm.ploty, cprm.fplotme)
 	for n := uint32(0); n < mcPrm.nStep; n++ {
 		var acc bool
 		nout--
@@ -152,26 +175,15 @@ func doRun(mcPrm *mcPrm) error {
 		}
 		nRunAcc--
 		if nRunAcc == 0 { // Do we want to try adjusting the step size ?
-			const step = "step"
-			if runAcc < accRateIdeal-0.01 { // acceptance rate too low
-				xDlta *= 0.9
-				if mcPrm.verbose {
-					fmt.Println(step, xDlta, "decrease")
-				}
-			} else if (xDlta < maxxDlta) && (runAcc > accRateIdeal+0.01) {
-				xDlta *= 1.1
-				if mcPrm.verbose {
-					fmt.Println(step, xDlta, "increase")
-				}
-			}
-			nRunAcc = nRunAccAdj
+			xDlta = nRunAdj(mcPrm, runAcc, xDlta) // mucking about here
+			nRunAcc = nRunAccAdj                  // Reset the counter
 		}
 		newx(x, xT, cprm.rand, xDlta)
 		fTrial := ackley.Ackley(xT)
 
 		if fOld < fTrial {
-			r := cprm.rand.Float64()
-			delta := fTrial - fOld
+			r := cprm.rand.Float64() // Make the decision as to whether to
+			delta := fTrial - fOld   // accept or reject the trial
 			t := math.Exp(-delta / tmprtr)
 			if r < t {
 				acc = true
@@ -184,7 +196,7 @@ func doRun(mcPrm *mcPrm) error {
 			runAcc = runMult*runAcc + (1.0 - runMult)
 			copy(x, xT)
 			fOld = fTrial
-			plotPnt(n+1, fTrial, &cprm.plotx, &cprm.ploty, cprm.fplotme)
+			plotFval(n+1, fTrial, &cprm.plotx, &cprm.ploty, cprm.fplotme)
 		} else { // update the running estimate of acceptance
 			runAcc = runMult * runAcc
 		}
diff --git a/ackwork/rdprm.go b/ackwork/rdprm.go
index 74dafbc..02a62f1 100644
--- a/ackwork/rdprm.go
+++ b/ackwork/rdprm.go
@@ -82,9 +82,9 @@ func digest(prmMap map[string]string, mcPrm *mcPrm) error {
 	mcPrm.nRun = getu(prmMap["n_run"])
 	mcPrm.nOutput = getu(prmMap["n_output"])
 	mcPrm.xIni = getx(prmMap["x_ini"])
-	mcPrm.fOutName = prmMap["fOutName"]
-	mcPrm.fPltName = prmMap["fPltName"]
-	mcPrm.xPltName = prmMap["xPltName"]
+	mcPrm.fOutName = prmMap["foutname"]
+	mcPrm.fPltName = prmMap["fpltname"]
+	mcPrm.xPltName = prmMap["xpltname"]
 	seed = int64(getu(prmMap["seed"]))
 	if err != nil { // Only returns the first error encountered
 		return err
-- 
GitLab