diff --git a/printer.go b/recorder.go similarity index 64% rename from printer.go rename to recorder.go index 1a5f491..e46d54c 100644 --- a/printer.go +++ b/recorder.go @@ -5,6 +5,7 @@ package optimize import ( + "encoding/json" "fmt" "io" "math" @@ -104,3 +105,72 @@ func (p *Printer) Record(loc *Location, op Operation, stats *Stats) error { p.lastValue = time.Now() return nil } + +// Full Recorder records all of the evaluations that occur during an optimization +// run. If Operation is an Evaulation, FullRecorder records the x location and +// the corresponding field of Location. If Operation is a MajorIteration, or +// PostIteration, FullRecorder records the full value of the Location struct. +// Otherwise, FullRecorder records the operation type. +type FullRecorder struct { + Writer io.Writer +} + +func (f FullRecorder) Init() error { + return nil +} + +func (f FullRecorder) Record(loc *Location, op Operation, stats *Stats) error { + r := RecordLocation{Op: op.String()} + switch { + case op.isEvaluation(): + r.Loc.X = loc.X + switch op { + default: + panic("optimize: unknown evaluation operation") + case FuncEvaluation: + r.Loc.F = loc.F + case GradEvaluation: + r.Loc.Gradient = loc.Gradient + case HessEvaluation: + r.Loc.Hessian = loc.Hessian + } + case op == MajorIteration || op == PostIteration: + r.Loc = *loc + } + if op.isEvaluation() { + + } else if op == MajorIteration { + + } + b, err := json.MarshalIndent(r, "", "\t") + if err != nil { + return nil + } + _, err = f.Writer.Write(b) + return err +} + +// Read reads the stream written to by FullRecorder, and returns the history of +// the optimization run. +func (f FullRecorder) Read(r io.Reader) ([]RecordLocation, error) { + d := json.NewDecoder(r) + var records []RecordLocation + var err error + for { + var r RecordLocation + err = d.Decode(&r) + if err != nil { + break + } + records = append(records, r) + } + if err == io.EOF { + return records, nil + } + return records, err +} + +type RecordLocation struct { + Op string + Loc Location +}