Skip to content

Commit 2699e50

Browse files
committed
Implemented first version of hybridisation
1 parent 2825e26 commit 2699e50

File tree

7 files changed

+1192
-55
lines changed

7 files changed

+1192
-55
lines changed

experiments/hybridisation.ipynb

Lines changed: 1130 additions & 0 deletions
Large diffs are not rendered by default.

sampo/backend/__init__.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from sampo.api.genetic_api import ChromosomeType, FitnessFunction, Individual, ScheduleGenerationScheme
88
from sampo.schemas import WorkGraph, Contractor, LandscapeConfiguration, Schedule, GraphNode, Time, WorkTimeEstimator
99
from sampo.schemas.schedule_spec import ScheduleSpec
10+
from sampo.schemas.time_estimator import DefaultWorkEstimator
1011

1112
T = TypeVar('T')
1213
R = TypeVar('R')
@@ -20,7 +21,7 @@ def __init__(self):
2021
self._landscape = None
2122
self._spec = None
2223
self._rand = Random()
23-
self._work_estimator = None
24+
self._work_estimator = DefaultWorkEstimator()
2425

2526
# additional genetic parameters
2627
self._toolbox = None
@@ -41,26 +42,27 @@ def __init__(self):
4142
def cache_scheduler_info(self,
4243
wg: WorkGraph,
4344
contractors: list[Contractor],
44-
landscape: LandscapeConfiguration,
45-
spec: ScheduleSpec,
45+
landscape: LandscapeConfiguration = LandscapeConfiguration(),
46+
spec: ScheduleSpec = ScheduleSpec(),
4647
rand: Random | None = None,
47-
work_estimator: WorkTimeEstimator | None = None):
48+
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
4849
...
4950

5051
@abstractmethod
5152
def cache_genetic_info(self,
52-
population_size: int,
53-
mutate_order: float,
54-
mutate_resources: float,
55-
mutate_zones: float,
56-
deadline: Time | None,
57-
weights: list[int] | None,
58-
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
59-
assigned_parent_time: Time,
60-
fitness_weights: tuple[int | float, ...],
61-
sgs_type: ScheduleGenerationScheme,
62-
only_lft_initialization: bool,
63-
is_multiobjective: bool):
53+
population_size: int = 50,
54+
mutate_order: float = 0.1,
55+
mutate_resources: float = 0.05,
56+
mutate_zones: float = 0.05,
57+
deadline: Time | None = None,
58+
weights: list[int] | None = None,
59+
init_schedules: dict[
60+
str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
61+
assigned_parent_time: Time = Time(0),
62+
fitness_weights: tuple[int | float, ...] = None,
63+
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
64+
only_lft_initialization: bool = False,
65+
is_multiobjective: bool = False):
6466
...
6567

6668
@abstractmethod

sampo/backend/default.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ def map(self, action: Callable[[T], R], values: list[T]) -> list[R]:
1818
def cache_scheduler_info(self,
1919
wg: WorkGraph,
2020
contractors: list[Contractor],
21-
landscape: LandscapeConfiguration,
22-
spec: ScheduleSpec,
21+
landscape: LandscapeConfiguration = LandscapeConfiguration(),
22+
spec: ScheduleSpec = ScheduleSpec(),
2323
rand: Random | None = None,
24-
work_estimator: WorkTimeEstimator | None = None):
24+
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
2525
self._wg = wg
2626
self._contractors = contractors
2727
self._landscape = landscape
@@ -31,18 +31,18 @@ def cache_scheduler_info(self,
3131
self._toolbox = None
3232

3333
def cache_genetic_info(self,
34-
population_size: int,
35-
mutate_order: float,
36-
mutate_resources: float,
37-
mutate_zones: float,
38-
deadline: Time | None,
39-
weights: list[int] | None,
40-
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
41-
assigned_parent_time: Time,
42-
fitness_weights: tuple[int | float, ...],
43-
sgs_type: ScheduleGenerationScheme,
44-
only_lft_initialization: bool,
45-
is_multiobjective: bool):
34+
population_size: int = 50,
35+
mutate_order: float = 0.1,
36+
mutate_resources: float = 0.05,
37+
mutate_zones: float = 0.05,
38+
deadline: Time | None = None,
39+
weights: list[int] | None = None,
40+
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
41+
assigned_parent_time: Time = Time(0),
42+
fitness_weights: tuple[int | float, ...] = None,
43+
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
44+
only_lft_initialization: bool = False,
45+
is_multiobjective: bool = False):
4646
self._selection_size = population_size
4747
self._mutate_order = mutate_order
4848
self._mutate_resources = mutate_resources
@@ -61,8 +61,11 @@ def _ensure_toolbox_created(self):
6161
if self._toolbox is None:
6262
from sampo.scheduler.genetic.utils import init_chromosomes_f, create_toolbox_using_cached_chromosomes
6363

64-
init_chromosomes = init_chromosomes_f(self._wg, self._contractors, self._init_schedules,
65-
self._landscape)
64+
if self._init_schedules:
65+
init_chromosomes = init_chromosomes_f(self._wg, self._contractors, self._init_schedules,
66+
self._landscape)
67+
else:
68+
init_chromosomes = []
6669

6770
rand = self._rand or Random()
6871
work_estimator = self._work_estimator or DefaultWorkEstimator()

sampo/backend/multiproc.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,28 @@ def _ensure_pool_created(self):
115115
def cache_scheduler_info(self,
116116
wg: WorkGraph,
117117
contractors: list[Contractor],
118-
landscape: LandscapeConfiguration,
119-
spec: ScheduleSpec,
118+
landscape: LandscapeConfiguration = LandscapeConfiguration(),
119+
spec: ScheduleSpec = ScheduleSpec(),
120120
rand: Random | None = None,
121121
work_estimator: WorkTimeEstimator = DefaultWorkEstimator()):
122122
super().cache_scheduler_info(wg, contractors, landscape, spec, rand, work_estimator)
123123
self._pool = None
124124

125125
def cache_genetic_info(self,
126-
selection_size: int,
127-
mutate_order: float,
128-
mutate_resources: float,
129-
mutate_zones: float,
130-
deadline: Time | None,
131-
weights: list[int] | None,
132-
init_schedules: dict[str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]],
133-
assigned_parent_time: Time,
134-
fitness_weights: tuple[int | float, ...],
135-
sgs_type: ScheduleGenerationScheme,
136-
only_lft_initialization: bool,
137-
is_multiobjective: bool):
138-
super().cache_genetic_info(selection_size, mutate_order, mutate_resources, mutate_zones, deadline,
126+
population_size: int = 50,
127+
mutate_order: float = 0.1,
128+
mutate_resources: float = 0.05,
129+
mutate_zones: float = 0.05,
130+
deadline: Time | None = None,
131+
weights: list[int] | None = None,
132+
init_schedules: dict[
133+
str, tuple[Schedule, list[GraphNode] | None, ScheduleSpec, float]] = None,
134+
assigned_parent_time: Time = Time(0),
135+
fitness_weights: tuple[int | float, ...] = None,
136+
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
137+
only_lft_initialization: bool = False,
138+
is_multiobjective: bool = False):
139+
super().cache_genetic_info(population_size, mutate_order, mutate_resources, mutate_zones, deadline,
139140
weights, init_schedules, assigned_parent_time, fitness_weights, sgs_type,
140141
only_lft_initialization, is_multiobjective)
141142
self._init_chromosomes = init_chromosomes_f(self._wg, self._contractors, init_schedules, self._landscape)

sampo/hybrid/cycle.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from sampo.api.genetic_api import FitnessFunction, ChromosomeType, ScheduleGenerationScheme
44
from sampo.base import SAMPO
55
from sampo.hybrid.population import PopulationScheduler
6+
from sampo.scheduler.genetic import TimeFitness
67
from sampo.scheduler.genetic.schedule_builder import create_toolbox
78
from sampo.schemas import WorkGraph, Contractor, Time, LandscapeConfiguration, Schedule
89
from sampo.schemas.schedule_spec import ScheduleSpec
@@ -12,7 +13,7 @@ class CycleHybridScheduler:
1213
def __init__(self,
1314
starting_scheduler: PopulationScheduler,
1415
cycle_schedulers: list[PopulationScheduler],
15-
fitness: FitnessFunction,
16+
fitness: FitnessFunction = TimeFitness(),
1617
max_plateau_size: int = 2):
1718
self._starting_scheduler = starting_scheduler
1819
self._cycle_schedulers = cycle_schedulers
@@ -25,8 +26,7 @@ def _get_population_fitness(self, pop: list[ChromosomeType]):
2526

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

3131
def run(self,
3232
wg: WorkGraph,

sampo/hybrid/population.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from abc import ABC, abstractmethod
22

3-
from sampo.api.genetic_api import ChromosomeType
3+
from sampo.api.genetic_api import ChromosomeType, Individual
44
from sampo.scheduler import GeneticScheduler, Scheduler
55
from sampo.scheduler.genetic.schedule_builder import create_toolbox
66
from sampo.schemas import WorkGraph, Contractor, Time, LandscapeConfiguration
@@ -49,5 +49,6 @@ def schedule(self,
4949
toolbox = create_toolbox(wg=wg, contractors=contractors,
5050
spec=spec, assigned_parent_time=assigned_parent_time,
5151
landscape=landscape)
52-
return [toolbox.schedule_to_chromosome(scheduler.schedule(wg, contractors, spec, landscape=landscape))
53-
for scheduler in self._schedulers]
52+
return [toolbox.Individual(toolbox.schedule_to_chromosome(schedule=schedule))
53+
for scheduler in self._schedulers
54+
for schedule in scheduler.schedule(wg, contractors, spec, landscape=landscape)]

sampo/scheduler/genetic/schedule_builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def create_toolbox(wg: WorkGraph,
3030
rand: random.Random = random.Random(),
3131
spec: ScheduleSpec = ScheduleSpec(),
3232
fitness_weights: tuple[int | float, ...] = (-1,),
33-
work_estimator: WorkTimeEstimator = None,
33+
work_estimator: WorkTimeEstimator = DefaultWorkEstimator(),
3434
sgs_type: ScheduleGenerationScheme = ScheduleGenerationScheme.Parallel,
3535
assigned_parent_time: Time = Time(0),
3636
landscape: LandscapeConfiguration = LandscapeConfiguration(),

0 commit comments

Comments
 (0)