README
README of IdeaSearch-fit
IdeaSearch/IdeaSearch-fit
IdeaSearch-fit
Quick Start
To install IdeaSearch-fit, run:
pip install IdeaSearch-fitProject Overview
IdeaSearch-fit is a symbolic-regression application for the IdeaSearch framework. It provides IdeaSearchFitter, a Helper object that configures formula generation, numerical parameter fitting, evaluation, and result reporting before being attached to an IdeaSearcher with bind_helper().
Scope
Use this package to generate and compare candidate expressions for data X and targets y, including experiments on how semantic context or IdeaSearch search settings affect the result. The package reports numerical fit quality and expression complexity; it does not establish physical interpretation, causal validity, robustness, or extrapolation. Validate selected expressions with held-out data and domain-specific checks.
Configuration Model
| Stage | Main configuration or interface | Result |
|---|---|---|
| Data | data, data_path, result_path | Input arrays and output directory |
| Semantic context | variable_names, output_name, units, descriptions, auto_polish | Prompt context for candidate generation |
| Expression grammar | functions, constant_whitelist, constant_map | Allowed symbols in executable expressions |
| Generation mode | generate_fuzzy, fuzzy_translator | Direct expressions or hypothesis-to-expression translation |
| Numerical evaluation | optimization_method, optimization_trial_num, metric-mapping settings | Fitted parameters and candidate scores |
| Agent loop | IdeaSearcher.bind_helper(), model, memory, island, migration, and budget settings | Iterative candidate generation and evaluation |
| Result access | get_best_fit(), get_pareto_frontier() | Best numerical fit and accuracy–complexity trade-off |
To compare search configurations, keep the data, expression grammar, metric, numerical optimizer, model version, and random settings fixed unless they are the variables being tested.
Processing Pipeline
IdeaSearch-fit evaluates a candidate in two stages:
- Candidate structure generation: the LLM receives the configured data summary, variable metadata, optional domain descriptions, and expression grammar. It returns an expression directly, or a natural-language hypothesis followed by an expression when
generate_fuzzy=True. - Parameter fitting and scoring: the expression is parsed, its free parameters are fitted with
L-BFGS-Bordifferential-evolution, and the configured metric is mapped to anIdeaSearchscore.
Only expressions that pass parsing and enabled validation checks enter the reported results.
Core Input and Output
Core Input:
X: Input data (independent variables, multi-dimensional support).y: Target data (dependent variable, one-dimensional).error(Optional): Measurement uncertainty for each value iny. When supplied, it is used by the uncertainty-weighted fit metric; otherwise the fitter uses mean squared error.
Core Output:
- A Pareto frontier containing the retained accuracy–complexity trade-off, together with access to the current best numerical fit.
Key Features
-
Evolutionary Symbolic Regression: Uses the multi-island evolution framework of
IdeaSearchto explore candidate mathematical expressions. -
Pareto Frontier: Reports retained candidates across the configured accuracy–complexity trade-off.
-
Dimensional Consistency Checks: Checks physical dimensions when unit validation is enabled. Dimensional consistency is a constraint, not proof of physical correctness.
-
Dual-Mode Formula Generation:
- Precise Generation: Directly generates and evolves mathematical expressions that strictly adhere to a specific computational syntax.
- Fuzzy Generation: First, an LLM proposes a natural-language hypothesis about patterns in the data. Another LLM agent then translates the hypothesis into a strict mathematical expression.
-
Automated Semantic Polishing: The system can invoke an LLM to propose descriptions of the inputs and outputs for the search prompt.
-
Seamless Integration and Automation: As a highly integrated module for
IdeaSearch, theIdeaSearchFitterclass only needs to be initialized once. It then automatically configures all the necessary core components forIdeaSearch, including the evaluation function (evaluate_func), prompts (prologue_section,epilogue_section), and mutation/crossover operators (mutation_func,crossover_func).
Core API
The primary interface for the IdeaSearch-fit package is the IdeaSearchFitter class, which consists of its constructor and several result-retrieval methods.
-
IdeaSearchFitter(__init__): ⭐️ Important- Function: Initializes an
IdeaSearchFitterinstance. This is the unified entry point for all configurations, including data loading, problem definition, expression construction, and search strategy settings. - Importance: The first step in using
IdeaSearch-fit, defining the entire framework for the symbolic regression task.
- Function: Initializes an
-
get_best_fit():- Function: Returns the numerical expression string, fitted with its optimal parameters, that achieved the lowest metric value (e.g., mean squared error) among all evaluated formulas.
- Importance: Retrieves the single best fitting result based on accuracy alone.
-
get_pareto_frontier():- Function: Returns a dictionary containing all formulas on the current Pareto frontier, along with their detailed information (complexity, metric value, fitted parameters, etc.).
- Importance: Retrieves a set of optimal solutions that balance accuracy and complexity.
Configuration Parameters
All configurations for an IdeaSearchFitter instance are set in its __init__ constructor. The parameters are logically grouped by function to facilitate understanding and setup.
1. Task Input & Output
data:Optional[Dict[str, ndarray]]- Data passed directly as a dictionary in memory. Must contain keys
"x"(input, 2D array) and"y"(output, 1D array). Can optionally include"error"(errors for y, 1D array).
- Data passed directly as a dictionary in memory. Must contain keys
data_path:Optional[str]- Path to a local
.npzfile from which to load data. Use eitherdataordata_path. The file should contain arrays with the same keys.
- Path to a local
result_path:str- Path to an existing directory where fitting results, such as the Pareto frontier report (
pareto_report.txt) and data (pareto_data.json), will be stored.
- Path to an existing directory where fitting results, such as the Pareto frontier report (
2. Problem Definition & Units
variable_names:Optional[List[str]]- A list of names for the input variables (e.g.,
["mass", "velocity"]). Defaults to["x1", "x2", ...]if not provided.
- A list of names for the input variables (e.g.,
output_name:Optional[str]- The name of the output variable (e.g.,
"energy").
- The name of the output variable (e.g.,
perform_unit_validation:bool(Default:False)- Whether to enable dimensional consistency checks.
variable_units:Optional[List[str]]- A list of units corresponding to
variable_names(e.g.,["kg", "m s^-1"]). Required whenperform_unit_validationisTrue.
- A list of units corresponding to
output_unit:Optional[str]- The unit of the output variable (e.g.,
"J"or"kg m^2 s^-2"). Required whenperform_unit_validationisTrue.
- The unit of the output variable (e.g.,
auto_polish:bool(Default:True)- Whether to invoke an LLM to propose variable and output descriptions for the search prompt.
auto_polisher:Optional[str]- The name of the LLM model to use for the
auto_polishtask. IfNone, an available model is selected automatically.
- The name of the LLM model to use for the
input_description,variable_descriptions,output_description:Optional[str]- Manually specify text descriptions for the system, input variables, and output variable. If provided, the
auto_polishstep will be skipped.
- Manually specify text descriptions for the system, input variables, and output variable. If provided, the
3. Expression Building Blocks
functions:List[str](Default: Includes common functions likesin,cos,log,exp)- A list of mathematical functions allowed in expressions. All functions must be supported by the
numexprlibrary.
- A list of mathematical functions allowed in expressions. All functions must be supported by the
constant_whitelist:List[str](Default:[])- A list of named constants (as strings) allowed in expressions.
constant_map:Dict[str, float](Default:{"pi": np.pi})- A dictionary mapping named constants to their float values.
4. Search & Evolution Strategy
- LLM Generation Strategy
generate_fuzzy:bool(Default:True)- [Master Switch] Enables "fuzzy generation" mode. If
False, the LLM will generate strict mathematical expressions directly.
- [Master Switch] Enables "fuzzy generation" mode. If
fuzzy_translator:Optional[str]- In fuzzy mode, the name of the LLM model used to translate natural language theories into mathematical expressions.
- Numerical Optimization Strategy
optimization_method:Literal["L-BFGS-B", "differential-evolution"](Default:"L-BFGS-B")- Specifies the numerical optimization algorithm for fitting ansatz parameters.
L-BFGS-Bis an efficient local optimizer suitable for smoother objective functions.differential-evolutionis a global optimizer that may be more robust for complex problems with multiple local minima.
- Specifies the numerical optimization algorithm for fitting ansatz parameters.
optimization_trial_num:int(Default:100)- The number of trials for the numerical optimizer. For
differential-evolution, this corresponds to the population size. For non-convex or complex problems, increasing this value can improve the probability of finding the global optimum at the cost of increased computation time.
- The number of trials for the numerical optimizer. For
- Evolutionary Operators (Still work in progress)
enable_mutation:bool(Default:False)- Enables the built-in expression mutation functionality.
enable_crossover:bool(Default:False)- Enables the built-in expression crossover functionality.
5. Score Mapping
baseline_metric_value:Optional[float]- Defines a "baseline" metric value (e.g., MSE) that will be mapped to an
IdeaSearchscore of20.0. IfNone, the result of a naive linear fit is used as the baseline.
- Defines a "baseline" metric value (e.g., MSE) that will be mapped to an
good_metric_value:Optional[float]- Defines a "good" metric value that will be mapped to an
IdeaSearchscore of80.0.
- Defines a "good" metric value that will be mapped to an
metric_mapping:Literal["linear", "logarithm"](Default:"linear")- The mapping function from metric value to score. Logarithmic mapping is more suitable when metric values can span several orders of magnitude.
6. Miscellaneous
seed:Optional[int]- Seed for the fitter's local random-number generator. Repeating a complete run also requires fixed model versions, API settings, and
IdeaSearchconfiguration.
- Seed for the fitter's local random-number generator. Repeating a complete run also requires fixed model versions, API settings, and
Workflow
The following is a complete workflow example (from https://github.com/IdeaSearch/IdeaSearch-fit-test) that demonstrates how to solve a symbolic regression problem using IdeaSearch-fit and IdeaSearch.
# pip install IdeaSearch-fit
import numpy as np
from IdeaSearch import IdeaSearcher
from IdeaSearch_fit import IdeaSearchFitter
def build_data():
"""
Builds simulated data for fitting.
True Formula: x = 1.2*A + A*exp(-0.7*gamma*t) - A*exp(-0.5*gamma*t)*cos(3*omega*t)
"""
n_samples = 1000
rng = np.random.default_rng(seed=42)
# Define the value ranges for the independent variables
A_range = (1.0, 10.0)
gamma_range = (0.1, 1.0)
omega_range = (1.0, 5.0)
t_range = (0.0, 10.0)
# Sample randomly within the defined ranges
A_samples = rng.uniform(A_range[0], A_range[1], n_samples)
gamma_samples = rng.uniform(gamma_range[0], gamma_range[1], n_samples)
omega_samples = rng.uniform(omega_range[0], omega_range[1], n_samples)
t_samples = rng.uniform(t_range[0], t_range[1], n_samples)
# Stack the independent variables into the format required by the Fitter (n_samples, n_features)
x_data = np.stack([A_samples, gamma_samples, omega_samples, t_samples], axis=1)
# Calculate the y values based on the true formula and add noise
y_true = (1.2 * A_samples +
A_samples * np.exp(-0.7 * gamma_samples * t_samples) -
A_samples * np.exp(-0.5 * gamma_samples * t_samples) * np.cos(3 * omega_samples * t_samples))
error_data = 0.01 + 0.02 * np.abs(y_true)
y_data = y_true + rng.normal(0, error_data)
# Note: This example does not pass error_data to the Fitter, so MSE will be used as the metric.
return {
"x": x_data,
"y": y_data,
}
def main():
# 1. Prepare the data
data = build_data()
# 2. Initialize IdeaSearchFitter
fitter = IdeaSearchFitter(
result_path = "fit_results", # Ensure this directory exists
data = data,
variable_names = ["A", "gamma", "omega", "t"],
variable_units = ["m", "s^-1", "s^-1", "s"],
output_name = "x",
output_unit = "m",
constant_whitelist = ["1", "2", "pi"],
constant_map = {"1": 1, "2": 2, "pi": np.pi},
auto_polish = True,
generate_fuzzy = True,
perform_unit_validation = True,
optimization_method = "L-BFGS-B",
optimization_trial_num = 5,
)
# 3. Initialize IdeaSearcher
ideasearcher = IdeaSearcher()
# 4. Basic Configuration
ideasearcher.set_program_name("IdeaSearch Fitter Test")
ideasearcher.set_database_path("database") # Ensure this directory exists
ideasearcher.set_api_keys_path("api_keys.json")
ideasearcher.set_models(["gemini-2.5-pro"]) # Use your desired model
ideasearcher.set_record_prompt_in_diary(True) # Optional: Record prompts in the diary log
# 5. Bind the Fitter! (The most crucial step)
ideasearcher.bind_helper(fitter)
# 6. Define and execute the evolutionary loop
island_num = 3
cycle_num = 3
unit_interaction_num = 20
for _ in range(island_num):
ideasearcher.add_island()
for cycle in range(cycle_num):
print(f"---[ Cycle {cycle + 1}/{cycle_num} ]---")
if cycle != 0: ideasearcher.repopulate_islands()
ideasearcher.run(unit_interaction_num)
print("Done.")
# 7. Retrieve and display the results
print("\n---[ Search Complete ]---")
print(f"Best Fit Formula: {fitter.get_best_fit()}")
print("\nOptimal Solutions on the Pareto Frontier:")
pareto_frontier = fitter.get_pareto_frontier()
if not pareto_frontier:
print(" - No solutions found on the Pareto frontier.")
else:
for complexity, info in sorted(pareto_frontier.items()):
metric_key = "reduced chi squared" if "reduced chi squared" in info else "mean square error"
metric_value = info.get(metric_key, float('nan'))
print(f" - Complexity: {complexity}, Error: {metric_value:.4g}, Formula: {info.get('ansatz', 'N/A')}")
if __name__ == "__main__":
# Before running, please ensure:
# 1. The './fit_results' and './database' directories exist.
# 2. The 'api_keys.json' file is correctly configured.
main()Last updated on