functioneer 0.4.2__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: functioneer
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: Effortlessly explore function behavior with the ultimate batch runner.
5
5
  Author-email: Quinn Marsh <quinnmarsh@hotmail.com>
6
6
  Maintainer-email: Quinn Marsh <quinnmarsh@hotmail.com>
@@ -71,7 +71,7 @@ analysis = fn.AnalysisModule() # Create new analysis
71
71
  analysis.add.define({'a': 1, 'b': 100}) # define a and b
72
72
  analysis.add.fork('x', (0, 1, 2)) # Fork analysis, create branches for x=0, x=1, x=2
73
73
  analysis.add.fork('y', (1, 10))
74
- analysis.add.execute(func=rosenbrock) #
74
+ analysis.add.evaluate(func=rosenbrock) #
75
75
  results = analysis.run()
76
76
  print('Example 1 Output:')
77
77
  print(results['df'][['a', 'b', 'x', 'y', 'rosenbrock']])
@@ -132,7 +132,7 @@ At its core, functioneer organizes analyses as a tree where a *set of parameters
132
132
  Summary of most useful types of *analysis steps*:
133
133
  - Define: Adds a new parameter to the analysis
134
134
  - Fork: Splits the analysis into multiple parallel *branches*, each exploring different values for a specific parameter
135
- - Execute: Calls a provided function using the parameters
135
+ - Evaluate: Calls a provided function using the parameters
136
136
  - Optimize: Quickly set up an optimization by providing a function and defining which parameters are going to be optimized
137
137
 
138
138
  <details>
@@ -40,7 +40,7 @@ analysis = fn.AnalysisModule() # Create new analysis
40
40
  analysis.add.define({'a': 1, 'b': 100}) # define a and b
41
41
  analysis.add.fork('x', (0, 1, 2)) # Fork analysis, create branches for x=0, x=1, x=2
42
42
  analysis.add.fork('y', (1, 10))
43
- analysis.add.execute(func=rosenbrock) #
43
+ analysis.add.evaluate(func=rosenbrock) #
44
44
  results = analysis.run()
45
45
  print('Example 1 Output:')
46
46
  print(results['df'][['a', 'b', 'x', 'y', 'rosenbrock']])
@@ -101,7 +101,7 @@ At its core, functioneer organizes analyses as a tree where a *set of parameters
101
101
  Summary of most useful types of *analysis steps*:
102
102
  - Define: Adds a new parameter to the analysis
103
103
  - Fork: Splits the analysis into multiple parallel *branches*, each exploring different values for a specific parameter
104
- - Execute: Calls a provided function using the parameters
104
+ - Evaluate: Calls a provided function using the parameters
105
105
  - Optimize: Quickly set up an optimization by providing a function and defining which parameters are going to be optimized
106
106
 
107
107
  <details>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "functioneer"
7
- version = "0.4.2"
7
+ version = "0.5.0"
8
8
  authors = [{ name = "Quinn Marsh", email = "quinnmarsh@hotmail.com" }]
9
9
  maintainers = [{ name = "Quinn Marsh", email = "quinnmarsh@hotmail.com" }]
10
10
  description = "Effortlessly explore function behavior with the ultimate batch runner."
@@ -1,4 +1,4 @@
1
1
  # functioneer/__init__.py
2
- __version__ = "0.4.2"
3
- from functioneer.analysis import AnalysisModule, AnalysisStep, Define, Fork, Execute, Optimize
2
+ __version__ = "0.5.0"
3
+ from functioneer.analysis import AnalysisModule, AnalysisStep, Define, Fork, Evaluate, Optimize
4
4
  from functioneer.parameter import Parameter
@@ -20,13 +20,14 @@
20
20
  # THE SOFTWARE.
21
21
 
22
22
 
23
+ import itertools
23
24
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
24
25
  import copy
25
26
  import pandas as pd
26
27
  from datetime import datetime
27
28
  import time
28
29
 
29
- from functioneer.steps import AnalysisStep, Define, Fork, Execute, Optimize
30
+ from functioneer.steps import AnalysisStep, Define, Fork, Evaluate, Optimize
30
31
  from functioneer.parameter import ParameterSet, Parameter
31
32
  from functioneer.util import call_with_matched_kwargs
32
33
 
@@ -139,52 +140,75 @@ class AnalysisModule():
139
140
  else:
140
141
  raise ValueError("Expected (param_id, value) or {param_id: value, ...}")
141
142
 
142
- def fork(self, param_or_dict: Union[str, Dict[str, Tuple[Any, ...]]], value_set: Optional[Tuple[Any, ...]] = None, condition: Optional[Callable[..., bool]] = None) -> None:
143
- """Fork analysis with a single parameter or dictionary of parameter value sets.
143
+ def fork(self, param_or_dict_or_configs: Union[str, Dict[str, Tuple[Any, ...]], List[Dict[str, Any]], Tuple[Dict[str, Any], ...]],
144
+ value_list: Optional[Tuple[Any, ...]] = None, condition: Optional[Callable[..., bool]] = None) -> None:
145
+ """Fork analysis with a single parameter, dictionary of parameter value lists, or list of parameter configurations.
144
146
 
145
147
  Args:
146
- param_or_dict: Parameter ID (str) or dictionary of parameter IDs to value sets.
147
- value_set: Tuple of values for the parameter (if param_or_dict is a string).
148
+ param_or_dict_or_configs: Parameter ID (str), dictionary of parameter IDs to value lists, or list/tuple of parameter configurations.
149
+ value_list: Tuple of values for the parameter (if param_or_dict_or_configs is a string).
148
150
  condition: Optional condition function to determine if the step should run.
149
151
 
150
152
  Examples:
151
153
  >>> anal.add.fork('x', (0, 1, 2)) # Fork single parameter
152
- >>> anal.add.fork({'x': (0, 1, 2), 'y': (0, 10, 20)}) # Fork multiple parameters
154
+ >>> anal.add.fork({'x': (0, 1), 'y': (10, 20)}) # Fork multiple parameters with value lists
155
+ >>> anal.add.fork([{'x': 0, 'y': 0}, {'x': 1, 'y': 10}]) # Fork with parameter configurations
153
156
 
154
157
  Raises:
155
- ValueError: If inputs are invalid (e.g., wrong types, missing value_set, or value_set provided with dict).
158
+ ValueError: If inputs are invalid (e.g., wrong types, missing value_list, non-iterable value lists, or inconsistent configurations).
156
159
  """
157
- if isinstance(param_or_dict, dict):
158
- if value_set is not None:
159
- raise ValueError(
160
- "When forking multiple parameters with a dictionary, the 'value_set' argument is ignored. "
161
- "Use either fork(param_id: str, value_set: Tuple[Any, ...]) or fork(params: Dict[str, Tuple[Any, ...]])."
162
- )
163
- self.parent.sequence.append(Fork(param_or_dict, condition))
164
- elif isinstance(param_or_dict, str) and value_set is not None:
165
- self.parent.sequence.append(Fork({param_or_dict: value_set}, condition))
160
+ if isinstance(param_or_dict_or_configs, str):
161
+ if value_list is None:
162
+ raise ValueError("value_list must be provided for single parameter fork")
163
+ if not isinstance(value_list, (list, tuple)):
164
+ raise ValueError("value_list must be a list or tuple of parameter values")
165
+ configurations = [{param_or_dict_or_configs: value} for value in value_list]
166
+ elif isinstance(param_or_dict_or_configs, dict):
167
+ param_ids = list(param_or_dict_or_configs.keys())
168
+ value_lists = list(param_or_dict_or_configs.values())
169
+ # Validate that value lists are iterable and same length
170
+ for vs in value_lists:
171
+ if not isinstance(vs, (list, tuple)):
172
+ raise ValueError("Value lists must be lists or tuples")
173
+ value_lengths = [len(values) for values in value_lists]
174
+ if not value_lengths:
175
+ raise ValueError("param_value_lists dictionary cannot be empty")
176
+ if len(set(value_lengths)) > 1:
177
+ raise ValueError("All value lists must have the same length")
178
+
179
+ # Compute create configurations
180
+ value_configs = zip(*value_lists)
181
+ configurations = [dict(zip(param_ids, values)) for values in value_configs]
182
+
183
+ elif isinstance(param_or_dict_or_configs, (list, tuple)):
184
+ configurations = param_or_dict_or_configs
185
+ # Validate that configurations is a list of dictionaries
186
+ if not all(isinstance(config, dict) for config in configurations):
187
+ raise ValueError("Configurations must be a list or tuple of dictionaries")
166
188
  else:
167
- raise ValueError("Expected (param_id, value_set) or {param_id: value_set, ...}")
189
+ raise ValueError("Invalid input for fork: expected str, dict, or list/tuple of dicts")
190
+
191
+ self.parent.sequence.append(Fork(configurations, condition))
168
192
 
169
- def execute(self, func: Callable[..., Any], assign_to: Optional[Union[str, List[str], Tuple[str, ...]]] = None, unpack_result: bool = False, condition: Optional[Callable[..., bool]] = None) -> None:
170
- """Execute a function and store its result in the ParameterSet.
193
+ def evaluate(self, func: Callable[..., Any], assign_to: Optional[Union[str, List[str], Tuple[str, ...]]] = None, unpack_result: bool = False, condition: Optional[Callable[..., bool]] = None) -> None:
194
+ """Evaluate a function and store its result in the ParameterSet.
171
195
 
172
196
  Args:
173
- func: Function to execute, taking parameter values as input.
197
+ func: Function to evaluate, taking parameter values as input.
174
198
  assign_to: Custom Parameter ID(s) to store the result (str or list/tuple of strings).
175
199
  unpack_result: If True, unpacks a dictionary result into multiple parameters.
176
200
  condition: Optional condition function to determine if the step should run.
177
201
 
178
202
  Examples:
179
- >>> anal.add.execute(my_function) # Execute function, store result
180
- >>> anal.add.execute(my_function, assign_to='new_param') # Execute function, store result to param: 'new_param'
181
- >>> anal.add.execute(my_function_returns_dict, unpack_result=True) # Unpack dict result
182
- >>> anal.add.execute(my_function_returns_dict, assign_to=['out_1', 'out_2'], unpack_result=True) # Unpack only dict keys: out_1, out_2
203
+ >>> anal.add.evaluate(my_function) # Evaluate function, store result
204
+ >>> anal.add.evaluate(my_function, assign_to='new_param') # Evaluate function, store result to param: 'new_param'
205
+ >>> anal.add.evaluate(my_function_returns_dict, unpack_result=True) # Unpack dict result
206
+ >>> anal.add.evaluate(my_function_returns_dict, assign_to=['out_1', 'out_2'], unpack_result=True) # Unpack only dict keys: out_1, out_2
183
207
 
184
208
  Raises:
185
209
  ValueError: If func is not callable or assign_to is invalid.
186
210
  """
187
- self.parent.sequence.append(Execute(func, assign_to, unpack_result, condition))
211
+ self.parent.sequence.append(Evaluate(func, assign_to, unpack_result, condition))
188
212
 
189
213
  def optimize(self, func: Callable[..., float], opt_param_ids: Tuple[str, ...], assign_to: Optional[str] = None, direction: str = 'min', optimizer: Union[str, Callable] = 'SLSQP', tol: Optional[float] = None, bounds: Optional[Dict[str, Tuple[float, float]]] = None, options: Optional[Dict[str, Any]] = None, condition: Optional[Callable[..., bool]] = None, **kwargs) -> None:
190
214
  """Optimize a function over specified parameters.
@@ -214,7 +238,7 @@ class AnalysisModule():
214
238
  # create_pandas = True,
215
239
  # verbose = True
216
240
  ) -> Dict[str, Any]:
217
- """Execute the analysis sequence and return results including a DataFrame of leaf data.
241
+ """Evaluate the analysis sequence and return results including a DataFrame of leaf data.
218
242
 
219
243
  Returns:
220
244
  Dict[str, Any]: Dictionary containing the results DataFrame, runtime, and number of finished leaves.
@@ -21,9 +21,7 @@
21
21
 
22
22
 
23
23
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
24
- import logging
25
24
  import copy
26
- import warnings
27
25
  import numpy as np
28
26
  from scipy.optimize import minimize, dual_annealing, basinhopping, OptimizeResult
29
27
 
@@ -46,7 +44,7 @@ class AnalysisStep():
46
44
 
47
45
  def run(self, paramset: ParameterSet) -> Tuple[ParameterSet, ...]:
48
46
  """
49
- Execute the analysis step, returning a tuple of modified ParameterSets.
47
+ Evaluate the analysis step, returning a tuple of modified ParameterSets.
50
48
 
51
49
  Parameters
52
50
  ----------
@@ -109,91 +107,79 @@ class Define(AnalysisStep):
109
107
 
110
108
  class Fork(AnalysisStep):
111
109
  """
112
- Fork AnalysisStep: Splits analysis into parallel branches based on provided parameters and values.
113
- Creates new parameters in ParameterSet if they do not already exist.
110
+ Fork AnalysisStep: Splits analysis into parallel branches based on provided parameter configurations.
111
+
112
+ Each configuration is a dictionary mapping parameter IDs to values. The analysis creates a new branch
113
+ for each configuration by updating the parameter set with the specified key-value pairs, adding new
114
+ parameters or overwriting existing ones as needed.
114
115
 
115
116
  Parameters
116
117
  ----------
117
- param_id_or_ids : str or tuple/list of str
118
- Parameter ID(s) to fork. Must be valid parameter IDs (non-empty strings, not reserved).
119
- value_set_or_sets : tuple/list of values or tuple/list of tuples
120
- Values to assign to the parameter(s) in each branch. For a single parameter, provide a
121
- tuple/list of values. For multiple parameters, provide a tuple/list of tuples, where each
122
- inner tuple contains values for the corresponding parameters. The number of value sets must
123
- match the number of param_ids, and all inner value sets must have the same length.
118
+ configurations : list of dict
119
+ List of parameter configurations, where each dictionary contains parameter IDs (str) as keys
120
+ and their corresponding values. All configurations must share the same set of parameter IDs.
124
121
  condition : callable, optional
125
122
  Condition function to determine if the step should run.
126
123
 
127
124
  Raises
128
125
  ------
129
126
  ValueError
130
- If param_id_or_ids are invalid, or if value_set_or_sets are not a non-empty tuple/list of
131
- values/tuples with lengths matching param_ids and consistent across all value sets.
127
+ If configurations is not a list of dictionaries, is empty, contains inconsistent parameter IDs,
128
+ or includes invalid parameter IDs.
132
129
  TypeError
133
- If condition is not callable or None.
130
+ If condition is provided but is not callable.
134
131
 
135
132
  Examples
136
133
  --------
137
- >>> fork = Fork('x', (1, 2, 3)) # Single parameter fork
138
- >>> fork = Fork(('x', 'y'), ((0, 1), (2, 3))) # Multi-parameter fork
139
- >>> fork = Fork(['x', 'y'], [(0, 1), (2, 3)]) # List input
134
+ >>> fork = Fork([{'x': 0}, {'x': 1}, {'x': 2}]) # Single parameter fork
135
+ >>> fork = Fork([{'x': 0, 'y': 10}, {'x': 1, 'y': 20}]) # Multi-parameter fork with configurations
140
136
  """
141
- def __init__(self, param_value_sets: dict, condition: Callable[..., bool] | None = None):
137
+ def __init__(self, configurations: List[Dict[str, Any]], condition: Callable[..., bool] | None = None):
142
138
  super().__init__(condition)
143
- if not isinstance(param_value_sets, dict):
144
- raise ValueError("param_value_sets must be a dictionary with format {'param_id': (value1, value2, ...)}")
145
- self.param_value_sets = param_value_sets
146
-
147
- # Validate parameter IDs
148
- for param_id in self.param_value_sets:
149
- try:
150
- Parameter.validate_id(param_id)
151
- except ValueError as e:
152
- raise ValueError(f"Invalid param_id '{param_id}': {str(e)}") from e
139
+ # Validate that configurations is a non-empty list of dictionaries
140
+ if not isinstance(configurations, (list, tuple)) or not all(isinstance(config, dict) for config in configurations):
141
+ raise ValueError("configurations must be a list or tuple of dictionaries")
142
+ if not configurations:
143
+ raise ValueError("configurations cannot be empty")
153
144
 
154
- # Validate value sets
155
- value_lengths = [len(values) for values in self.param_value_sets.values()]
156
- if not value_lengths:
157
- raise ValueError("param_value_sets dictionary cannot be empty")
158
- if len(set(value_lengths)) > 1:
159
- raise ValueError("All value sets in param_value_sets must have the same length")
160
- self.value_cnt = value_lengths[0]
161
-
162
- # TODO Validate value types
163
- # this will be optional but left alone and values are tuples then it might be good to throw a warning in case user meant
164
- # raise ValueError(f"Warning: values of paramfork are of type 'tuple'. to silence this error set Parameter.value_type tot tuple")
165
-
166
- # TODO: Provide one level higher of error handling at the analysis level that can provide context like step index.
145
+ self.configurations = list(configurations) # Convert to list for consistency
146
+
147
+ # Validate parameter IDs and ensure consistency across configurations
148
+ # param_ids = set(self.configurations[0].keys())
149
+ for config in self.configurations:
150
+ # if set(config.keys()) != param_ids: # may turn on this optionally
151
+ # raise ValueError("All configurations must have the same parameter IDs")
152
+ for param_id in config:
153
+ try:
154
+ Parameter.validate_id(param_id)
155
+ except ValueError as e:
156
+ raise ValueError(f"Invalid param_id '{param_id}': {str(e)}") from e
167
157
 
168
158
  def run(self, paramset: ParameterSet) -> Tuple[ParameterSet, ...]:
169
159
  super().run(paramset)
170
- if self.value_cnt == 0:
171
- return (paramset,)
172
-
173
- # Do forky stuff
174
160
  next_paramsets = []
175
- for i in range(self.value_cnt):
161
+ for config in self.configurations:
176
162
  ps = copy.deepcopy(paramset)
177
- for param_id, values in self.param_value_sets.items():
178
- ps.update_param(param_id, values[i])
163
+ for param_id, value in config.items():
164
+ ps.update_param(param_id, value) # Update or add parameter
179
165
  next_paramsets.append(ps)
180
166
  return tuple(next_paramsets)
181
-
167
+
182
168
  def get_details(self) -> Dict[str, Any]:
183
169
  details = super().get_details()
184
170
  details.update({
185
- 'param_value_sets': self.param_value_sets
171
+ 'configurations': self.configurations
186
172
  })
187
173
  return details
188
174
 
189
- class Execute(AnalysisStep):
175
+ class Evaluate(AnalysisStep):
190
176
  """
191
- Execute AnalysisStep: Executes a provided function and updates the ParameterSet with results.
177
+ Evaluate AnalysisStep: Evaluates a provided function and updates the ParameterSet with results.
192
178
 
193
179
  Parameters
194
180
  ----------
195
181
  func : callable
196
- The function to execute. Output can be any type if unpack_result=False and assign_to is a string,
182
+ The function to evaluate. Output can be any type if unpack_result=False and assign_to is a string,
197
183
  or a dictionary if unpack_result=True.
198
184
  assign_to : str or iterable of str, optional
199
185
  Parameter ID(s) where the function output is stored. If a string and unpack_result=False, stores
@@ -212,14 +198,14 @@ class Execute(AnalysisStep):
212
198
  >>> anal = AnalysisModule({'x': 0, 'y': 0})
213
199
  >>> def add(x, y):
214
200
  ... return x + y
215
- >>> anal.add.execute(func=add, assign_to='sum') # Stores scalar 0 in 'sum'
216
- >>> anal.add.execute(func=add) # Stores scalar 0 in 'add'
201
+ >>> anal.add.evaluate(func=add, assign_to='sum') # Stores scalar 0 in 'sum'
202
+ >>> anal.add.evaluate(func=add) # Stores scalar 0 in 'add'
217
203
  >>> def dict_func(x, y):
218
204
  ... return {'sum': x + y, 'product': x * y}
219
- >>> anal.add.execute(func=dict_func, assign_to='results') # Stores {'sum': 0, 'product': 0} in 'results'
220
- >>> anal.add.execute(func=dict_func, assign_to=['sum', 'product'], unpack_result=True) # Stores sum=0, product=0
221
- >>> anal.add.execute(func=dict_func, unpack_result=True) # Unpacks sum=0, product=0
222
- >>> anal.add.execute(func=lambda x, y: [x, y], assign_to='list_result') # Stores [0, 0] in 'list_result'
205
+ >>> anal.add.evaluate(func=dict_func, assign_to='results') # Stores {'sum': 0, 'product': 0} in 'results'
206
+ >>> anal.add.evaluate(func=dict_func, assign_to=['sum', 'product'], unpack_result=True) # Stores sum=0, product=0
207
+ >>> anal.add.evaluate(func=dict_func, unpack_result=True) # Unpacks sum=0, product=0
208
+ >>> anal.add.evaluate(func=lambda x, y: [x, y], assign_to='list_result') # Stores [0, 0] in 'list_result'
223
209
  """
224
210
  def __init__(self,
225
211
  func: Callable,
@@ -231,7 +217,7 @@ class Execute(AnalysisStep):
231
217
 
232
218
  # Validate func
233
219
  if not isinstance(func, Callable):
234
- raise ValueError("Invalid Execute: 'func' must be a callable")
220
+ raise ValueError("Invalid Evaluate: 'func' must be a callable")
235
221
  self.func = func
236
222
 
237
223
  # Handle assign_to
@@ -243,34 +229,34 @@ class Execute(AnalysisStep):
243
229
  # Handle unpack_result
244
230
  self.unpack_result = unpack_result if unpack_result is not None else False
245
231
  if not isinstance(self.unpack_result, bool):
246
- raise ValueError(f"Invalid Execute: 'unpack_result' must be a boolean, got {type(self.unpack_result)}")
232
+ raise ValueError(f"Invalid Evaluate: 'unpack_result' must be a boolean, got {type(self.unpack_result)}")
247
233
 
248
234
  # Validate assign_to
249
235
  if isinstance(assign_to, str):
250
236
  try:
251
237
  Parameter.validate_id(assign_to)
252
238
  except ValueError as e:
253
- raise ValueError(f"Invalid Execute: 'assign_to' is not a valid param id, got {assign_to}: {str(e)}") from e
239
+ raise ValueError(f"Invalid Evaluate: 'assign_to' is not a valid param id, got {assign_to}: {str(e)}") from e
254
240
  self.assign_to = assign_to
255
241
  elif isinstance(assign_to, (list, tuple)) and assign_to:
256
242
  try:
257
243
  Parameter.validate_id_iterable(assign_to)
258
244
  except ValueError as e:
259
- raise ValueError(f"Invalid Execute: 'assign_to' must be a valid iterable of param ids, got {assign_to}: {str(e)}") from e
245
+ raise ValueError(f"Invalid Evaluate: 'assign_to' must be a valid iterable of param ids, got {assign_to}: {str(e)}") from e
260
246
  self.assign_to = tuple(assign_to)
261
247
  else:
262
- raise ValueError(f"Invalid Execute: 'assign_to' must be a string or non-empty iterable of strings, got {assign_to}")
248
+ raise ValueError(f"Invalid Evaluate: 'assign_to' must be a string or non-empty iterable of strings, got {assign_to}")
263
249
 
264
250
  # Error if unpack_result is False and assign_to is tuple/list
265
251
  if not self.unpack_result and isinstance(self.assign_to, tuple):
266
252
  raise ValueError(
267
- f"Invalid Execute: assign_to={self.assign_to} is a tuple/list, but unpack_result=False. "
253
+ f"Invalid Evaluate: assign_to={self.assign_to} is a tuple/list, but unpack_result=False. "
268
254
  f"Try setting unpack_result=True to explicitly indicate a dictionary output (which a tuple/list 'assign_to' expects. "
269
255
  )
270
256
 
271
257
  def run(self, paramset: ParameterSet) -> Tuple[ParameterSet, ...]:
272
258
  """
273
- Executes the function and updates the ParameterSet with the output.
259
+ Evaluates the function and updates the ParameterSet with the output.
274
260
 
275
261
  Parameters
276
262
  ----------
@@ -304,18 +290,18 @@ class Execute(AnalysisStep):
304
290
  if self.unpack_result:
305
291
  if not isinstance(output, dict):
306
292
  raise ValueError(
307
- f"Execute: Expected dictionary output for unpack_result=True, "
293
+ f"Evaluate: Expected dictionary output for unpack_result=True, "
308
294
  f"got {type(output)} with value {output}"
309
295
  )
310
296
  if not output:
311
- raise ValueError("Execute: Output dictionary is empty for unpack_result=True")
297
+ raise ValueError("Evaluate: Output dictionary is empty for unpack_result=True")
312
298
 
313
299
  # Use specified keys if assign_to is a tuple/list
314
300
  if isinstance(self.assign_to, tuple):
315
301
  for key in self.assign_to:
316
302
  if key not in output:
317
303
  raise ValueError(
318
- f"Execute: Output dictionary missing key '{key}' for assign_to={self.assign_to}"
304
+ f"Evaluate: Output dictionary missing key '{key}' for assign_to={self.assign_to}"
319
305
  )
320
306
  next_paramset.update_param(key, output[key])
321
307
 
@@ -325,7 +311,7 @@ class Execute(AnalysisStep):
325
311
  try:
326
312
  Parameter.validate_id(key)
327
313
  except ValueError as e:
328
- raise ValueError(f"Execute: Output key '{key}' is not a valid param id: {str(e)}") from e
314
+ raise ValueError(f"Evaluate: Output key '{key}' is not a valid param id: {str(e)}") from e
329
315
  next_paramset.update_param(key, value)
330
316
 
331
317
  # Handle any output type (unpack_result=False, string assign_to)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: functioneer
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: Effortlessly explore function behavior with the ultimate batch runner.
5
5
  Author-email: Quinn Marsh <quinnmarsh@hotmail.com>
6
6
  Maintainer-email: Quinn Marsh <quinnmarsh@hotmail.com>
@@ -71,7 +71,7 @@ analysis = fn.AnalysisModule() # Create new analysis
71
71
  analysis.add.define({'a': 1, 'b': 100}) # define a and b
72
72
  analysis.add.fork('x', (0, 1, 2)) # Fork analysis, create branches for x=0, x=1, x=2
73
73
  analysis.add.fork('y', (1, 10))
74
- analysis.add.execute(func=rosenbrock) #
74
+ analysis.add.evaluate(func=rosenbrock) #
75
75
  results = analysis.run()
76
76
  print('Example 1 Output:')
77
77
  print(results['df'][['a', 'b', 'x', 'y', 'rosenbrock']])
@@ -132,7 +132,7 @@ At its core, functioneer organizes analyses as a tree where a *set of parameters
132
132
  Summary of most useful types of *analysis steps*:
133
133
  - Define: Adds a new parameter to the analysis
134
134
  - Fork: Splits the analysis into multiple parallel *branches*, each exploring different values for a specific parameter
135
- - Execute: Calls a provided function using the parameters
135
+ - Evaluate: Calls a provided function using the parameters
136
136
  - Optimize: Quickly set up an optimization by providing a function and defining which parameters are going to be optimized
137
137
 
138
138
  <details>
File without changes
File without changes