From b471b01c3e74ebb57532ac3d6bcabcbc7297ba08 Mon Sep 17 00:00:00 2001
From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de>
Date: Thu, 10 Mar 2022 11:01:48 +0100
Subject: [PATCH] Removed dummy variable from input. Added window resize after
 first calculation. Do not collect best values if we are simulating at a
 constant temperature.

---
 examples/example2       |  4 ++--
 mc_work/dorun.go        | 14 ++++++--------
 mc_work/mc_work.go      |  1 -
 mc_work/mc_work_test.go |  2 +-
 mc_work/plot.go         | 16 +++++++++-------
 mc_work/rdprm.go        |  4 ----
 ui/output_tab.go        | 19 ++++++++-----------
 7 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/examples/example2 b/examples/example2
index 9824ead..61b77e6 100644
--- a/examples/example2
+++ b/examples/example2
@@ -1,6 +1,6 @@
 # This one is a constant temperature run
-ini_temp 0.08
-final_temp 0.08
+ini_temp 0.1
+final_temp 0.1
 n_step 100000
 x_ini 4,4
 x_delta 0.5
diff --git a/mc_work/dorun.go b/mc_work/dorun.go
index 55e1104..d607274 100644
--- a/mc_work/dorun.go
+++ b/mc_work/dorun.go
@@ -67,9 +67,6 @@ func isNotSane(mcPrm *McPrm) error {
 // setupRun does things like get the cooling rate, seed the random numbers.
 func setupRun(mcPrm *McPrm, cprm *cprm) error {
 	var err error
-	if mcPrm.dummy {
-		return nil
-	}
 	cprm.rand = rand.New(rand.NewSource(int64(getSeed())))
 
 	if mcPrm.IniTmp != mcPrm.FnlTmp { // cooling or constant temperature ?
@@ -177,10 +174,12 @@ func saveBest(x []float32, fTrial float64, n int) {
 }
 
 // saveStep is called when we accept a change. It writes or saves for
-// later plotting. The plan, every time we append values, we have to do it twice
+// later plotting. Every time we append values, we have to do it twice
 // so we get a proper stepped appearance.
 func saveStep(cprm *cprm, n int, tmprtr float64, x []float32, fTrial float64) {
-	saveBest(x, fTrial, n)
+	if cprm.coolme { // Only keep the best values found if we are annealing
+		saveBest(x, fTrial, n)
+	}
 	fprev := fTrial
 	xprev := x
 	if n != 0 {
@@ -305,9 +304,8 @@ func DoRun(mcPrm *McPrm) (MCresult, error) {
 
 	defer fmt.Println("n accepted:", nAcc, "of", mcPrm.NStep)
 	if bestX != nil {
-		defer fmt.Printf("Best function value: %.2f at %.2v at step %d\n", bestfval, bestX, bestN)
-	} else {
-		defer fmt.Println("bestX was never initialised")
+		s := "Best function value: %.2f at %.2v at step %d\n"
+		defer fmt.Printf(s, bestfval, bestX, bestN)
 	}
 	if err := plotfWrt(&cprm); err != nil {
 		return broken, err
diff --git a/mc_work/mc_work.go b/mc_work/mc_work.go
index f53335d..7d79c2e 100644
--- a/mc_work/mc_work.go
+++ b/mc_work/mc_work.go
@@ -17,7 +17,6 @@ type McPrm struct {
 	xPltName       string    // where we plot x trajectories to
 	AdaptStep      bool      // Adaptive step sizes
 	verbose        bool
-	dummy          bool // for testing. If set, do not do a run
 }
 
 // For random numbers. It is not in the main structure, since, if one ever writes
diff --git a/mc_work/mc_work_test.go b/mc_work/mc_work_test.go
index 50d0d46..ad12041 100644
--- a/mc_work/mc_work_test.go
+++ b/mc_work/mc_work_test.go
@@ -58,7 +58,7 @@ n_step 10000`, "s1d"},
 ini_temp 0.02
 final_temp 0.001
 x_ini 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-n_step 1000000
+n_step 100
 x_delta 1`, "s16d"},
 	{`
 ini_temp 1
diff --git a/mc_work/plot.go b/mc_work/plot.go
index 4f20ee4..d9cf7de 100644
--- a/mc_work/plot.go
+++ b/mc_work/plot.go
@@ -1,5 +1,5 @@
 // 31 Dec 2021
-// This is for plotting. For the moment, this is in the ackwork package,
+// For plotting. For the moment, this is in the mc_work package,
 // but maybe it should be in its own. It definitely goes in its own file, since
 // it is tied to one of the chart packages I have tried out.
 // What I have learnt about the go-chart package...
@@ -9,9 +9,12 @@
 //    it to work by: Make a child type from continuousRange. For this type,
 //    define the GetTicks function. go-chart then calls this function, at
 //    apparently the right place, and the tick marks come out nicely.
-// We can make two plots - one for the function value+temperature and one for
+//  - The package puts the main axis on the right and secondary on the left. Yuk
+//  - It makes a mess of the scaling on the secondary axis if you do not have
+//    a primary axis. This leads to some of the copying and contortions below.
+// We make two plots - one for the function value+temperature and one for
 // the trajectory of coordinates. We want them to have the same horizontal scale.
-// The plot with the temperature has two axes, so the plot package wants to scale
+// The plot with the temperature has two axes, so the plot package wants to size
 // the X-axis differently. The solution is that we draw the temperature on both
 // plots, but set all the style attributes to be invisible when we plot the
 // X trajectories.
@@ -157,11 +160,10 @@ func plotxWrt(cprm *cprm, ndim int) error {
 		return nil
 	}
 	graph := plotbase(cprm)
-	type f64 []float64
 	len_used := len(cprm.plotnstp)
-	xdata := make([]f64, ndim)
-	for i := 0; i < ndim; i++ {
-		xdata[i] = make([]float64, len_used)
+	xdata := make([][]float64, ndim)
+	for i := 0; i < ndim; i++ { // Copies, but also does the type promotion
+		xdata[i] = make([]float64, len_used) // to double prec for go-chart
 	}
 	var n int
 	for i := 0; i < len_used; i++ {
diff --git a/mc_work/rdprm.go b/mc_work/rdprm.go
index 6a8dc42..b616e4e 100644
--- a/mc_work/rdprm.go
+++ b/mc_work/rdprm.go
@@ -31,7 +31,6 @@ var cmdDflt = []struct {
 	{"xpltname", ""},
 	{"adaptstep", ""},
 	{"verbose", ""},
-	{"dummy", ""},
 }
 
 // digest digests the map, fills out our structure and sets the seed.
@@ -92,9 +91,6 @@ func digest(prmMap map[string]string, mcPrm *McPrm) error {
 	if prmMap["adaptstep"] != "" {
 		mcPrm.AdaptStep = true
 	}
-	if prmMap["dummy"] != "" {
-		mcPrm.dummy = true
-	}
 	return nil
 }
 
diff --git a/ui/output_tab.go b/ui/output_tab.go
index e7e17f4..44a1620 100644
--- a/ui/output_tab.go
+++ b/ui/output_tab.go
@@ -28,10 +28,13 @@ import (
 
 // runStatTxt should summarise some of the statistics
 func runStatTxt(rslt *mcwork.MCresult) fyne.Widget {
-	t1 := fmt.Sprintf("Num steps %d\nNum accepted %d\nacceptance rate %.1f %%\n",
+	s := fmt.Sprintf("Num steps %d\nNum accepted %d\nacceptance rate %.1f %%",
 		rslt.NStep, rslt.NAcc, (float32(rslt.NAcc)/float32(rslt.NStep))*100.)
-	t2 := fmt.Sprintf("best function value: %.2f\nat %.1g", rslt.Bestfval, rslt.BestX)
-	r := widget.NewLabel(t1 + t2)
+	if rslt.BestX != nil {
+		s += fmt.Sprintf("\nbest function value: %.2f\nat %.1g",
+			rslt.Bestfval, rslt.BestX)
+	}
+	r := widget.NewLabel(s)
 	return r
 }
 
@@ -81,13 +84,6 @@ var leftText = `Stretch window and play with the divider to make plots bigger.
 Clicking on a button below will let one save the plot of the cost function or the
 actual X values given to the function`
 
-// This spacer is the simplest way to stick a bit of room in the stucture
-// below. We cheat a bit in that the Hide() is just a noop.
-type spacer struct{ widget.Separator }
-
-func (spacer) Hide()              {}
-func (spacer) MinSize() fyne.Size { return fyne.Size{Width: 1, Height: 2} }
-
 // leftbar sets up the buttons on the left
 func leftbar(win fyne.Window, fdata, xdata []byte) *fyne.Container {
 	wrtFdata := func() { innerWrite(fdata, win) }
@@ -98,7 +94,7 @@ func leftbar(win fyne.Window, fdata, xdata []byte) *fyne.Container {
 	infobox := widget.NewLabel(leftText)
 	infobox.Alignment = fyne.TextAlignLeading
 	infobox.Wrapping = fyne.TextWrapWord
-	s := &spacer{}
+	s :=  &widget.Separator{}
 	return container.NewVBox(infobox, s, fdataBtn, s, xdataBtn)
 }
 
@@ -149,6 +145,7 @@ func showResultsTab(cntr *fyne.Container, win fyne.Window, rslt mcwork.MCresult)
 	split := container.NewHSplit(left, right)
 	split.SetOffset(0.01)
 	cntr.Add(split)
+	win.Resize(cntr.Size()) // only necessary on first call
 }
 
 // outputTab is run as a background process. After showing the initial
-- 
GitLab