Skip to content

Commit 0ecace2

Browse files
committed
params: new param search and tweak
1 parent 26f9433 commit 0ecace2

File tree

7 files changed

+228
-427
lines changed

7 files changed

+228
-427
lines changed

params/apply.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ import (
1616
// using the Styler interface, and returns false if it does not. If it does apply,
1717
// then the Set function is called on the object.
1818
func (ps *Sel[T]) Apply(obj T) bool {
19-
if !ps.SelMatch(obj) {
19+
if !SelMatch(ps.Sel, obj) {
2020
return false
2121
}
2222
ps.Set(obj)
2323
return true
2424
}
2525

2626
// SelMatch returns true if Sel selector matches the target object properties.
27-
func (ps *Sel[T]) SelMatch(obj T) bool {
28-
if ps.Sel == "" {
27+
func SelMatch[T Styler](sel string, obj T) bool {
28+
if sel == "" {
2929
return true
3030
}
31-
if ps.Sel[0] == '.' { // class
32-
return ClassMatch(ps.Sel[1:], obj.StyleClass())
31+
if sel[0] == '.' { // class
32+
return ClassMatch(sel[1:], obj.StyleClass())
3333
}
34-
if ps.Sel[0] == '#' { // name
35-
return obj.StyleName() == ps.Sel[1:]
34+
if sel[0] == '#' { // name
35+
return obj.StyleName() == sel[1:]
3636
}
3737
return true // type always matches
3838
}
@@ -72,17 +72,17 @@ func (ps *Sheet[T]) SelMatchReset() {
7272

7373
// SelNoMatchWarn issues warning messages for any Sel selectors that had no
7474
// matches during the last Apply process -- see SelMatchReset.
75-
// The setName and objName provide info about the Set and obj being applied.
75+
// The sheetName and objName provide info about the Sheet and obj being applied.
7676
// Returns an error message with the non-matching sets if any, else nil.
77-
func (ps *Sheet[T]) SelNoMatchWarn(setName, objName string) error {
77+
func (ps *Sheet[T]) SelNoMatchWarn(sheetName, objName string) error {
7878
msg := ""
7979
for _, sl := range *ps {
8080
if sl.NMatch == 0 {
8181
msg += "\tSel: " + sl.Sel + "\n"
8282
}
8383
}
8484
if msg != "" {
85-
msg = fmt.Sprintf("param.Sheet from Set: %s for object: %s had the following non-matching Selectors:\n%s", setName, objName, msg)
85+
msg = fmt.Sprintf("param.Sheet from Sheet: %s for object: %s had the following non-matching Selectors:\n%s", sheetName, objName, msg)
8686
log.Println(msg) // todo: slog?
8787
return errors.New(msg)
8888
}

params/enumgen.go

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

params/params.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type Sel[T Styler] struct {
2222
// using standard css selector syntax:
2323
// - .Example applies to anything with a Class tag of 'Example'
2424
// - #Example applies to anything with a Name of 'Example'
25-
// - Example with no prefix or blank selector always applies.
25+
// - Example with no prefix or blank selector always applies as the presumed Type.
2626
Sel string `width:"30"`
2727

2828
// Doc is documentation of these parameter values: what effect

params/search.go

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,126 @@
44

55
package params
66

7-
// SearchValues is a list of parameter values to search for one parameter
8-
// on a given object (specified by Name), for float-valued params.
9-
type SearchValues struct {
10-
// name of object with the parameter
11-
Name string
7+
import (
8+
"fmt"
9+
)
1210

13-
// type of object with the parameter. This is a Base type name (e.g., Layer, Path),
14-
// that is at the start of the path in Network params.
15-
Type string
11+
// Search represents one parameter search element, applying given selector
12+
// to objects of given type, using float32 values generated by given function.
13+
type Search[T Styler] struct {
14+
// Sel is the selector for what to apply the parameters to,
15+
// using standard css selector syntax:
16+
// - .Example applies to anything with a Class tag of 'Example'
17+
// - #Example applies to anything with a Name of 'Example'
18+
// - Example with no prefix or blank selector always applies as the presumed Type.
19+
Sel string
1620

17-
// path to the parameter within the object
18-
Path string
21+
// Set function applies given parameter value to the given object
22+
// of the target type.
23+
Set func(v T, val float32)
1924

20-
// starting value, e.g., for restoring after searching
21-
// before moving on to another parameter, for grid search.
22-
Start float32
25+
// Vals is a function that generates values to search over. This is
26+
// typically called once at the start of the entire search process to get
27+
// a list of values that are cached, to determine the total number of search
28+
// jobs required, and then it is called again when this parameter is at the
29+
// top of the list to be searched, so that new values can potentially be
30+
// generated.
31+
Vals func() []float32
2332

24-
// values of the parameter to search
25-
Values []float32
33+
cached []float32
34+
}
35+
36+
// Apply checks if Sel selector applies to this object according to
37+
// (.Class, #Name, Type) using the Styler interface, and returns
38+
// false if it does not. If it does apply, then the given value
39+
// is passed to the Set function on the object, and true is returned.
40+
func (ps *Search[T]) Apply(obj T, val float32) bool {
41+
if !SelMatch(ps.Sel, obj) {
42+
return false
43+
}
44+
ps.Set(obj, val)
45+
return true
46+
}
47+
48+
// Value returns the parameter value at given value index.
49+
// Returns false if the value index is invalid.
50+
func (ps *Search[T]) Value(valIndex int) (bool, float32) {
51+
vals := ps.Values()
52+
if valIndex >= len(vals) {
53+
return false, 0
54+
}
55+
val := vals[valIndex]
56+
return true, val
57+
}
58+
59+
// Values returns the search values, using cached values if already set,
60+
// and returning [Search.CacheValues] otherwise.
61+
func (ps *Search[T]) Values() []float32 {
62+
if ps.cached != nil {
63+
return ps.cached
64+
}
65+
return ps.CacheValues()
66+
}
67+
68+
// CacheValues calls the Vals function and caches the resulting values
69+
// for later use. This can be called for dynamic searches to update the
70+
// current values relative to any initial cached values, if the search is
71+
// dynamic and depends on other state. Returns the updated cached values.
72+
func (ps *Search[T]) CacheValues() []float32 {
73+
ps.cached = ps.Vals()
74+
return ps.cached
75+
}
76+
77+
// JobString returns a string that identifies a param search job
78+
// for given parameter index and value, for this item.
79+
func (ps *Search[T]) JobString(paramIndex int, val float32) string {
80+
return fmt.Sprintf("Search %d: %s=%g", paramIndex, ps.Sel, val)
81+
}
82+
83+
// Searches is a list of [Search] elements, representing an entire
84+
// parameter search process, where multiple parameters with multiple
85+
// values per parameter are searched, typically in parallel across
86+
// independent sim run jobs. Thus, you first get the total number of
87+
// params via the [Searches.NumParams] method, and then launch jobs
88+
// for each of these param indexes, which applies that param.
89+
type Searches[T Styler] []*Search[T]
90+
91+
// NumParams returns the total number of parameter values to search.
92+
// This calls the Vals function to generate initial search values.
93+
func (sr Searches[T]) NumParams() int {
94+
n := 0
95+
for _, ps := range sr {
96+
n += len(ps.Values())
97+
}
98+
return n
99+
}
100+
101+
// SearchAtIndex returns the [Search] element at given parameter
102+
// index in range [0..NumParams), and the value index within that search.
103+
func (sr Searches[T]) SearchAtIndex(paramIndex int) (*Search[T], int) {
104+
n := 0
105+
for _, ps := range sr {
106+
sn := len(ps.Values())
107+
if paramIndex >= n && paramIndex < n+sn {
108+
return ps, paramIndex - n
109+
}
110+
n += sn
111+
}
112+
return nil, -1
113+
}
114+
115+
// SearchValue returns [Search] and value for parameter at given
116+
// param index within searches, returning error for invalid index.
117+
// Also returns string descriptor for parameter.
118+
func (sr Searches[T]) SearchValue(paramIndex int) (*Search[T], float32, string, error) {
119+
ps, valIndex := sr.SearchAtIndex(paramIndex)
120+
if ps == nil {
121+
return ps, 0, "", fmt.Errorf("No param search found for param index: %d", paramIndex)
122+
}
123+
ok, val := ps.Value(valIndex)
124+
if !ok {
125+
return ps, 0, "", fmt.Errorf("Param value index out of range: %d, for Sel: %s", valIndex, ps.Sel)
126+
}
127+
lbl := ps.JobString(paramIndex, val)
128+
return ps, val, lbl, nil
26129
}

0 commit comments

Comments
 (0)