Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "trace_activations" option to turn on detailed info if available #160

Merged
merged 1 commit into from
Jun 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions actr/actr.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,37 @@ package actr
import (
"github.com/asmaloney/gactar/actr/buffer"
"github.com/asmaloney/gactar/actr/modules"
"github.com/asmaloney/gactar/actr/params"
"github.com/asmaloney/gactar/util/container"
)

type options struct {
// "log_level": one of 'min', 'info', or 'detail'
LogLevel ACTRLogLevel

// "trace_activations": output detailed info about activations
TraceActivations bool
}

// Model represents a basic ACT-R model.
// This is used as input to a Framework where it can be run or output to a file.
// (This is incomplete w.r.t. all of ACT-R's capabilities.)
type Model struct {
Name string
Description string
Authors []string
Examples []*Pattern
Chunks []*Chunk
Modules []modules.ModuleInterface
Memory *modules.DeclarativeMemory // memory is always present
Goal *modules.Goal // goal is always present
Procedural *modules.Procedural // procedural is always present
Name string
Description string
Authors []string
Examples []*Pattern

Modules []modules.ModuleInterface
Memory *modules.DeclarativeMemory // memory is always present
Goal *modules.Goal // goal is always present
Procedural *modules.Procedural // procedural is always present
Chunks []*Chunk

Initializers []*Initializer
Productions []*Production
LogLevel ACTRLogLevel

options
}

type Initializer struct {
Expand Down Expand Up @@ -137,3 +150,28 @@ func (model Model) LookupBuffer(bufferName string) buffer.BufferInterface {

return nil
}

func (model *Model) SetParam(param *params.Param) (options []string, err params.ParamError) {
value := param.Value

switch param.Key {
case "log_level":
if (value.Str == nil) || !ValidLogLevel(*value.Str) {
return ACTRLoggingLevels, params.InvalidOption
}

model.LogLevel = ACTRLogLevel(*value.Str)

case "trace_activations":
if (value.ID == nil) || !container.Contains(*value.ID, params.Boolean) {
return params.Boolean, params.InvalidOption
}

model.TraceActivations = params.BooleanStrToBool(*value.ID)

default:
return []string{}, params.UnrecognizedParam
}

return
}
11 changes: 11 additions & 0 deletions actr/params/params.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package params

var Boolean = []string{
"true",
"false",
}

// Value mimics amod.fieldValue but without tokens.
type Value struct {
ID *string
Expand All @@ -19,5 +24,11 @@ const (
NumberRequired
NumberMustBePositive

InvalidOption

UnrecognizedParam
)

func BooleanStrToBool(b string) bool {
return b == "true"
}
54 changes: 36 additions & 18 deletions amod/amod.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,29 @@ func addGACTAR(model *actr.Model, log *issueLog, list []*field) {
for _, field := range list {
value := field.Value

switch field.Key {
case "log_level":
if (value.Str == nil) || !actr.ValidLogLevel(*value.Str) {
log.errorT(value.Tokens, "log_level '%s' must be 'min', 'info', 'or 'detail'", value.String())
options, err := model.SetParam(&params.Param{
Key: field.Key,
Value: params.Value{
ID: value.ID,
Str: value.Str,
Number: value.Number,
},
})

if err != params.NoError {
switch err {
case params.InvalidOption:
log.errorT(value.Tokens, "%s ('%s') must be one of %q", field.Key, value.String(), strings.Join(options, ", "))
continue
}

model.LogLevel = actr.ACTRLogLevel(*value.Str)
case params.UnrecognizedParam:
log.errorTR(field.Tokens, 0, 1, "unrecognized field in gactar section: '%s'", field.Key)
continue

default:
log.errorTR(field.Tokens, 0, 1, "unrecognized field in gactar section: '%s'", field.Key)
default:
log.errorT(field.Tokens, "internal: unhandled error (%d) in gactar section: '%s'", err, field.Key)
continue
}
}
}
}
Expand Down Expand Up @@ -249,18 +261,24 @@ func setModuleParams(module modules.ModuleInterface, log *issueLog, fields []*fi
},
})

switch err {
case params.NumberRequired:
log.errorT(value.Tokens, "%s %s '%s' must be a number", moduleName, field.Key, value.String())
continue
if err != params.NoError {
switch err {
case params.NumberRequired:
log.errorT(value.Tokens, "%s %s '%s' must be a number", moduleName, field.Key, value.String())
continue

case params.NumberMustBePositive:
log.errorT(value.Tokens, "%s %s '%s' must be a positive number", moduleName, field.Key, value.String())
continue
case params.NumberMustBePositive:
log.errorT(value.Tokens, "%s %s '%s' must be a positive number", moduleName, field.Key, value.String())
continue

case params.UnrecognizedParam:
log.errorTR(field.Tokens, 0, 1, "unrecognized field '%s' in %s config", field.Key, moduleName)
continue
case params.UnrecognizedParam:
log.errorTR(field.Tokens, 0, 1, "unrecognized field '%s' in %s config", field.Key, moduleName)
continue

default:
log.errorT(field.Tokens, "internal: unhandled error (%d) in %s config: '%s'", err, moduleName, field.Key)
continue
}
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions amod/amod_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,44 @@ func Example_gactarUnrecognizedField() {
// ERROR: unrecognized field in gactar section: 'foo' (line 5, col 10)
}

func Example_gactarUnrecognizedLogLevel() {
generateToStdout(`
==model==
name: Test
==config==
gactar { log_level: bar }
==init==
==productions==`)

// Output:
// ERROR: log_level ('bar') must be one of "min, info, detail" (line 5, col 21)
}

func Example_gactarTraceActivations() {
generateToStdout(`
==model==
name: Test
==config==
gactar { trace_activations: true }
==init==
==productions==`)

// Output:
}

func Example_gactarTraceActivationsNonBool() {
generateToStdout(`
==model==
name: Test
==config==
gactar { trace_activations: 6.0 }
==init==
==productions==`)

// Output:
// ERROR: trace_activations ('6.000000') must be one of "true, false" (line 5, col 29)
}

func Example_chunkReservedName() {
generateToStdout(`
==model==
Expand Down
9 changes: 7 additions & 2 deletions examples/addition.amod
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ examples {

==config==

// Turn on logging by setting 'log_level' to 'min', 'info' (default), or 'detail'
gactar { log_level: 'detail' }
gactar {
// Logging level can be 'min', 'info' (default), or 'detail'
log_level: 'detail'

// Show detailed information about activations (if available)
trace_activations: true
}

// Declare chunks and their layouts
chunks {
Expand Down
9 changes: 7 additions & 2 deletions examples/addition2.amod
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ examples {

==config==

// Turn on logging by setting 'log_level' to 'min', 'info' (default), or 'detail'
gactar { log_level: 'detail' }
gactar {
// Logging level can be 'min', 'info' (default), or 'detail'
log_level: 'detail'

// Show detailed information about activations (if available)
trace_activations: true
}

// Declare chunks and their layouts
chunks {
Expand Down
9 changes: 7 additions & 2 deletions examples/count.amod
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ examples {

==config==

// Turn on logging by setting 'log_level' to 'min', 'info' (default), or 'detail'
gactar { log_level: 'detail' }
gactar {
// Logging level can be 'min', 'info' (default), or 'detail'
log_level: 'detail'

// Show detailed information about activations (if available)
trace_activations: false
}

// Declare chunks and their layouts
chunks {
Expand Down
9 changes: 7 additions & 2 deletions examples/semantic.amod
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ examples {

==config==

// Turn on logging by setting 'log_level' to 'min', 'info' (default), or 'detail'
gactar { log_level: 'detail' }
gactar {
// Logging level can be 'min', 'info' (default), or 'detail'
log_level: 'detail'

// Show detailed information about activations (if available)
trace_activations: true
}

// Declare chunks and their layouts
chunks {
Expand Down
9 changes: 7 additions & 2 deletions examples/topdown_parser.amod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ description: "This model is based on pyactr's ch3_topdown_parser."

==config==

// Turn on logging by setting 'log_level' to 'min', 'info' (default), or 'detail'
gactar { log_level: 'info' }
gactar {
// Logging level can be 'min', 'info' (default), or 'detail'
log_level: 'info'

// Show detailed information about activations (if available)
trace_activations: true
}

modules {
// Require the imaginal buffer and set its delay
Expand Down
4 changes: 4 additions & 0 deletions framework/pyactr/pyactr.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ func (p *PyACTR) WriteModel(path string, initialBuffers framework.InitialBuffers
p.Writeln(" rule_firing=%s,", numbers.Float64Str(*procedural.DefaultActionTime))
}

if p.model.TraceActivations {
p.Writeln(" activation_trace=True,")
}

p.Writeln(")")

if p.model.HasPrintStatement() {
Expand Down
4 changes: 4 additions & 0 deletions framework/vanilla_actr/vanilla_actr.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ func (v *VanillaACTR) WriteModel(path string, initialBuffers framework.InitialBu
v.Writeln("\t:trace-detail high")
}

if v.model.TraceActivations {
v.Writeln("\t:act t")
}

imaginal := v.model.ImaginalModule()
if imaginal != nil {
v.Writeln("\t:do-not-harvest imaginal")
Expand Down