Skip to content

Implemented optimoptions builtin - #380

Merged
gneeri merged 7 commits into
devfrom
rm-508
Jun 1, 2026
Merged

gneeri merged 7 commits into
devfrom
rm-508

Conversation

@gneeri

@gneeri gneeri commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Note

Low Risk
New additive API with host-only metadata; existing solvers consume the same option fields already read via common helpers, and behavior is heavily covered by tests.

Overview
Adds a new optimoptions builtin that builds and updates solver-specific option structs for fminbnd, fzero, and fsolve, with MATLAB-style call forms (solver only, solver + name/value pairs, or existing struct + updates/merges).

Validation is stricter than optimset: solver-specific defaults, case-insensitive canonical field names, rejected unknown options, and typed checks for tolerances, integer limits, and Display. Struct merges handle solver switches, generic options, and skipping fields that match normalized defaults. gpuArray scalars are gathered on the host; GPU/fusion specs mark the builtin as host metadata.

canonical_option_name is moved into common.rs and shared with optimset. Builtin JSON docs and broad unit/integration tests (including passing options into the three solvers) are included.

Reviewed by Cursor Bugbot for commit 32e7741. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added an optimoptions builtin for creating and configuring optimization solver options. Supports fminbnd, fzero, and fsolve, multiple call forms, case-insensitive option names, solver-specific defaults, validation, and merging/updating of existing option sets.
  • Refactor
    • Centralized option-name canonicalization for consistent behavior across related APIs.
  • Documentation
    • Added built-in metadata, examples, and FAQ entries for optimoptions.
  • Tests
    • Added comprehensive unit tests covering defaults, validation, merging, and integration.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c798c408-fc36-4c30-8947-8180c5630b8b

📥 Commits

Reviewing files that changed from the base of the PR and between a98df5c and 32e7741.

📒 Files selected for processing (1)
  • crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs

📝 Walkthrough

Walkthrough

Adds an optimoptions builtin: shared canonicalization, descriptor and GPU/fusion metadata, async entrypoint that builds and validates solver-specific option structs for fminbnd/fzero/fsolve, tests, JSON docs, and refactors optimset to use the shared helper.

Changes

optimoptions builtin implementation

Layer / File(s) Summary
Shared utility and module structure
crates/runmat-runtime/src/builtins/math/optim/common.rs, crates/runmat-runtime/src/builtins/math/optim/mod.rs, crates/runmat-runtime/src/builtins/math/optim/optimset.rs
canonical_option_name helper normalizes known optimization option names case-insensitively; new optimoptions submodule exported; optimset refactored to use shared helper.
Builtin contract definition and metadata
crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs, crates/runmat-runtime/src/builtins/builtins-json/optimoptions.json
OPTIMOPTIONS_DESCRIPTOR specifies three call signatures, error descriptors, and GPU/fusion host-side spec; JSON documents canonical options, solver coverage (fminbnd, fzero, fsolve), validation rules, examples, and links.
Builtin entrypoint and option validation logic
crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
Async entrypoint gathers args, determines solver/defaults, merges option structs, applies canonicalized name/value pairs with parsing and validation (finite positive numerics, integer checks for iteration counts, restricted Display values), and returns typed options struct.
Tests and integration
crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
Unit and integration tests validate descriptor signatures, solver defaults, case-insensitive name handling, struct merging/override semantics, rejection of unknown/invalid values, and end-to-end usage with fminbnd, fzero, fsolve.
sequenceDiagram
  participant User
  participant OptimoptionsCall as optimoptions
  participant ParseSolver
  participant InitDefaults
  participant ApplyPairs
  participant ValidateFields
  participant SolverFn as fminbnd/fzero/fsolve
  User->>OptimoptionsCall: optimoptions('fminbnd', 'TolX', 1e-6)
  OptimoptionsCall->>ParseSolver: determine active solver
  ParseSolver->>InitDefaults: initialize solver defaults
  InitDefaults->>ApplyPairs: merge and apply pairs
  ApplyPairs->>ValidateFields: canonicalize and validate
  ValidateFields->>OptimoptionsCall: set struct field
  OptimoptionsCall->>User: return options struct
  User->>SolverFn: fminbnd(fun, a, b, opts)
  SolverFn->>SolverFn: use TolX, MaxIter from opts
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through fields both short and long,

TolX neat, Display singing its song.
Defaults set, merges sewn with care,
Solvers ready, options fair.
A rabbit's cheer for options done right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implemented optimoptions builtin' directly and accurately describes the main change: adding a new optimoptions builtin function to the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rm-508
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch rm-508

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ef2b2e6. Configure here.

Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs`:
- Around line 233-239: The code resets options to defaults whenever a later
struct specifies a non-generic solver even if that solver is the same as the
currently active one, wiping prior overrides; change the logic in the
Value::Struct handling so you call solver_from_options(&existing) into
next_solver and only replace options = default_options(next_solver) when
next_solver != solver (the currently active solver), then set solver =
next_solver and call apply_struct_fields(&existing, &mut options, solver) so
same-solver merges preserve prior overrides while switches to a different solver
reset to defaults.
- Around line 470-478: The function positive_integer_scalar currently casts a
validated f64 to usize which on stable Rust saturates and can produce usize::MAX
for out-of-range inputs; modify positive_integer_scalar to explicitly reject
parsed values that are >= 2^(usize::BITS) (or >= (2f64.powi(usize::BITS as
i32))) before casting so that it returns an
OPTIMOPTIONS_ERROR_INVALID_OPTION_VALUE via optimoptions_error_with when parsed
is too large, keeping the existing integer check (parsed.fract()==0.0) and only
performing Ok(parsed as usize) after the new upper-bound check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 481ace3e-f969-42a2-bdde-5cc2405e010c

📥 Commits

Reviewing files that changed from the base of the PR and between ecc8213 and ef2b2e6.

📒 Files selected for processing (5)
  • crates/runmat-runtime/src/builtins/builtins-json/optimoptions.json
  • crates/runmat-runtime/src/builtins/math/optim/common.rs
  • crates/runmat-runtime/src/builtins/math/optim/mod.rs
  • crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
  • crates/runmat-runtime/src/builtins/math/optim/optimset.rs

Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs Outdated
Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs`:
- Around line 255-265: When transitioning from Solver::Generic to a concrete
solver (when next_solver != Solver::Generic and solver == Solver::Generic), do
not discard the already-accumulated generic fields in options; instead create
the concrete solver defaults via default_options(next_solver) and then
merge/overlay any fields present in the current generic options that are valid
for next_solver into that new options object before setting skip_defaults_from
and calling apply_struct_fields; implement this by copying applicable fields
from the existing options (the variable options that was accumulating generic
overrides) into the new default_options(next_solver) instance (or by a small
helper like merge_generic_into_defaults), then proceed to set solver =
next_solver, skip_defaults_from = None, and call apply_struct_fields(&existing,
&mut options, solver, true, skip_defaults_from)? to reapply struct fields
correctly.
- Around line 452-458: The comparison currently checks raw Value equality
(default == value) and should instead compare normalized/coerced values; before
calling lookup_case_insensitive(...).is_some_and(|default| default == value) run
the incoming key/value through the same validation/coercion used by
set_option_field (i.e., normalize the field using the set_option_field path or
its helper), then compare the normalized incoming Value to the stored default;
update the block around canonical_option_name, lookup_case_insensitive,
source_defaults, key and value to use the normalized value for the equality
check so semantically equivalent inputs (e.g., Int vs Num, CharArray vs String)
are treated as defaults and skipped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f00ca36a-179d-42cb-b4cd-53e22ecdaf47

📥 Commits

Reviewing files that changed from the base of the PR and between ef2b2e6 and a98df5c.

📒 Files selected for processing (1)
  • crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs

Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
Comment thread crates/runmat-runtime/src/builtins/math/optim/optimoptions.rs
@gneeri
gneeri merged commit 0fe4bd1 into dev Jun 1, 2026
10 checks passed
@gneeri
gneeri deleted the rm-508 branch June 1, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant