-
Notifications
You must be signed in to change notification settings - Fork 2
[#221] non-distributed optimization algorithm #296
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
[#221] non-distributed optimization algorithm #296
Conversation
src/evolution/asset/hyperon_das_node-0.0.1-cp310-abi3-manylinux_2_28_x86_64.whl
Outdated
Show resolved
Hide resolved
src/evolution/selection_methods.py
Outdated
""" | ||
if method == SelectionMethodType.BEST_FITNESS: | ||
return best_fitness | ||
elif method == SelectionMethodType.FITNESS_PROPORTIONATE: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean "FITNESS_PROPORTIONAL"? Anyway, even "proportional" is an awful name :-P
Please use ROULETTE instead, which is a more usual name for this function. However, I have two comments which don't need to be addressed in this PR but need to be fixed (please create separate cards for them).
Firstly, this roulette selection method allows the same individual to be selected more than once. Although this is OK in some implementations of GA/GP, in the case of our optimization algorithm tit doesn't seem to make sense IMO.
Secondly, we should implement a tournament selection as well. It's supposed to give equivalent results (when compared to roulette selection) but it's a lot cheaper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think cycle
from itertools
can be useful here: https://docs.python.org/3/library/itertools.html#itertools.cycle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this file could follow the same pattern I've suggested for FitnessFunctions
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the function to not allow the same individual to be selected more than once
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think cycle
does what we need here. The "Roulette" algorithm is not like a round robin selection. The idea is to select a individual with a probability which is proportional to its fitness value.
pyinstaller --onefile ./evolution/main.py | ||
mkdir -p bin | ||
mv ./dist/main ./dist/evolution | ||
mv ./dist/evolution ./bin/evolution | ||
rm -rf build/ __pycache__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this creating a wheel
file?
Please check how the other modules are created using a bazel
target:
Lines 35 to 58 in ed760b3
py_wheel( | |
name = "hyperon_das_wheel", | |
abi = "none", | |
author = "Andre Senna", | |
author_email = "[email protected]", | |
classifiers = [ | |
"Programming Language :: Python :: 3", | |
"Programming Language :: Python :: 3.10", | |
"Programming Language :: Python :: 3.11", | |
"Programming Language :: Python :: 3.12", | |
"Programming Language :: Python :: 3.13", | |
], | |
description_content_type = "text/markdown", | |
description_file = "README.md", | |
distribution = "hyperon_das", | |
platform = "any", | |
python_requires = ">=3.10", | |
python_tag = "py3", | |
requires_file = "//deps:requirements_lock.txt", | |
stamp = 1, | |
summary = "Query Engine API for Distributed AtomSpace", | |
version = "$(DAS_VERSION)", # must be defined when calling `bazel build` with `--define=DAS_VERSION=<version>` | |
deps = [":hyperon_das"], | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not create a wheel file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, got it. It's a way of creating a kind of a binary which embeds a python application along with its dependencies, allowing this:
Lines 52 to 53 in 2bcf588
run-evolution: | |
src/bin/evolution $(OPTIONS) |
I suppose this is temporary and will be replaced by a wheel
file once it is considered ready/done, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a way of creating a kind of a binary which embeds a python application along with its dependencies
I suppose this is temporary and will be replaced by a wheel file once it is considered ready/done, right?
It's a way to test the algorithm in a simpler way. This binary probably won't exist, but I don't know if we would have a wheel file up front. In short, yes, this is temporary.
src/evolution/fitness_functions.py
Outdated
class FitnessFunctionsTAG(str, enum.Enum): | ||
MULTIPLY_STRENGTHS = "multiply_strengths" | ||
|
||
|
||
def handle_fitness_function(tag: str) -> callable: | ||
if tag == FitnessFunctionsTAG.MULTIPLY_STRENGTHS: | ||
return multiply_strengths | ||
else: | ||
raise ValueError("Unknown fitness function TAG") | ||
|
||
|
||
def multiply_strengths(atom_db, query) -> float: | ||
strengths_value = [] | ||
for handle in query.handles: | ||
atom = atom_db.get_atom(handle) | ||
if (custom_attributes := atom.custom_attributes): | ||
if (strength := custom_attributes.get('strength')): | ||
strengths_value.append(strength) | ||
# if (truth_value := custom_attributes.get('truth_value')): | ||
# strength, confidence = truth_value | ||
# strengths_value.append(strength) | ||
return math.prod(strengths_value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is cleaner/simpler and also addresses @andre-senna's comment.
Unless I'm not seeing other problems/issues this change could cause.
import math
from typing import ClassVar
def multiply_strengths(atom_db, query) -> float:
strengths_value = []
for handle in query.handles:
atom = atom_db.get_atom(handle)
if (custom_attributes := atom.custom_attributes):
if (strength := custom_attributes.get('strength')):
strengths_value.append(strength)
# if (truth_value := custom_attributes.get('truth_value')):
# strength, confidence = truth_value
# strengths_value.append(strength)
return math.prod(strengths_value)
class FitnessFunctions:
_fitness_functions: ClassVar[dict[str, callable]] = {
"multiply_strengths": multiply_strengths
}
@classmethod
def get(cls, fitness_function_name: str) -> callable:
if fitness_function_name not in cls._fitness_functions:
raise ValueError("Unknown fitness function")
return cls._fitness_functions[fitness_function_name]
In the places where it is used (just an example):
from fitness_functions import FitnessFunctions
...
class QueryOptimizerIterator:
...
def _evaluate(self, query_answer: QueryAnswer) -> tuple[QueryAnswer, float]:
""" ... """
fitness_function = FitnessFunctions.get(self.fitness_function)
...
python3.10-distutils \ | ||
python3.10-venv \ | ||
python3-pip \ | ||
binutils \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
binutils \ | |
binutils \ | |
git \ |
src/evolution/Dockerfile
Outdated
|
||
ENV PYTHONPATH=/app | ||
|
||
RUN apt-get update && apt-get install -y git |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RUN apt-get update && apt-get install -y git |
No description provided.