Skip to content

Commit

Permalink
Merge pull request #247 from alcides/problem_with_target
Browse files Browse the repository at this point in the history
Problems now store the target value
  • Loading branch information
alcides authored Oct 24, 2024
2 parents 6b4c680 + 810c313 commit b9f48d9
Show file tree
Hide file tree
Showing 57 changed files with 277 additions and 350 deletions.
14 changes: 0 additions & 14 deletions docs/source/stopping.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,6 @@ Search algorithms can be defined with different budgets (subclasses of `genetice
.. autoapiclass:: geneticengine.evaluation.budget.EvaluationBudget
```

## Target Fitness

For single-objective:

```{eval-rst}
.. autoapiclass:: geneticengine.evaluation.budget.TargetFitness
```

For multi-objective:

```{eval-rst}
.. autoapiclass:: geneticengine.evaluation.budget.TargetMultiFitness
```

## Budget Combinators

## AnyOf
Expand Down
4 changes: 2 additions & 2 deletions examples/benchmarks/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def example_run(b: Benchmark):
problem = b.get_problem()
grammar = b.get_grammar()
random = NativeRandomSource(1)
s = GeneticProgramming(
alg = GeneticProgramming(
problem=problem,
budget=TimeBudget(5),
representation=TreeBasedRepresentation(
Expand All @@ -31,7 +31,7 @@ def example_run(b: Benchmark):
random=random,
tracker=ProgressTracker(problem, recorders=[PopulationRecorder()]),
)
best = s.search()
best = alg.search()[0]
print(
f"Fitness of {best.get_fitness(problem)} by genotype: {best.genotype} with phenotype: {best.get_phenotype()}",
)
3 changes: 2 additions & 1 deletion examples/benchmarks/benchmark_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
recorders=[PopulationRecorder()],
)
instance = m(grammar, problem, random, budget, tracker)
best = instance.search()
bests = instance.search()
best = bests[0]
print(
f"Fitness of {best.get_fitness(problem)} by genotype: {best.genotype} with phenotype: {best.get_phenotype()}",
)
3 changes: 1 addition & 2 deletions examples/benchmarks/classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from geml.grammars.ruleset_classification import make_grammar



class ClassificationBenchmark(Benchmark):

def __init__(self, X, y, feature_names):
Expand All @@ -34,7 +33,7 @@ def fitness_function(ruleset):
except ValueError:
return -1

self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function)
self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function, target=1)

def setup_grammar(self, y, feature_names):
# Grammar
Expand Down
9 changes: 7 additions & 2 deletions examples/benchmarks/classification_lexicase.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from examples.benchmarks.benchmark import Benchmark, example_run
from examples.benchmarks.datasets import get_banknote
from geneticengine.grammar.grammar import extract_grammar, Grammar
from geneticengine.problems import Problem, MultiObjectiveProblem
from geneticengine.problems import MultiObjectiveProblem, Problem
from geml.common import forward_dataset
from geml.grammars.ruleset_classification import make_grammar

Expand All @@ -24,7 +24,12 @@ def fitness_function_lexicase(ruleset):
except ValueError:
return [0 for _ in y]

self.problem = MultiObjectiveProblem(minimize=False, fitness_function=fitness_function_lexicase)
n_objectives = len(y)
self.problem = MultiObjectiveProblem(
fitness_function=fitness_function_lexicase,
minimize=[False for _ in range(n_objectives)],
target=[1 for _ in range(n_objectives)],
)

def setup_grammar(self, y, feature_names):
options = [int(v) for v in np.unique(y)]
Expand Down
2 changes: 1 addition & 1 deletion examples/benchmarks/game_of_life_vectorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def fitness_function(i: Condition):
ypred = [_clf(line) for line in np.rollaxis(X, 0)]
return f1_score(y, ypred)

self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function)
self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function, target=1)

def setup_grammar(self):
self.grammar = extract_grammar(
Expand Down
2 changes: 1 addition & 1 deletion examples/benchmarks/regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def fitness_function(ruleset):
except ValueError:
return -1

self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function)
self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function, target=0)

def setup_grammar(self, feature_names):
# Grammar
Expand Down
7 changes: 6 additions & 1 deletion examples/benchmarks/regression_lexicase.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ def lexicase_fitness_function(n: Expression):

return grouped_errors

self.problem = MultiObjectiveProblem(minimize=True, fitness_function=lexicase_fitness_function)
n_objectives = len(y)
self.problem = MultiObjectiveProblem(
fitness_function=lexicase_fitness_function,
minimize=[True for _ in range(n_objectives)],
target=[0 for _ in range(n_objectives)],
)

def setup_grammar(self, feature_names):
# Grammar
Expand Down
3 changes: 2 additions & 1 deletion examples/benchmarks/santafe.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ def setup_problem(self, map):
def fitness_function(i):
return simulate(i, map)

self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function)
target_food = map.count("#")
self.problem = SingleObjectiveProblem(minimize=False, fitness_function=fitness_function, target=target_food)

def setup_grammar(self):
self.grammar = extract_grammar([ActionBlock, Action, IfFood, Move, Right, Left], ActionMain)
Expand Down
5 changes: 1 addition & 4 deletions examples/benchmarks/string_match.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from __future__ import annotations




from examples.benchmarks.benchmark import Benchmark, example_run
from geml.grammars.letter import Char, Consonant, LetterString, String, Vowel
from geneticengine.grammar.grammar import extract_grammar
Expand All @@ -11,7 +9,6 @@
from geneticengine.problems import SingleObjectiveProblem



class StringMatchBenchmark(Benchmark):
def __init__(self, target: str = "Hellow world!"):
self.setup_problem(target)
Expand All @@ -33,7 +30,7 @@ def fitness_function(individual):
fitness -= 1 / (1 + (abs(ord(t_p) - ord(g_p))))
return fitness

self.problem = SingleObjectiveProblem(minimize=True, fitness_function=fitness_function)
self.problem = SingleObjectiveProblem(minimize=True, fitness_function=fitness_function, target=0)

def setup_grammar(self):
self.grammar = extract_grammar([LetterString, Char, Vowel, Consonant], String)
Expand Down
2 changes: 1 addition & 1 deletion examples/benchmarks/vectorialgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3112,7 +3112,7 @@ def regressor(l):
y_pred,
)

self.problem = SingleObjectiveProblem(minimize=True, fitness_function=fitness_function)
self.problem = SingleObjectiveProblem(minimize=True, fitness_function=fitness_function, target=0)

def setup_grammar(self):
"""See fitness/vectorialgp.py for docs.
Expand Down
6 changes: 3 additions & 3 deletions examples/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataclasses import dataclass
from typing import Annotated

from geneticengine.evaluation.budget import AnyOf, TargetFitness, TimeBudget
from geneticengine.evaluation.budget import TimeBudget
from geneticengine.problems import SingleObjectiveProblem
from geneticengine.random.sources import NativeRandomSource, RandomSource

Expand Down Expand Up @@ -87,8 +87,8 @@ def crossover(
repr = BinaryListTreeBasedRepresentation(random=r, grammar=g, max_depth=4)

gp = GeneticProgramming(
problem=SingleObjectiveProblem(fitness_function=fitness, minimize=False),
budget=AnyOf(TargetFitness(1), TimeBudget(3)),
problem=SingleObjectiveProblem(fitness_function=fitness, minimize=False, target=1),
budget=TimeBudget(3),
representation=repr,
random=r,
population_size=10,
Expand Down
29 changes: 14 additions & 15 deletions examples/classification_unknown_length_objectives.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import pandas as pd
from sklearn.model_selection import train_test_split

from geml.simplegp import SimpleGP
from geneticengine.algorithms.gp.gp import GeneticProgramming
from geneticengine.evaluation.budget import EvaluationBudget
from geneticengine.grammar.decorators import abstract
from geneticengine.grammar.grammar import extract_grammar
from geneticengine.grammar.grammar import Grammar
Expand All @@ -20,6 +21,10 @@
from geml.grammars.sgp import Var
from geneticengine.grammar.metahandlers.floats import FloatList
from geneticengine.grammar.metahandlers.vars import VarRange
from geneticengine.problems import LazyMultiObjectiveProblem
from geneticengine.random.sources import NativeRandomSource
from geneticengine.representations.tree.initializations import MaxDepthDecider
from geneticengine.representations.tree.treebased import TreeBasedRepresentation

# ===================================
# This is an example of normal classification using normal GP,
Expand Down Expand Up @@ -179,22 +184,16 @@ def get_grammar(self) -> Grammar:
)

def main(self, **args):
g = self.get_grammar()

alg = SimpleGP(
grammar=g,
minimize=[],
fitness_function=fitness_function_lexicase,
crossover_probability=0.75,
mutation_probability=0.01,
max_evaluations=10000,
max_depth=15,
grammar = self.get_grammar()
random = NativeRandomSource(0)
problem = LazyMultiObjectiveProblem(fitness_function_lexicase, minimize=False, target=1)
alg = GeneticProgramming(
problem=problem,
representation=TreeBasedRepresentation(grammar, MaxDepthDecider(random, grammar, 15)),
budget=EvaluationBudget(1000),
population_size=50,
selection_method=("lexicase",),
elitism=5,
**args,
)
best = alg.search()
best = alg.search()[0]
print(
f"Fitness of {best.get_fitness(alg.get_problem())} by genotype: {best.genotype} with phenotype: {best.get_phenotype()}",
)
Expand Down
9 changes: 4 additions & 5 deletions examples/coevolution_dna.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Annotated

from geneticengine.algorithms.gp.cooperativegp import CooperativeGP
from geneticengine.evaluation.budget import AnyOf, EvaluationBudget, TargetFitness
from geneticengine.evaluation.budget import EvaluationBudget
from geneticengine.grammar.grammar import extract_grammar
from geneticengine.grammar.metahandlers.lists import ListSizeBetween
from geneticengine.grammar.metahandlers.strings import StringSizeBetween
Expand Down Expand Up @@ -47,8 +47,7 @@ def dataset_fitness_function(d: Dataset):

class Explanation(ABC):
@abstractmethod
def eval(self, line: str) -> bool:
...
def eval(self, line: str) -> bool: ...


@dataclass
Expand Down Expand Up @@ -118,10 +117,10 @@ def eval_explanation_on_dataset(d: Dataset, e: Explanation) -> float:
population2_size=500,
coevolutions=10,
kwargs1={
"budget": AnyOf(TargetFitness(55), EvaluationBudget(10000)),
"budget": EvaluationBudget(10000),
},
kwargs2={
"budget": AnyOf(TargetFitness(100), EvaluationBudget(10000)),
"budget": EvaluationBudget(10000),
},
)
x: tuple[Dataset, Explanation] = alg.search()
Expand Down
6 changes: 3 additions & 3 deletions examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ def target(x):


alg_gp = GeneticProgramming(problem=problem, budget=budget, representation=representation)
ind = alg_gp.search()
ind = alg_gp.search()[0]
print("\n======\nGP\n======\n")
print(f"{ind.get_fitness(problem)} - {ind}")


alg_hc = HC(problem=problem, budget=budget, representation=representation)
ind = alg_hc.search()
ind = alg_hc.search()[0]
print("\n======\nHC\n======\n")
print(f"{ind.get_fitness(problem)} - {ind}")

alg_rs = RandomSearch(problem=problem, budget=budget, representation=representation)
ind = alg_rs.search()
ind = alg_rs.search()[0]
print("\n======\nRS\n======\n")
print(f"{ind.get_fitness(problem)} - {ind}")
2 changes: 1 addition & 1 deletion examples/extra_columns_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ def fitness_test(p) -> float:
seed=SEED,
)

ind = gp.search()
ind = gp.search()[0]
print(simplify(ind.get_phenotype()))
8 changes: 3 additions & 5 deletions examples/genetic_example/genetic_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@


class DecisionNode(ABC):
def evaluate(self, X):
...
def evaluate(self, X): ...


class IntNode(ABC):
def evaluate(self, X):
...
def evaluate(self, X): ...


@dataclass
Expand Down Expand Up @@ -101,7 +99,7 @@ def fitness_function(d: DecisionNode):
population_size=10,
max_evaluations=10000,
)
ind = alg.search()
ind = alg.search()[0]
print(ind)


Expand Down
2 changes: 1 addition & 1 deletion examples/logging_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ def target(x):


alg_gp = GeneticProgramming(problem=problem, budget=budget, representation=representation, population_size=10)
ind = alg_gp.search()
ind = alg_gp.search()[0]
print("\n======\nGP\n======\n")
print(f"{ind.get_fitness(problem)} - {ind}")
2 changes: 1 addition & 1 deletion examples/multi_target_lexicase.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def main(self, **args):
elitism=0,
**args,
)
best = alg.search()
best = alg.search()[0]
print(
f"Fitness of {best.get_fitness(alg.get_problem())} by genotype: {best.genotype} with phenotype: {best.get_phenotype()}",
)
Expand Down
2 changes: 1 addition & 1 deletion examples/pcfg_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def fitness_function(x) -> float:
population_size=1000,
max_evaluations=10 * 1000,
)
ind = alg.search()
ind = alg.search()[0]

x: TreeNode = ind.get_phenotype()
print(x)
2 changes: 1 addition & 1 deletion examples/progsys/Median.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def evolve(g, seed, mode, representation="treebased"):
population_size=50,
crossover_probability=0.9,
)
ind = alg.search()
ind = alg.search()[0]
return ind.get_phenotype(), ind.get_fitness(alg.get_problem()), g


Expand Down
2 changes: 1 addition & 1 deletion examples/progsys/Number_IO.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def evolve(g, seed, mode, representation="treebased"):
population_size=50,
crossover_probability=0.9,
)
ind = alg.search()
ind = alg.search()[0]
return ind.get_phenotype(), ind.get_fitness(alg.get_problem()), g


Expand Down
2 changes: 1 addition & 1 deletion examples/progsys/Smallest.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def evolve(g, seed, mode, representation="treebased"):
population_size=50,
crossover_probability=0.9,
)
ind = alg.search()
ind = alg.search()[0]
return ind.get_phenotype(), ind.get_fitness(alg.get_problem()), g


Expand Down
2 changes: 1 addition & 1 deletion examples/progsys/Sum_of_Squares.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def evolve(g, seed, mode, representation="treebased"):
population_size=50,
crossover_probability=0.9,
)
ind = alg.search()
ind = alg.search()[0]
return ind.get_phenotype(), ind.get_fitness(alg.get_problem()), g


Expand Down
2 changes: 1 addition & 1 deletion examples/progsys/Vector_Average.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def evolve(g, seed, mode, representation="treebased"):
population_size=50,
crossover_probability=0.9,
)
ind = alg.search()
ind = alg.search()[0]
return ind.get_phenotype(), ind.fitness, g


Expand Down
Loading

0 comments on commit b9f48d9

Please sign in to comment.