looper

package
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2022 License: BSD-3-Clause Imports: 6 Imported by: 35

README

Looper: A flexible steppable control hierarchy

Looper implements a fully generic looping control system with extensible functionality at each level of the loop, with logic that supports reentrant stepping so each time it is Run it advances at any specified step size, with results that are identical to running.

This steppability constraint requires that no code is run at the start of a loop, which is equivalent to a do..while loop with no initialization condition:

do {
    Main()
} while !Stop()
End()

The Loop object has these three function lists: Main(), Stop(), End() where function closures can be added to perform any relevant functionality.

In Go syntax, including the running of sub-loops under a given level, this would be:

for {
   for { <subloops here> } // drills down levels for each subloop
   Main()                  // Main is called after subloops -- increment counters!
   if Stop() {
       break
   }
}
End()                      // Reset counters here so next pass starts over

To make this work, an initialization function must be run prior to starting, which puts the system in a ready-to-run state. The End() function at each level must likewise ensure that it is ready to start again properly the next time through.

The envlp Env is designed to work in concert with the looper control, where the Env holds counter values, and looper automatically increments and uses these counters to stop looping at a given level. Each Stack of loops is associated with a given etime.Mode, corresponding to that of the Env.

Algorithm and Sim Integration

Specific algorithms use AddLevels to add inner, lower levels of loops to implement specific algorithm code (typically Phase and Cycle). Leabra and Axon use the Time struct as a context for holding the relevant counters and mode, which is then accessed directly in the callback functions as needed.

In cases where something must be done prior to looping through cycles (e.g., ApplyInputs and new phase startup methods), trigger it on the first cycle, before calling other functions, using a provided AddCycle0 function.

Concrete Example of Looping Logic

The stack_test.go output shows the logic of the looping functions:

Here's the trace of a Run with 2 Run iterations, 3 Epoch iterations, and 3 Trials per epoch:

		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 1
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 2
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 3
	Epoch Stop: 3
	Epoch End: 0
Run Main: 1
		Trial Main: 1
   .... (repeat of above)
	Epoch Main: 3
	Epoch Stop: 3
	Epoch End: 0
Run Main: 2
Run Stop: 2
Run End: 0

Here is stepping 1 Trial at a time:

##############
Step Trial 1
		Trial Main: 1

##############
Step Trial 1
		Trial Main: 2

##############
Step Trial 1
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 1

##############
Step Trial 1
		Trial Main: 1

##############
Step Trial 2
		Trial Main: 1
		Trial Main: 2

Here is stepping 2 Trials at a time:

##############
Step Trial 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 1
		Trial Main: 1

##############
Step Trial 2
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 2

##############
Step Trial 2
		Trial Main: 1
		Trial Main: 2

And here's stepping 1 Epoch at a time:

##############
Step Epoch 1
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 1

##############
Step Epoch 1
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 2

##############
Step Epoch 1
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 3
	Epoch Stop: 3
	Epoch End: 0
Run Main: 1

##############
Step Epoch 1
		Trial Main: 1
		Trial Main: 2
		Trial Main: 3
		Trial Stop: 3
		Trial End: 0
	Epoch Main: 1

Documentation

Index

Constants

This section is empty.

Variables

View Source
var IndentSize = 4

IndentSize is number of spaces to indent for output

Functions

This section is empty.

Types

type BoolFuncs

type BoolFuncs []*NamedBoolFunc

BoolFuncs is a list of named plain functions

func (*BoolFuncs) Add

func (fs *BoolFuncs) Add(nm string, f func() bool)

Add adds a function to the end of the list

func (*BoolFuncs) Delete

func (fs *BoolFuncs) Delete(nm string) error

Delete deletes function of given name

func (*BoolFuncs) FindName

func (fs *BoolFuncs) FindName(nm string) (int, error)

FindName finds index of function by name, returns not found err message if not found

func (*BoolFuncs) InsertAfter

func (fs *BoolFuncs) InsertAfter(after, nm string, f func() bool) error

InsertAfter inserts function after other function of given name

func (*BoolFuncs) InsertAt

func (fs *BoolFuncs) InsertAt(i int, nm string, f func() bool)

InsertAt inserts function at given index

func (*BoolFuncs) InsertBefore

func (fs *BoolFuncs) InsertBefore(before, nm string, f func() bool) error

InsertBefore inserts function before other function of given name

func (*BoolFuncs) Names

func (fs *BoolFuncs) Names() []string

Names returns the list of function names

func (*BoolFuncs) Prepend

func (fs *BoolFuncs) Prepend(nm string, f func() bool)

Prepend adds a function to the start of the list

func (*BoolFuncs) Replace

func (fs *BoolFuncs) Replace(nm string, f func() bool) error

Replace replaces function with other function of given name

func (*BoolFuncs) Run

func (fs *BoolFuncs) Run() bool

Run runs the list of functions in order, returning true as soon as any of the functions return true, else false

func (*BoolFuncs) RunTrace

func (fs *BoolFuncs) RunTrace(level int) bool

RunTrace runs the list of functions in order, returning true as soon as any of the functions return true, else false. Prints a trace before each as they run

func (*BoolFuncs) String

func (fs *BoolFuncs) String() string

String returns the list of function names

type Funcs

type Funcs []*NamedFunc

Funcs is a list of named plain functions

func (*Funcs) Add

func (fs *Funcs) Add(nm string, f func())

Add adds a function to the end of the list

func (*Funcs) Delete

func (fs *Funcs) Delete(nm string) error

Delete deletes function of given name

func (*Funcs) FindName

func (fs *Funcs) FindName(nm string) (int, error)

FindName finds index of function by name, returns not found err message if not found

func (*Funcs) InsertAfter

func (fs *Funcs) InsertAfter(after, nm string, f func()) error

InsertAfter inserts function after other function of given name

func (*Funcs) InsertAt

func (fs *Funcs) InsertAt(i int, nm string, f func())

InsertAt inserts function at given index

func (*Funcs) InsertBefore

func (fs *Funcs) InsertBefore(before, nm string, f func()) error

InsertBefore inserts function before other function of given name

func (*Funcs) Names

func (fs *Funcs) Names() []string

Names returns the list of function names

func (*Funcs) Prepend

func (fs *Funcs) Prepend(nm string, f func())

Prepend adds a function to the start of the list

func (*Funcs) Replace

func (fs *Funcs) Replace(nm string, f func()) error

Replace replaces function with other function of given name

func (*Funcs) Run

func (fs *Funcs) Run()

Run runs the list of functions in order

func (*Funcs) RunTrace

func (fs *Funcs) RunTrace(level int)

RunTrace runs the list of functions in order, printing a trace before each as they run

func (*Funcs) String

func (fs *Funcs) String() string

String returns the list of function names

type Loop

type Loop struct {
	Stack *Stack         `desc:"stack that owns this loop"`
	Scope etime.ScopeKey `desc:"scope level of this loop"`
	Main  Funcs          `` /* 333-byte string literal not displayed */
	Stop  BoolFuncs      `desc:"functions that cause the loop to stop -- if any return true, it stops"`
	End   Funcs          `` /* 204-byte string literal not displayed */
}

Loop represents one level of looping, with arbitrary functions called at 3 different points in the loop, corresponding to a do..while loop logic, with no initialization, which is necessary to ensure reentrant steppability. In Go, the logic looks like this:

for {
   for { <subloops here> } // drills down levels for each subloop
   Main()                  // Main is called after subloops -- increment counters!
   if Stop() {
       break
   }
}

End() // Reset counters here so next pass starts over

func NewLoop

func NewLoop(sc etime.ScopeKey, st *Stack) *Loop

func (*Loop) AddEnvFuncs

func (lp *Loop) AddEnvFuncs()

AddEnvFuncs adds Env: funcs for loop

func (*Loop) EnvCtr

func (lp *Loop) EnvCtr() *envlp.Ctr

EnvCtr returns the counter corresponding to this loop's scope, nil if not found

func (*Loop) EnvIncr

func (lp *Loop) EnvIncr()

EnvIncr is the Env:Incr Main function

func (*Loop) EnvIsOverMax

func (lp *Loop) EnvIsOverMax() bool

EnvIsOverMax is the Env:IsOverMax Stop function

func (*Loop) EnvResetIfOverMax

func (lp *Loop) EnvResetIfOverMax()

EnvResetIfOverMax is the Env:ResetIfOverMax End function

func (*Loop) EnvStep

func (lp *Loop) EnvStep()

EnvStep is the Env:Step Main function

func (*Loop) StageString

func (lp *Loop) StageString(stage string, level int) string

StageString returns a string for given stage of loop, indented to level

type NamedBoolFunc

type NamedBoolFunc struct {
	Name string      `` /* 165-byte string literal not displayed */
	Func func() bool `desc:"function -- note that you can pass a method to a type as well as a closure here"`
}

NamedBoolFunc is a named function returning bool

type NamedFunc

type NamedFunc struct {
	Name string `` /* 165-byte string literal not displayed */
	Func func() `desc:"function -- note that you can pass a method to a type as well as a closure here"`
}

NamedFunc is a named function

type Set

type Set struct {
	Stacks   map[string]*Stack `desc:"the collection of loop stacks -- key is typically etime.Mode"`
	StopFlag bool              `desc:"if true, running will stop at soonest opportunity"`
}

Set contains a set of interconnected loop Stacks (e.g., Train, Test, etc)

func NewSet

func NewSet() *Set

func StdTrainTest

func StdTrainTest() *Set

StdTrainTest adds standard Train: Run, Epoch, Trial, Test: Epoch, Trial

func (*Set) AddLevels

func (set *Set) AddLevels(times ...etime.Times)

AddLevels adds given levels to all Stacks. For algorithms to add mechanism inner loops.

func (*Set) AddStack

func (set *Set) AddStack(st *Stack)

func (*Set) Init

func (set *Set) Init(mode etime.Modes)

Init initializes Stack defined by given mode

func (*Set) InitAll

func (set *Set) InitAll()

InitAll runs Init on all Stacks

func (*Set) InitMap

func (set *Set) InitMap()

func (*Set) InitName

func (set *Set) InitName(name string) (*Stack, error)

InitName initializes Stack of given name

func (*Set) Run

func (set *Set) Run(mode etime.Modes)

Run runs Stack defined by given mode

func (*Set) RunName

func (set *Set) RunName(name string) (*Stack, error)

RunName runs Stack of given name

func (*Set) Stack

func (set *Set) Stack(mode etime.Modes) *Stack

Stack returns Stack defined by given mode

func (*Set) StackNameTry

func (set *Set) StackNameTry(name string) (*Stack, error)

StackNameTry returns Stack based on name key, returning err if not found

func (*Set) StackTry

func (set *Set) StackTry(mode etime.Modes) (*Stack, error)

StackTry returns Stack defined by given mode, returning err if not found

func (*Set) Step

func (set *Set) Step(mode etime.Modes, step etime.Times, n int) (*Stack, error)

Step Steps Stack defined by given mode, at given step level, Stepping n times (n = 0 turns off stepping)

func (*Set) StepName

func (set *Set) StepName(name string, step string, n int) (*Stack, error)

StepName Steps Stack of given name, at given step time level, Stepping n times (n = 0 turns off stepping)

type Stack

type Stack struct {
	Mode  string                   `desc:"eval mode for this stack"`
	Env   envlp.Env                `desc:"environment used by default for loop iteration, stopping, if set"`
	Order []etime.ScopeKey         `desc:"ordered list of the loops, from outer-most (highest) to inner-most (lowest)"`
	Loops map[etime.ScopeKey]*Loop `desc:"the loops by scope"`
	Ctxt  map[string]interface{}   `` /* 135-byte string literal not displayed */
	Step  Step                     `desc:"stepping state"`
	Set   *Set                     `desc:"Set of Stacks that we belong to"`
}

Stack contains one stack of nested loops, associated with one evaluation Mode, and, optionally, envlp.Env. If the Env is set, then counters at corresponding Scope levels are incremented, checked for stopping, and reset to control looping.

func NewStack

func NewStack(mode string, times ...etime.Times) *Stack

NewStack returns new stack for given mode and times

func NewStackEnv

func NewStackEnv(ev envlp.Env) *Stack

NewStackEnv returns new stack with loops matching those in the given environment. Adds standard Env counter funcs to manage updating of counters, with Step at the lowest level.

func NewStackScope

func NewStackScope(scopes ...etime.ScopeKey) *Stack

NewStack returns new stack for given list of scopes

func (*Stack) AddEnvFuncs

func (st *Stack) AddEnvFuncs()

AddEnvFuncs adds Env: funcs for Stack

func (*Stack) AddLevels

func (st *Stack) AddLevels(times ...etime.Times)

AddLevels adds given levels to stack. For algorithms to add mechanism inner loops.

func (*Stack) DocString

func (st *Stack) DocString() string

DocString returns an indented summary of the loops and functions in the stack

func (*Stack) EndRun

func (st *Stack) EndRun(lp *Loop, level int)

EndRun runs End functions on loop, and then resets Env counter at same Scope level (if Env)

func (*Stack) Init

func (st *Stack) Init()

Init runs End functions for all levels in the Stack, to reset state for a fresh Run.

func (*Stack) Level

func (st *Stack) Level(lev int) *Loop

Level returns loop for given level in order

func (*Stack) Loop

func (st *Stack) Loop(time etime.Times) *Loop

Loop returns loop for given time

func (*Stack) MainRun

func (st *Stack) MainRun(lp *Loop, level int)

MainRun runs Main functions on loop

func (*Stack) Run

func (st *Stack) Run()

Run runs the stack of looping functions. It will stop at any existing Step settings -- call StepClear to clear those.

func (*Stack) Scope

func (st *Stack) Scope() etime.ScopeKey

Scope returns the top-level scope for this stack

func (*Stack) SetStep

func (st *Stack) SetStep(time etime.Times, n int)

SetStep sets the stepping scope and n -- 0 = no stepping resets counter.

func (*Stack) SetStepTime

func (st *Stack) SetStepTime(time string, n int)

SetStepTime sets the stepping time and n -- 0 = no stepping resets counter.

func (*Stack) StepCheck

func (st *Stack) StepCheck(lp *Loop, level int) bool

StepCheck checks if it is time to stop based on stepping

func (*Stack) StepClear

func (st *Stack) StepClear()

StepClear resets stepping

func (*Stack) StepIsScope

func (st *Stack) StepIsScope(lp *Loop) bool

StepIsScope returns true if stepping is happening at scope level of given loop

func (*Stack) StopCheck

func (st *Stack) StopCheck(lp *Loop, level int) bool

StopCheck checks if it is time to stop, based on loop Stop functions.

func (*Stack) Times

func (st *Stack) Times() []string

Times returns a list of Times strings for loops

type Step

type Step struct {
	Time      string `desc:"stepping level, time string"`
	Default   string `desc:"default stepping level"`
	N         int    `desc:"number of times to iterate at StepScope level, no stepping if 0"`
	Cnt       int    `desc:"counter for number of times through loop"`
	LoopTrace bool   `desc:"if true, print out a trace of looping stages as they run"`
	FuncTrace bool   `desc:"if true, print out a trace of functions as they run -- implies LoopTrace"`
}

Step manages stepping state. Also trace flag

func (*Step) Clear

func (st *Step) Clear()

Clear resets stepping (sets N = 0)

func (*Step) IsScope

func (st *Step) IsScope(scope etime.ScopeKey) bool

IsScope checks if given scope is stepping scope

func (*Step) Set

func (st *Step) Set(time string, n int)

Set sets the stepping time and n -- 0 = no stepping resets counter.

func (*Step) StopCheck

func (st *Step) StopCheck(scope etime.ScopeKey) bool

StopCheck checks if it is time to stop for this scope returns true if so

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL