diff --git a/examples/choose/armaze/paradigms.go b/examples/choose/armaze/paradigms.go index 28964d98b..32a294143 100644 --- a/examples/choose/armaze/paradigms.go +++ b/examples/choose/armaze/paradigms.go @@ -36,15 +36,18 @@ func (ev *Env) ConfigGroupGoodBad() { ai := 0 for gi := 0; gi < 2; gi++ { - length := cfg.LengthRange.Min - eff := cfg.EffortRange.Min - mag := cfg.USMagRange.Max - prob := cfg.USProbRange.Max - if gi == 1 { + var eff, mag, prob float32 + var length int + if gi == 1 { // note: this is critical: if bad is at 0, it can randomly get stuck length = cfg.LengthRange.Max eff = cfg.EffortRange.Max mag = cfg.USMagRange.Min prob = cfg.USProbRange.Min + } else { // good case + length = cfg.LengthRange.Min + eff = cfg.EffortRange.Min + mag = cfg.USMagRange.Max + prob = cfg.USProbRange.Max } for ui := 0; ui < cfg.NUSs; ui++ { diff --git a/examples/choose/choose.go b/examples/choose/choose.go index 60cac81f6..fd2c8830a 100644 --- a/examples/choose/choose.go +++ b/examples/choose/choose.go @@ -691,6 +691,7 @@ func (ss *Sim) InitStats() { ss.Stats.SetInt("Di", 0) ss.Stats.SetFloat("PctCortex", 0) ss.Stats.SetFloat("Pos", 0) + ss.Stats.SetFloat("Arm", 0) ss.Stats.SetFloat("Dist", 0) ss.Stats.SetFloat("Drive", 0) ss.Stats.SetFloat("CS", 0) @@ -746,9 +747,9 @@ func (ss *Sim) StatCounters(di int) { ss.Stats.SetInt("Di", di) ss.Stats.SetInt("Cycle", int(ctx.Cycle)) ss.Stats.SetFloat32("PctCortex", ss.Config.Env.PctCortex) + ss.Stats.SetFloat32("Arm", float32(ev.Arm)) ss.Stats.SetFloat32("Pos", float32(ev.Pos)) ss.Stats.SetFloat32("Dist", float32(ev.Dist)) - ss.Stats.SetFloat32("Arm", float32(ev.Arm)) // ss.Stats.SetFloat32("Drive", float32(ev.Drive)) ss.Stats.SetFloat32("CS", float32(ev.CurCS())) ss.Stats.SetFloat32("US", float32(ev.USConsumed)) @@ -881,11 +882,13 @@ func (ss *Sim) GatedStats(di int) { ss.Stats.SetFloat32("GateBLAposExt", nan) ss.Stats.SetFloat32("GateBLAposAcqExt", nan) hasPos := rp.HasPosUS(ctx, diu) + armIsBest := ev.ArmIsBest(ev.Arm) + armIsBad := num.FromBool[float32](!armIsBest) if justGated { if hasPos { - ss.Stats.SetFloat32("BadUSGate", num.FromBool[float32](!ev.ArmIsBest(ev.Arm))) + ss.Stats.SetFloat32("BadUSGate", armIsBad) } else { - ss.Stats.SetFloat32("BadCSGate", num.FromBool[float32](!ev.ArmIsBest(ev.Arm))) + ss.Stats.SetFloat32("BadCSGate", armIsBad) vsgo := net.AxonLayerByName("VMtxGo") vsno := net.AxonLayerByName("VMtxNo") goact := ss.MaxPoolSpkMax(vsgo, diu) @@ -992,7 +995,7 @@ func (ss *Sim) ConfigLogs() { ss.Logs.AddStatStringItem(etime.AllModes, etime.AllTimes, "RunName") // ss.Logs.AddStatStringItem(etime.AllModes, etime.Trial, "TrialName") ss.Logs.AddStatFloatNoAggItem(etime.AllModes, etime.AllTimes, "PctCortex") - ss.Logs.AddStatFloatNoAggItem(etime.AllModes, etime.Trial, "Drive", "CS", "Pos", "Dist", "US") + ss.Logs.AddStatFloatNoAggItem(etime.AllModes, etime.Trial, "Drive", "CS", "Arm", "Pos", "Dist", "US") ss.Logs.AddStatStringItem(etime.AllModes, etime.Trial, "NetAction", "Instinct", "ActAction", "TraceState") ss.Logs.AddPerTrlMSec("PerTrlMSec", etime.Run, etime.Epoch, etime.Trial) diff --git a/examples/choose/configs/01_us_magnitude.toml b/examples/choose/configs/01_us_magnitude.toml index 3aaa8429a..ae96d6a79 100644 --- a/examples/choose/configs/01_us_magnitude.toml +++ b/examples/choose/configs/01_us_magnitude.toml @@ -2,6 +2,6 @@ NDrives = 3 Paradigm = "GroupGoodBad" -USMagRange.Min = 0.4 # 0.2 works +USMagRange.Min = 0.99 # 0.4 gives reasonable diff USMagRange.Max = 1 diff --git a/simscripts/30-Submit.cosh b/simscripts/30-Submit.cosh index 491a346f4..ed7cc2678 100644 --- a/simscripts/30-Submit.cosh +++ b/simscripts/30-Submit.cosh @@ -27,7 +27,7 @@ func WriteSBatchHeader(w io.Writer, jid string) { func WriteSBatchSetup(w io.Writer, jid string) { fmt.Fprintf(w, "#!/bin/bash -l\n") // -l = login session, sources your .bash_profile fmt.Fprint(w, "#SBATCH --output=job.setup.out\n") - // fmt.Fprint(w, "#SBATCH --error=job.%A.setup.err") + fmt.Fprint(w, "#SBATCH --error=job.setup.err\n") WriteSBatchHeader(w, jid) ////////////////////////////////////////////////////////// @@ -157,12 +157,64 @@ func FindGoMod(dir string) string { return "" } +// GoModulePath returns the overall module path for project +// in given directory, and the full module path to the current +// project, which is a subdirectory within the module. +func GoModulePath(dir string) (modpath, fullpath string) { + @0 + os.Chdir(dir) + cd {dir} + gg := cosh.SplitLines(`go mod graph`) + gg = strings.Fields(gg[0]) + modpath = gg[0] + + // strategy: go up the dir until the dir name matches the last element of modpath + dirsp := strings.Split(dir, "/") + n := len(dirsp) + for i := n-1; i >= 0; i-- { + d := dirsp[i] + if strings.HasSuffix(modpath, d) { + fullpath = filepath.Join(modpath, strings.Join(dirsp[i+1:], "/")) + break + } + } + return +} + +// CopyFilesToJob copies files with given extensions (none for all), +// from localSrc to localJob and remote hostJob (@1). +// Ensures directories are made in the job locations +func CopyFilesToJob(localSrc, localJob, hostJob string, exts ...string) { + @0 + mkdir -p {localJob} + cd {localJob} + @1 + cd + mkdir -p {hostJob} + cd {hostJob} + @0 + efls := dirs.ExtFilenames(localSrc, exts...) + for _, f := range efls { + sfn := filepath.Join(localSrc, f) + /bin/cp {sfn} {f} + scp {sfn} {"@1:"+f} + } +} + func NewJob(message, args string) { os.Chdir(br.DataRoot) jid := NextJobID() spath := ServerJobPath(jid) jpath := JobPath(jid) core.MessageSnackbar(br, "Submitting Job: " + jid) + + gomodDir := FindGoMod(br.StartDir) + modulePath, fullPath := GoModulePath(br.StartDir) + projPath := filepath.Join("emer", Config.Project) + + // fmt.Println("go.mod:", gomodDir, "\nmodule:", modulePath, "\nfull path:", fullPath, "\njob proj:", projPath) + + @0 // fmt.Println(jpath) os.MkdirAll(jpath, 0750) os.Chdir(jpath) @@ -170,66 +222,45 @@ func NewJob(message, args string) { cosh.WriteFile("job.args", args) cosh.WriteFile("job.submit", time.Now().Format(Config.TimeFormat)) cosh.WriteFile("job.status", "Submitted") + + // need to do sub-code first and update paths in copied files + codepaths := make([]string, len(Config.CodeDirs)) + for i, ed := range Config.CodeDirs { + @0 + loce := filepath.Join(br.StartDir, ed) + codepaths[i] = filepath.Join(fullPath, ed) + jpathe := filepath.Join(jpath, ed) + spathe := filepath.Join(spath, ed) + CopyFilesToJob(loce, jpathe, spathe, ".go") + } + // copy local files: @1 cd mkdir -p {spath} cd {spath} @0 cd {jpath} - fls := dirs.ExtFilenames(br.StartDir, ".go") - // fmt.Println("uploading files:") for _, f := range fls { - // fmt.Println(f) sfn := filepath.Join(br.StartDir, f) /bin/cp {sfn} {f} - scp {sfn} {"@1:"+f} + for i, ed := range Config.CodeDirs { + subpath := filepath.Join(projPath, ed) + // fmt.Println("replace in:", f, codepaths[i], "->", subpath) + cosh.ReplaceInFile(f, codepaths[i], subpath) + } + scp {f} {"@1:"+f} } for _, f := range Config.ExtraFiles { - // fmt.Println(f) sfn := filepath.Join(br.StartDir, f) /bin/cp {sfn} {f} scp {sfn} {"@1:"+f} } for _, ed := range Config.ExtraDirs { - @0 jpathe := filepath.Join(jpath, ed) spathe := filepath.Join(spath, ed) loce := filepath.Join(br.StartDir, ed) - mkdir -p {jpathe} - cd {jpathe} - @1 - cd - mkdir -p {spathe} - cd {spathe} - @0 - efls := dirs.ExtFilenames(loce) - for _, f := range efls { - // fmt.Println("extra dir file:", f) - sfn := filepath.Join(loce, f) - /bin/cp {sfn} {f} - scp {sfn} {"@1:"+f} - } - } - for _, ed := range Config.CodeDirs { - @0 - jpathe := filepath.Join(jpath, ed, "v2") // note: v2 required b/c axon/v2 - spathe := filepath.Join(spath, ed, "v2") - loce := filepath.Join(br.StartDir, ed) - mkdir -p {jpathe} - cd {jpathe} - @1 - cd - mkdir -p {spathe} - cd {spathe} - @0 - efls := dirs.ExtFilenames(loce, ".go") - for _, f := range efls { - // fmt.Println(f) - sfn := filepath.Join(loce, f) - /bin/cp {sfn} {f} - scp {sfn} {"@1:"+f} - } + CopyFilesToJob(loce, jpathe, spathe) } @1 cd @@ -237,8 +268,7 @@ func NewJob(message, args string) { @0 cd {jpath} - core.MessageSnackbar(br, "Job: " + jid + " files copied, now updating go.mod (slow)") - gomodDir := FindGoMod(br.StartDir) + core.MessageSnackbar(br, "Job: " + jid + " files copied") if gomodDir != "" { sfn := filepath.Join(gomodDir, "go.mod") // fmt.Println("go.mod dir:", gomodDir, sfn) @@ -246,24 +276,7 @@ func NewJob(message, args string) { sfn = filepath.Join(gomodDir, "go.sum") scp {sfn} "@1:go.sum" @1 - go mod edit -module {Config.Project} - for _, ed := range Config.CodeDirs { - ed2 := ed+"/v2" - cd {ed2} - cp ../../go.mod . - go mod edit -module {ed} - go mod tidy - @0 - scp "@1:go.mod" {ed2+"/go.mod"} - scp "@1:go.sum" {ed2+"/go.sum"} - @1 - cd ../../ - } - for _, ed := range Config.CodeDirs { - orig := "github.com/emer/axon/v2/examples/" + Config.Project + "/" + ed - repl := "./" + ed - go mod edit -replace {orig+"="+repl} - } + go mod edit -module {projPath} go mod tidy @0 scp "@1:go.mod" "go.mod" diff --git a/simscripts/config.cosh b/simscripts/config.cosh index 7fe9806dc..a5841b229 100644 --- a/simscripts/config.cosh +++ b/simscripts/config.cosh @@ -35,11 +35,11 @@ func (fp *FilterResults) Defaults() { type SubmitParams struct { // Message describing the simulation: // this is key id for what is special about this job - Message string `width:"100"` + Message string `width:"60"` // arguments to pass on the command line. // -nogui is already passed by default - Args string + Args string `width:"60"` } // JobParams are parameters for running the job