-
Notifications
You must be signed in to change notification settings - Fork 11
Evaluate objective in C #366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HenrikMettler
wants to merge
15
commits into
Happy-Algorithms-League:master
Choose a base branch
from
HenrikMettler:dev/evaluate_in_c
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+330
−6
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
54ee7fa
initial function: write cpp function implementation and header to files
c19e95a
add return statement
0ffb720
Add test for to_cpp() for two example functions
d83f4b7
fix example by run with subprocess
f3dc266
working creation of c module with files written in call
6f9ba12
graph.to_c, compilation and output read in objective with assertions
82476e3
Main.c and main.h for evaluation in example
9ceca9f
apply code cosmetics
a2080b1
implement PR feedback
9a59fbf
run code checks only for python-version 3.8
6712c7c
remove black from code checks
b1920be
fix flake8
22fa3cb
remove flake8 from code checks
66b5f96
remove code checks
fe0c041
address some misssed pr fb
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #include "individual.h" | ||
| #include <math.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
|
|
||
|
|
||
| double target(const double x_0, const double x_1) { | ||
| return x_0 * x_1 + 1.0; | ||
| } | ||
|
|
||
| /* generate a random floating point number from min to max */ | ||
| double rand_from_to(double min, double max) | ||
| { | ||
| const double range = (max - min); | ||
| double div = RAND_MAX / range; | ||
| return min + (rand() / div); | ||
| } | ||
|
|
||
|
|
||
| double loss() { | ||
| int n_samples = 100; | ||
| srand(1234); // fix seed | ||
|
|
||
| double sum_l2_difference = 0.0; | ||
|
|
||
| const double min = -1.0; | ||
| const double max = 1.0; | ||
|
|
||
| for(int i=0;i<n_samples;i++){ | ||
| /* generate two random values for x_0, x_1 */ | ||
| const double x_0_rand=rand_from_to(min, max); | ||
| const double x_1_rand=rand_from_to(min, max); | ||
|
|
||
| const double target_value=target(x_0_rand, x_1_rand); | ||
| const double rule_output=rule(x_0_rand, x_1_rand); | ||
|
|
||
| sum_l2_difference += pow(target_value-rule_output, 2); | ||
| } | ||
| return sum_l2_difference/(double)n_samples; | ||
| } | ||
|
|
||
| int main(){ | ||
| printf("%f", loss()); | ||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| """ | ||
| Example for evolutionary regression, with evaluation in C | ||
| ========================================================= | ||
| """ | ||
|
|
||
| # The docopt str is added explicitly to ensure compatibility with | ||
| # sphinx-gallery. | ||
| docopt_str = """ | ||
| Usage: | ||
| example_evaluate_in_c.py | ||
|
|
||
| Options: | ||
| -h --help | ||
| """ | ||
| import functools | ||
| import pathlib | ||
| import subprocess | ||
|
|
||
| from docopt import docopt | ||
|
|
||
| import cgp | ||
|
|
||
| args = docopt(docopt_str) | ||
|
|
||
| # %% | ||
| # We first define a helper function for compiling the C code. It creates | ||
| # object files from the file and main script and creates an executable | ||
|
|
||
|
|
||
| def compile_c_code(path): | ||
|
|
||
| # assert all necessary files exist | ||
| path_file_c = pathlib.Path(f"{path}/individual.c") | ||
| path_file_h = pathlib.Path(f"{path}/individual.h") | ||
| path_script_o = pathlib.Path(f"{path}/main.o") | ||
| assert path_file_c.is_file() & path_file_h.is_file() & path_script_o.is_file() | ||
|
|
||
| # compile file with rule | ||
| subprocess.check_call( | ||
| ["gcc", "-c", "-fPIC", f"{path}/individual.c", "-o", f"{path}/individual.o"] | ||
| ) | ||
|
|
||
| # create executable | ||
| subprocess.check_call( | ||
| ["gcc", f"{path}/main.o", f"{path}/individual.o", "-o", f"{path}/main"] | ||
| ) | ||
|
|
||
|
|
||
| # %% | ||
| # We define the objective function for the evolution. It creates a | ||
| # C module and header from the computational graph. The module | ||
| # and the main source file for evaluation are compiled using the above | ||
| # helper function. Here the objective obtains the fitness by reading | ||
| # the screen output of the C program. | ||
|
|
||
| def objective(individual, path): | ||
|
|
||
| if not individual.fitness_is_None(): | ||
| return individual | ||
|
|
||
| graph = cgp.CartesianGraph(individual.genome) | ||
|
|
||
| graph.to_c(path=path) | ||
|
|
||
| compile_c_code(path=path) | ||
|
|
||
| result = subprocess.check_output(pathlib.Path().absolute() / f"{path}/individual") | ||
| assert result | ||
|
|
||
| individual.fitness = -1.0 * float(result) | ||
|
|
||
| return individual | ||
|
|
||
|
|
||
| # %% | ||
| # Next, we set up the evolutionary search. We first define the parameters of the | ||
| # genome. We then create a population of individuals with matching genome parameters. | ||
|
|
||
|
|
||
| genome_params = {"n_inputs": 2, "primitives": (cgp.Add, cgp.Mul, cgp.ConstantFloat)} | ||
|
|
||
| pop = cgp.Population(genome_params=genome_params) | ||
|
|
||
| # compile C script | ||
| path = "c_code" | ||
| assert pathlib.Path(f"{path}/main.c") | ||
| subprocess.check_call(["gcc", "-c", "-fPIC", f"{path}/main.c", "-o", f"{path}/main.o"]) | ||
|
|
||
| # the objective passed to evolve should only accept one argument, | ||
| # the individual | ||
| obj = functools.partial(objective, path=path) | ||
|
|
||
| # %% | ||
| # and finally perform the evolution relying on the libraries default | ||
| # hyperparameters except that we terminate the evolution as soon as one | ||
| # individual has reached fitness zero. | ||
| pop = cgp.evolve(objective=obj, pop=pop, termination_fitness=0.0, print_progress=True) | ||
|
|
||
| # %% | ||
| # After finishing the evolution, we print the final evolved expression and assert it is the target | ||
| # expression. | ||
| print(pop.champion.to_sympy()) | ||
|
HenrikMettler marked this conversation as resolved.
|
||
| assert str(pop.champion.to_sympy()) == "x_0*x_1 + 1.0" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.