operon icon indicating copy to clipboard operation
operon copied to clipboard

Custom cost function

Open arita37 opened this issue 1 year ago • 1 comments

Hello,

just checking if it is possible to use a custom cost function like

def mycost(expr_str):

 cost = myfun(eval(expr_str))
 return cost

Thnks

arita37 avatar Aug 20 '22 02:08 arita37

Hi,

Yes, it is possible. With the C++ library, you can construct a UserDefinedEvaluator with a lambda, see here for an example.

With the python bindings, you need to define a custom function and pass it to the UserDefinedEvaluator. Consider the operon-bindings.py example. The following changes will work:

diff --git a/example/operon-bindings.py b/example/operon-bindings.py
index 100a4e4..b3f3ce5 100644
--- a/example/operon-bindings.py
+++ b/example/operon-bindings.py
@@ -74,10 +74,14 @@ mutation.Add(mut_replace, 1)
 crossover_internal_probability = 0.9 # probability to pick an internal node as a cut point
 crossover      = Operon.SubtreeCrossover(crossover_internal_probability, maxD, maxL)
 
+def custom_eval(rng, ind):
+    return [ ind.Genotype.Length ]
+
 # define fitness evaluation
 interpreter    = Operon.Interpreter() # tree interpreter
 error_metric   = Operon.R2()          # use the coefficient of determination as fitness
-evaluator      = Operon.Evaluator(problem, interpreter, error_metric, True) # initialize evaluator, use linear scaling = True
+#evaluator      = Operon.Evaluator(problem, interpreter, error_metric, True) # initialize evaluator, use linear scaling = True
+evaluator      = Operon.UserDefinedEvaluator(problem, custom_eval)
 evaluator.Budget = 1000 * 1000             # computational budget
 evaluator.LocalOptimizationIterations = 0  # number of local optimization iterations (coefficient tuning using gradient descent)

Note that this will most likely incur a performance cost due to crossing the python/C++ boundary. If the cost function is expensive enough it might not matter.

I hope this answers your question.

EDIT your question seems to be specifically about using operon to evaluate an expression string, yes that's possible, but a bit more involved. you'd have to create by hand the objects involved in evaluation (a dataset, interpreter, problem -- see example above). you can use operon.InfixParser.Parse (see here which takes the string and a dictionary mapping the variable names to variable hashes from the dataset). I will try to provide a full example in the next days.

foolnotion avatar Aug 24 '22 21:08 foolnotion

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar Jul 27 '23 01:07 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar Aug 10 '23 01:08 github-actions[bot]