Skip to content

[#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

Merged
merged 31 commits into from
Mar 18, 2025

Conversation

marcocapozzoli
Copy link
Collaborator

No description provided.

"""
if method == SelectionMethodType.BEST_FITNESS:
return best_fitness
elif method == SelectionMethodType.FITNESS_PROPORTIONATE:
Copy link
Contributor

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.

Copy link
Collaborator

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

Copy link
Collaborator

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.

Copy link
Collaborator Author

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

Copy link
Contributor

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.

Comment on lines +3 to +7
pyinstaller --onefile ./evolution/main.py
mkdir -p bin
mv ./dist/main ./dist/evolution
mv ./dist/evolution ./bin/evolution
rm -rf build/ __pycache__
Copy link
Collaborator

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:

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"],
)

Copy link
Collaborator Author

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.

Copy link
Collaborator

@angeloprobst angeloprobst Mar 17, 2025

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:

das/Makefile

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?

Copy link
Collaborator Author

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.

Comment on lines 5 to 26
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)
Copy link
Collaborator

@angeloprobst angeloprobst Mar 12, 2025

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 \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
binutils \
binutils \
git \


ENV PYTHONPATH=/app

RUN apt-get update && apt-get install -y git
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RUN apt-get update && apt-get install -y git

@andre-senna andre-senna removed their request for review March 17, 2025 17:44
@marcocapozzoli marcocapozzoli merged commit 0844338 into master Mar 18, 2025
1 check passed
@marcocapozzoli marcocapozzoli deleted the masc/221-non-distributed-optimization-algorithm branch March 18, 2025 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants