Skip to content

Commit

Permalink
Implemented first version of hybridisation
Browse files Browse the repository at this point in the history
  • Loading branch information
StannisMod committed Apr 3, 2024
1 parent 2825e26 commit 2699e50
Show file tree
Hide file tree
Showing 7 changed files with 1,192 additions and 55 deletions.
1,130 changes: 1,130 additions & 0 deletions experiments/hybridisation.ipynb

Large diffs are not rendered by default.

34 changes: 18 additions & 16 deletions sampo/backend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from sampo.api.genetic_api import ChromosomeType, FitnessFunction, Individual, ScheduleGenerationScheme
from sampo.schemas import WorkGraph, Contractor, LandscapeConfiguration, Schedule, GraphNode, Time, WorkTimeEstimator
from sampo.schemas.schedule_spec import ScheduleSpec
from sampo.schemas.time_estimator import DefaultWorkEstimator

T = TypeVar('T')
R = TypeVar('R')
Expand All @@ -20,7 +21,7 @@ def __init__(self):
self._landscape = None
self._spec = None
self._rand = Random()
self._work_estimator = None
self._work_estimator = DefaultWorkEstimator()

# additional genetic parameters
self._toolbox = None
Expand All @@ -41,26 +42,27 @@ def __init__(self):
def cache_scheduler_info(self,
wg: WorkGraph,
contractors: list[Contractor],
landscape: LandscapeConfiguration,
spec: ScheduleSpec,
landscape: LandscapeConfiguration = LandscapeConfiguration(),
spec: ScheduleSpec = ScheduleSpec(),
rand: Random | None = None,
work_estimator: WorkTimeEstimator | None = None):
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
...

@abstractmethod
def cache_genetic_info(self,
population_size: int,
mutate_order: float,
mutate_resources: float,
mutate_zones: float,
deadline: Time | None,
weights: list[int] | None,
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
assigned_parent_time: Time,
fitness_weights: tuple[int | float, ...],
sgs_type: ScheduleGenerationScheme,
only_lft_initialization: bool,
is_multiobjective: bool):
population_size: int = 50,
mutate_order: float = 0.1,
mutate_resources: float = 0.05,
mutate_zones: float = 0.05,
deadline: Time | None = None,
weights: list[int] | None = None,
init_schedules: dict[
str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
assigned_parent_time: Time = Time(0),
fitness_weights: tuple[int | float, ...] = None,
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
only_lft_initialization: bool = False,
is_multiobjective: bool = False):
...

@abstractmethod
Expand Down
37 changes: 20 additions & 17 deletions sampo/backend/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ def map(self, action: Callable[[T], R], values: list[T]) -> list[R]:
def cache_scheduler_info(self,
wg: WorkGraph,
contractors: list[Contractor],
landscape: LandscapeConfiguration,
spec: ScheduleSpec,
landscape: LandscapeConfiguration = LandscapeConfiguration(),
spec: ScheduleSpec = ScheduleSpec(),
rand: Random | None = None,
work_estimator: WorkTimeEstimator | None = None):
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
self._wg = wg
self._contractors = contractors
self._landscape = landscape
Expand All @@ -31,18 +31,18 @@ def cache_scheduler_info(self,
self._toolbox = None

def cache_genetic_info(self,
population_size: int,
mutate_order: float,
mutate_resources: float,
mutate_zones: float,
deadline: Time | None,
weights: list[int] | None,
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
assigned_parent_time: Time,
fitness_weights: tuple[int | float, ...],
sgs_type: ScheduleGenerationScheme,
only_lft_initialization: bool,
is_multiobjective: bool):
population_size: int = 50,
mutate_order: float = 0.1,
mutate_resources: float = 0.05,
mutate_zones: float = 0.05,
deadline: Time | None = None,
weights: list[int] | None = None,
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
assigned_parent_time: Time = Time(0),
fitness_weights: tuple[int | float, ...] = None,
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
only_lft_initialization: bool = False,
is_multiobjective: bool = False):
self._selection_size = population_size
self._mutate_order = mutate_order
self._mutate_resources = mutate_resources
Expand All @@ -61,8 +61,11 @@ def _ensure_toolbox_created(self):
if self._toolbox is None:
from sampo.scheduler.genetic.utils import init_chromosomes_f, create_toolbox_using_cached_chromosomes

init_chromosomes = init_chromosomes_f(self._wg, self._contractors, self._init_schedules,
self._landscape)
if self._init_schedules:
init_chromosomes = init_chromosomes_f(self._wg, self._contractors, self._init_schedules,
self._landscape)
else:
init_chromosomes = []

rand = self._rand or Random()
work_estimator = self._work_estimator or DefaultWorkEstimator()
Expand Down
31 changes: 16 additions & 15 deletions sampo/backend/multiproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,27 +115,28 @@ def _ensure_pool_created(self):
def cache_scheduler_info(self,
wg: WorkGraph,
contractors: list[Contractor],
landscape: LandscapeConfiguration,
spec: ScheduleSpec,
landscape: LandscapeConfiguration = LandscapeConfiguration(),
spec: ScheduleSpec = ScheduleSpec(),
rand: Random | None = None,
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
super().cache_scheduler_info(wg, contractors, landscape, spec, rand, work_estimator)
self._pool = None

def cache_genetic_info(self,
selection_size: int,
mutate_order: float,
mutate_resources: float,
mutate_zones: float,
deadline: Time | None,
weights: list[int] | None,
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
assigned_parent_time: Time,
fitness_weights: tuple[int | float, ...],
sgs_type: ScheduleGenerationScheme,
only_lft_initialization: bool,
is_multiobjective: bool):
super().cache_genetic_info(selection_size, mutate_order, mutate_resources, mutate_zones, deadline,
population_size: int = 50,
mutate_order: float = 0.1,
mutate_resources: float = 0.05,
mutate_zones: float = 0.05,
deadline: Time | None = None,
weights: list[int] | None = None,
init_schedules: dict[
str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
assigned_parent_time: Time = Time(0),
fitness_weights: tuple[int | float, ...] = None,
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
only_lft_initialization: bool = False,
is_multiobjective: bool = False):
super().cache_genetic_info(population_size, mutate_order, mutate_resources, mutate_zones, deadline,
weights, init_schedules, assigned_parent_time, fitness_weights, sgs_type,
only_lft_initialization, is_multiobjective)
self._init_chromosomes = init_chromosomes_f(self._wg, self._contractors, init_schedules, self._landscape)
Expand Down
6 changes: 3 additions & 3 deletions sampo/hybrid/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from sampo.api.genetic_api import FitnessFunction, ChromosomeType, ScheduleGenerationScheme
from sampo.base import SAMPO
from sampo.hybrid.population import PopulationScheduler
from sampo.scheduler.genetic import TimeFitness
from sampo.scheduler.genetic.schedule_builder import create_toolbox
from sampo.schemas import WorkGraph, Contractor, Time, LandscapeConfiguration, Schedule
from sampo.schemas.schedule_spec import ScheduleSpec
Expand All @@ -12,7 +13,7 @@ class CycleHybridScheduler:
def __init__(self,
starting_scheduler: PopulationScheduler,
cycle_schedulers: list[PopulationScheduler],
fitness: FitnessFunction,
fitness: FitnessFunction = TimeFitness(),
max_plateau_size: int = 2):
self._starting_scheduler = starting_scheduler
self._cycle_schedulers = cycle_schedulers
Expand All @@ -25,8 +26,7 @@ def _get_population_fitness(self, pop: list[ChromosomeType]):

def _get_best_individual(self, pop: list[ChromosomeType]) -> ChromosomeType:
fitness = SAMPO.backend.compute_chromosomes(self._fitness, pop)
min_indices = np.argmin(fitness)
return pop[min_indices[0]]
return pop[np.argmin(fitness)]

def run(self,
wg: WorkGraph,
Expand Down
7 changes: 4 additions & 3 deletions sampo/hybrid/population.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from abc import ABC, abstractmethod

from sampo.api.genetic_api import ChromosomeType
from sampo.api.genetic_api import ChromosomeType, Individual
from sampo.scheduler import GeneticScheduler, Scheduler
from sampo.scheduler.genetic.schedule_builder import create_toolbox
from sampo.schemas import WorkGraph, Contractor, Time, LandscapeConfiguration
Expand Down Expand Up @@ -49,5 +49,6 @@ def schedule(self,
toolbox = create_toolbox(wg=wg, contractors=contractors,
spec=spec, assigned_parent_time=assigned_parent_time,
landscape=landscape)
return [toolbox.schedule_to_chromosome(scheduler.schedule(wg, contractors, spec, landscape=landscape))
for scheduler in self._schedulers]
return [toolbox.Individual(toolbox.schedule_to_chromosome(schedule=schedule))
for scheduler in self._schedulers
for schedule in scheduler.schedule(wg, contractors, spec, landscape=landscape)]
2 changes: 1 addition & 1 deletion sampo/scheduler/genetic/schedule_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def create_toolbox(wg: WorkGraph,
rand: random.Random = random.Random(),
spec: ScheduleSpec = ScheduleSpec(),
fitness_weights: tuple[int | float, ...] = (-1,),
work_estimator: WorkTimeEstimator = None,
work_estimator: WorkTimeEstimator = DefaultWorkEstimator(),
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
assigned_parent_time: Time = Time(0),
landscape: LandscapeConfiguration = LandscapeConfiguration(),
Expand Down

0 comments on commit 2699e50

Please sign in to comment.