Skip to content

Commit

Permalink
Fix some issues (#230)
Browse files Browse the repository at this point in the history
Fix Problem with OptHistory #229
Fix Refactor utilities #173
Fix potential problem with n_jobs. It may appear if some multiprocessing modules cannot work with n_jobs < 0. Now n_jobs is checked and converted to positive value in GraphRequirements
Fix problem with retaining composing time calculation. Initial generation is taked as full generation, but it does not consume any time for preparing. Also fix problem with generation num increment.
Change version info from `0.3.3` to `0.4.0`.
  • Loading branch information
kasyanovse authored Oct 27, 2023
1 parent 4fed127 commit 52ad420
Show file tree
Hide file tree
Showing 46 changed files with 65 additions and 63 deletions.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
author = 'NSS Lab'

# The full version, including alpha/beta/rc tags
release = '0.3.3'
release = '0.4.0'
# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
Expand Down
2 changes: 1 addition & 1 deletion examples/synthetic_graph_evolution/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from golem.core.adapter.nx_adapter import BaseNetworkxAdapter
from golem.core.optimisers.opt_history_objects.opt_history import OptHistory
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence
from golem.visualisation.graph_viz import GraphVisualizer


Expand Down
2 changes: 1 addition & 1 deletion golem/core/adapter/adapt_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from functools import partial
from typing import Callable

from golem.core.utilities.singleton_meta import SingletonMeta
from golem.utilities.singleton_meta import SingletonMeta


class AdaptRegistry(metaclass=SingletonMeta):
Expand Down
2 changes: 1 addition & 1 deletion golem/core/dag/graph_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Sequence, List, TYPE_CHECKING, Callable, Union

from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence

if TYPE_CHECKING:
from golem.core.dag.graph import Graph
Expand Down
2 changes: 1 addition & 1 deletion golem/core/dag/linked_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from golem.core.dag.graph_node import GraphNode
from golem.core.dag.graph_utils import ordered_subnodes_hierarchy, node_depth, graph_has_cycle
from golem.core.paths import copy_doc
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence, Copyable, remove_items
from golem.utilities.data_structures import ensure_wrapped_in_sequence, Copyable, remove_items

NodePostprocessCallable = Callable[[Graph, Sequence[GraphNode]], Any]

Expand Down
2 changes: 1 addition & 1 deletion golem/core/dag/linked_graph_node.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Union, Optional, Iterable, List
from golem.core.dag.graph_node import GraphNode
from golem.core.utilities.data_structures import UniqueList
from golem.utilities.data_structures import UniqueList


class LinkedGraphNode(GraphNode):
Expand Down
2 changes: 1 addition & 1 deletion golem/core/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from logging.handlers import RotatingFileHandler
from typing import Optional, Tuple, Union

from golem.core.utilities.singleton_meta import SingletonMeta
from golem.utilities.singleton_meta import SingletonMeta
from golem.core.paths import default_data_dir

DEFAULT_LOG_PATH = pathlib.Path(default_data_dir(), 'log.log')
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/adaptive/agent_trainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from golem.core.optimisers.opt_history_objects.individual import Individual
from golem.core.optimisers.opt_history_objects.opt_history import OptHistory
from golem.core.optimisers.opt_history_objects.parent_operator import ParentOperator
from golem.core.utilities.data_structures import unzip
from golem.utilities.data_structures import unzip


class AgentTrainer:
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/advisor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Any, TypeVar, Generic

from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum

NodeType = TypeVar('NodeType')

Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/fitness/fitness.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import numpy as np

from golem.core.utilities.data_structures import Comparable
from golem.utilities.data_structures import Comparable


class Fitness(Comparable):
Expand Down
19 changes: 3 additions & 16 deletions golem/core/optimisers/genetic/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from functools import partial
from typing import List, Optional, Sequence, Tuple, TypeVar, Dict

from joblib import Parallel, cpu_count, delayed
from joblib import Parallel, delayed

from golem.core.adapter import BaseOptimizationAdapter
from golem.core.dag.graph import Graph
Expand All @@ -18,8 +18,9 @@
from golem.core.optimisers.objective import GraphFunction, ObjectiveFunction
from golem.core.optimisers.opt_history_objects.individual import GraphEvalResult
from golem.core.optimisers.timer import Timer, get_forever_timer
from golem.core.utilities.serializable import Serializable
from golem.utilities.serializable import Serializable
from golem.utilities.memory import MemoryAnalytics
from golem.utilities.utilities import determine_n_jobs

# the percentage of successful evaluations,
# at which evolution is not threatened with stagnation at the moment
Expand Down Expand Up @@ -276,17 +277,3 @@ def evaluate_population(self, individuals: PopulationT) -> PopulationT:
individuals_evaluated = self.apply_evaluation_results(individuals_to_evaluate, evaluation_results)
evaluated_population = individuals_evaluated + individuals_to_skip
return evaluated_population


def determine_n_jobs(n_jobs=-1, logger=None):
cpu_num = cpu_count()
if n_jobs > cpu_num:
n_jobs = cpu_num
elif n_jobs <= 0:
if n_jobs <= -cpu_num - 1 or n_jobs == 0:
raise ValueError(f"Unproper `n_jobs` = {n_jobs}. "
f"`n_jobs` should be between ({-cpu_num}, {cpu_num}) except 0")
n_jobs = cpu_num + 1 + n_jobs
if logger:
logger.info(f"Number of used CPU's: {n_jobs}")
return n_jobs
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/base_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from golem.core.optimisers.opt_node_factory import OptNodeFactory
from golem.core.optimisers.optimization_parameters import GraphRequirements
from golem.core.optimisers.optimizer import GraphGenerationParams, AlgorithmParameters
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum

if TYPE_CHECKING:
from golem.core.optimisers.genetic.gp_params import GPAlgorithmParameters
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/crossover.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from golem.core.optimisers.opt_history_objects.parent_operator import ParentOperator
from golem.core.optimisers.optimization_parameters import GraphRequirements
from golem.core.optimisers.optimizer import GraphGenerationParams
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum

if TYPE_CHECKING:
from golem.core.optimisers.genetic.gp_params import GPAlgorithmParameters
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/elitism.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from random import shuffle

from golem.core.optimisers.genetic.operators.operator import PopulationT, Operator
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum


class ElitismTypesEnum(Enum):
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/inheritance.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from golem.core.optimisers.genetic.operators.operator import PopulationT, Operator
from golem.core.optimisers.genetic.operators.selection import Selection
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum

if TYPE_CHECKING:
from golem.core.optimisers.genetic.gp_params import GPAlgorithmParameters
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/regularization.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from golem.core.optimisers.opt_history_objects.individual import Individual
from golem.core.optimisers.opt_history_objects.parent_operator import ParentOperator
from golem.core.optimisers.optimizer import GraphGenerationParams
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum

if TYPE_CHECKING:
from golem.core.optimisers.genetic.gp_params import GPAlgorithmParameters
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/reproduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from golem.core.optimisers.genetic.operators.operator import PopulationT, EvaluationOperator
from golem.core.optimisers.genetic.operators.selection import Selection
from golem.core.optimisers.populational_optimizer import EvaluationAttemptsError
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence


class ReproductionController:
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/genetic/operators/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Callable, List, Optional

from golem.core.optimisers.genetic.operators.operator import PopulationT, Operator
from golem.core.utilities.data_structures import ComparableEnum as Enum
from golem.utilities.data_structures import ComparableEnum as Enum


class SelectionTypesEnum(Enum):
Expand Down
4 changes: 2 additions & 2 deletions golem/core/optimisers/genetic/parameters/population_size.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from golem.core.optimisers.genetic.operators.inheritance import GeneticSchemeTypesEnum
from golem.core.optimisers.genetic.operators.operator import PopulationT
from golem.core.optimisers.genetic.parameters.parameter import AdaptiveParameter
from golem.core.utilities.data_structures import BidirectionalIterator
from golem.core.utilities.sequence_iterator import fibonacci_sequence, SequenceIterator
from golem.utilities.data_structures import BidirectionalIterator
from golem.utilities.sequence_iterator import fibonacci_sequence, SequenceIterator

PopulationSize = AdaptiveParameter[int]

Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/opt_history_objects/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from copy import deepcopy, copy
from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Union

from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence

if TYPE_CHECKING:
from golem.core.optimisers.opt_history_objects.individual import Individual
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/opt_history_objects/opt_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def save_current_results(self, save_dir: Optional[os.PathLike] = None):
last_gen = self.generations[last_gen_id]
for individual in last_gen:
ind_path = Path(save_dir, str(last_gen_id), str(individual.uid))
ind_path.mkdir(exist_ok=True)
ind_path.mkdir(exist_ok=True, parents=True)
individual.save(json_file_path=ind_path / f'{str(individual.uid)}.json')
except Exception as ex:
self._log.exception(ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from uuid import uuid4

from golem.core.optimisers.opt_history_objects.individual import Individual
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence


@dataclass(frozen=True)
Expand Down
7 changes: 4 additions & 3 deletions golem/core/optimisers/optimization_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Optional

from golem.core.paths import default_data_dir
from golem.utilities.utilities import determine_n_jobs


@dataclass
Expand Down Expand Up @@ -85,9 +86,9 @@ class GraphRequirements(OptimizationParameters):
max_arity: int = 4

def __post_init__(self):
excluded_fields = ['n_jobs']
# check and convert n_jobs to non-negative
self.n_jobs = determine_n_jobs(self.n_jobs)

for field_name, field_value in dataclasses.asdict(self).items():
if field_name in excluded_fields:
continue
if isinstance(field_value, Number) and field_value < 0:
raise ValueError(f'Value of {field_name} must be non-negative')
2 changes: 1 addition & 1 deletion golem/core/optimisers/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from golem.core.optimisers.opt_history_objects.opt_history import OptHistory
from golem.core.optimisers.opt_node_factory import DefaultOptNodeFactory, OptNodeFactory
from golem.core.optimisers.random_graph_factory import RandomGraphFactory, RandomGrowthGraphFactory
from golem.core.utilities.random import RandomStateHandler
from golem.utilities.random import RandomStateHandler

STRUCTURAL_DIVERSITY_FREQUENCY_CHECK = 5

Expand Down
4 changes: 2 additions & 2 deletions golem/core/optimisers/populational_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from golem.core.optimisers.optimization_parameters import GraphRequirements
from golem.core.optimisers.optimizer import GraphGenerationParams, GraphOptimizer, AlgorithmParameters
from golem.core.optimisers.timer import OptimisationTimer
from golem.core.utilities.grouped_condition import GroupedCondition
from golem.utilities.grouped_condition import GroupedCondition


class PopulationalOptimizer(GraphOptimizer):
Expand Down Expand Up @@ -57,7 +57,7 @@ def __init__(self,
max_stagnation_time = requirements.early_stopping_timeout or self.timer.timeout
self.stop_optimization = \
GroupedCondition(results_as_message=True).add_condition(
lambda: self.timer.is_time_limit_reached(self.current_generation_num),
lambda: self.timer.is_time_limit_reached(self.current_generation_num - 1),
'Optimisation stopped: Time limit is reached'
).add_condition(
lambda: (requirements.num_of_generations is not None and
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/random/random_mutation_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from golem.core.optimisers.optimizer import GraphGenerationParams
from golem.core.optimisers.populational_optimizer import PopulationalOptimizer
from golem.core.optimisers.random.random_search import RandomSearchOptimizer
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence


class PopulationalRandomMutationOptimizer(PopulationalOptimizer):
Expand Down
2 changes: 1 addition & 1 deletion golem/core/optimisers/random/random_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from golem.core.optimisers.optimization_parameters import GraphRequirements
from golem.core.optimisers.optimizer import GraphOptimizer, GraphGenerationParams
from golem.core.optimisers.timer import OptimisationTimer
from golem.core.utilities.grouped_condition import GroupedCondition
from golem.utilities.grouped_condition import GroupedCondition


class RandomSearchOptimizer(GraphOptimizer):
Expand Down
4 changes: 2 additions & 2 deletions golem/core/optimisers/timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ def __init__(self, timeout: datetime.timedelta = None):

def _is_next_iteration_possible(self, time_constraint: float, iteration_num: int = None) -> bool:
minutes = self.minutes_from_start
if iteration_num is not None:
if iteration_num is not None and iteration_num != 0:
evo_proc_minutes = minutes - self.init_time
possible = time_constraint > (minutes + (evo_proc_minutes / (iteration_num + 1)))
possible = time_constraint > (minutes + (evo_proc_minutes / iteration_num))
else:
possible = time_constraint > minutes
if not possible:
Expand Down
2 changes: 1 addition & 1 deletion golem/core/tuning/tuner_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from golem.core.optimisers.graph import OptGraph
from golem.core.optimisers.objective import ObjectiveEvaluate, ObjectiveFunction
from golem.core.tuning.search_space import SearchSpace, convert_parameters
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence

DomainGraphForTune = TypeVar('DomainGraphForTune')

Expand Down
Empty file removed golem/core/utilities/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion golem/serializers/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _register_default_coders():
from golem.core.optimisers.opt_history_objects.parent_operator import ParentOperator
from golem.core.optimisers.fitness.fitness import Fitness
from golem.core.optimisers.objective.objective import ObjectiveInfo
from golem.core.utilities.data_structures import ComparableEnum
from golem.utilities.data_structures import ComparableEnum

from .any_serialization import any_from_json, any_to_json

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from golem.core.dag.graph import Graph
from golem.core.log import default_log
from golem.core.paths import project_root
from golem.core.utilities.serializable import Serializable
from golem.utilities.serializable import Serializable
from golem.serializers import Serializer
from golem.structural_analysis.graph_sa.results.deletion_sa_approach_result import DeletionSAApproachResult
from golem.structural_analysis.graph_sa.results.object_sa_result import ObjectSAResult, \
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Callable, Optional

from golem.core.utilities.data_structures import BidirectionalIterator
from golem.utilities.data_structures import BidirectionalIterator


class SequenceIterator(BidirectionalIterator[int]):
Expand Down
File renamed without changes.
File renamed without changes.
15 changes: 15 additions & 0 deletions golem/utilities/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from joblib import cpu_count


def determine_n_jobs(n_jobs=-1, logger=None):
cpu_num = cpu_count()
if n_jobs > cpu_num:
n_jobs = cpu_num
elif n_jobs <= 0:
if n_jobs <= -cpu_num - 1 or n_jobs == 0:
raise ValueError(f"Unproper `n_jobs` = {n_jobs}. "
f"`n_jobs` should be between ({-cpu_num}, {cpu_num}) except 0")
n_jobs = cpu_num + 1 + n_jobs
if logger:
logger.info(f"Number of used CPU's: {n_jobs}")
return n_jobs
2 changes: 1 addition & 1 deletion golem/visualisation/opt_history/multiple_fitness_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from golem.core.log import default_log
from golem.core.optimisers.opt_history_objects.opt_history import OptHistory
from golem.core.utilities.data_structures import ensure_wrapped_in_sequence
from golem.utilities.data_structures import ensure_wrapped_in_sequence
from golem.visualisation.opt_history.arg_constraint_wrapper import ArgConstraintWrapper
from golem.visualisation.opt_history.fitness_line import setup_fitness_plot
from golem.visualisation.opt_history.utils import show_or_save_figure
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# The text of the README file
NAME = 'thegolem'
VERSION = '0.3.3'
VERSION = '0.4.0'
AUTHOR = 'NSS Lab'
SHORT_DESCRIPTION = 'Framework for Graph Optimization and Learning by Evolutionary Methods'

Expand Down
6 changes: 2 additions & 4 deletions test/unit/optimizers/gp_operators/test_population_size.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import pytest

from golem.core.optimisers.archive import GenerationKeeper
from golem.core.optimisers.fitness import SingleObjFitness
from golem.core.optimisers.genetic.parameters.population_size import PopulationSize, AdaptivePopulationSize, \
from golem.core.optimisers.genetic.parameters.population_size import AdaptivePopulationSize, \
ConstRatePopulationSize
from golem.core.optimisers.graph import OptGraph, OptNode
from golem.core.optimisers.objective import Objective
from golem.core.optimisers.opt_history_objects.individual import Individual
from golem.core.utilities.sequence_iterator import SequenceIterator, fibonacci_sequence
from golem.utilities.sequence_iterator import SequenceIterator


def custom_objective():
Expand Down
Loading

0 comments on commit 52ad420

Please sign in to comment.