-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finished cyclic hybridisation, experiments implemented
- Loading branch information
1 parent
2699e50
commit d92bac0
Showing
9 changed files
with
236 additions
and
1,024 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import json | ||
|
||
import pathos | ||
from tqdm import tqdm | ||
|
||
import sampo.scheduler | ||
from sampo.backend.multiproc import MultiprocessingComputationalBackend | ||
|
||
from sampo.hybrid.population_tabu import TabuPopulationScheduler | ||
|
||
from sampo.hybrid.cycle import CycleHybridScheduler | ||
from sampo.api.genetic_api import ScheduleGenerationScheme | ||
from sampo.scheduler import HEFTScheduler, HEFTBetweenScheduler, TopologicalScheduler, GeneticScheduler | ||
from sampo.hybrid.population import HeuristicPopulationScheduler, GeneticPopulationScheduler | ||
|
||
from sampo.generator.environment import get_contractor_by_wg | ||
from sampo.generator import SimpleSynthetic | ||
|
||
from sampo.base import SAMPO | ||
from sampo.schemas import WorkGraph | ||
|
||
def run_experiment(args): | ||
graph_size, iteration = args | ||
|
||
heuristics = HeuristicPopulationScheduler([HEFTScheduler(), HEFTBetweenScheduler(), TopologicalScheduler()]) | ||
# genetic1 = TabuPopulationScheduler() | ||
genetic1 = GeneticPopulationScheduler(GeneticScheduler(mutate_order=0.2, | ||
mutate_resources=0.2, | ||
sgs_type=ScheduleGenerationScheme.Parallel)) | ||
genetic2 = GeneticPopulationScheduler(GeneticScheduler(mutate_order=0.001, | ||
mutate_resources=0.001, | ||
sgs_type=ScheduleGenerationScheme.Parallel)) | ||
|
||
hybrid_combine = CycleHybridScheduler(heuristics, [genetic1, genetic2], max_plateau_size=1) | ||
hybrid_genetic1 = CycleHybridScheduler(heuristics, [genetic1], max_plateau_size=1) | ||
hybrid_genetic2 = CycleHybridScheduler(heuristics, [genetic2], max_plateau_size=1) | ||
|
||
wg = WorkGraph.load('wgs', f'{graph_size}_{iteration}') | ||
contractors = [get_contractor_by_wg(wg)] | ||
|
||
# SAMPO.backend = MultiprocessingComputationalBackend(n_cpus=10) | ||
SAMPO.backend.cache_scheduler_info(wg, contractors) | ||
SAMPO.backend.cache_genetic_info() | ||
|
||
schedule_hybrid_combine = hybrid_combine.schedule(wg, contractors) | ||
schedule_genetic1 = hybrid_genetic1.schedule(wg, contractors) | ||
schedule_genetic2 = hybrid_genetic2.schedule(wg, contractors) | ||
|
||
# print(f'Hybrid combine: {schedule_hybrid_combine.execution_time}') | ||
# print(f'Scheduler 1 cycled: {schedule_genetic1.execution_time}') | ||
# print(f'Scheduler 2 cycled: {schedule_genetic2.execution_time}') | ||
return schedule_hybrid_combine.execution_time, schedule_genetic1.execution_time, schedule_genetic2.execution_time | ||
|
||
if __name__ == '__main__': | ||
arguments = [(graph_size, iteration) for graph_size in [100, 200, 300, 400, 500] for iteration in range(5)] | ||
results = {graph_size: [] for graph_size in [100, 200, 300, 400, 500]} | ||
|
||
with pathos.multiprocessing.Pool(processes=11) as p: | ||
r = p.map(run_experiment, arguments) | ||
|
||
for (graph_size, _), (combined_time, time1, time2) in zip(arguments, r): | ||
results[graph_size].append((combined_time / time1, combined_time / time2)) | ||
|
||
with open('hybrid_results.json', 'w') as f: | ||
json.dump(results, f) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import json | ||
from itertools import chain | ||
from random import Random | ||
|
||
import matplotlib.pyplot as plt | ||
|
||
with open('hybrid_results.json', 'r') as f: | ||
results = json.load(f) | ||
|
||
results = {int(graph_size): [100 * (1 - res) for res in chain(*result)] | ||
for graph_size, result in results.items()} | ||
graph_sizes = results.keys() | ||
|
||
rand = Random() | ||
|
||
plt.title('Прирост качества планов\nот применения гибридизации', fontsize=16) | ||
plt.xlabel('Размер графа') | ||
plt.ylabel('% прироста качества относительно базового алгоритма') | ||
plt.boxplot(results.values(), labels=graph_sizes) | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from sampo.generator import SimpleSynthetic | ||
|
||
from tqdm import tqdm | ||
|
||
ss = SimpleSynthetic(rand=231) | ||
|
||
for size in range(100, 500 + 1, 100): | ||
for i in tqdm(range(100)): | ||
wg = ss.work_graph(bottom_border=size - 5, | ||
top_border=size) | ||
while not (size - 5 <= wg.vertex_count <= size): | ||
wg = ss.work_graph(bottom_border=size - 20, | ||
top_border=size) | ||
wg.dump('wgs', f'{size}_{i}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import numpy as np | ||
|
||
from sampo.api.genetic_api import ChromosomeType, FitnessFunction | ||
from sampo.base import SAMPO | ||
from sampo.hybrid.population import PopulationScheduler | ||
from sampo.scheduler.genetic import TimeFitness | ||
from sampo.scheduler.utils import get_worker_contractor_pool | ||
from sampo.schemas import WorkGraph, Contractor, Time, LandscapeConfiguration | ||
from sampo.schemas.schedule_spec import ScheduleSpec | ||
|
||
from sampo.scheduler.genetic.converter import ChromosomeType | ||
from tabusearch.experiments.scheduling.fixtures import setup_toolbox | ||
|
||
from tabusearch.experiments.scheduling.scheduling_utils import get_optimiser, OptimiserLifetime | ||
from tabusearch.utility.chromosome import ChromosomeRW | ||
|
||
|
||
class TabuPopulationScheduler(PopulationScheduler): | ||
|
||
def __init__(self, fitness: FitnessFunction = TimeFitness()): | ||
self._fitness = fitness | ||
|
||
def _get_population_fitness(self, pop: list[ChromosomeType]): | ||
# return best chromosome's fitness | ||
return min(SAMPO.backend.compute_chromosomes(self._fitness, pop)) | ||
|
||
def _get_best_individual(self, pop: list[ChromosomeType], fitness: list[float] | None = None) -> ChromosomeType: | ||
fitness = fitness or SAMPO.backend.compute_chromosomes(self._fitness, pop) | ||
return pop[np.argmin(fitness)] | ||
|
||
def schedule(self, | ||
initial_population: list[ChromosomeType], | ||
wg: WorkGraph, | ||
contractors: list[Contractor], | ||
spec: ScheduleSpec = ScheduleSpec(), | ||
assigned_parent_time: Time = Time(0), | ||
landscape: LandscapeConfiguration = LandscapeConfiguration()) -> list[ChromosomeType]: | ||
tabu_toolbox = setup_toolbox(wg, contractors, get_worker_contractor_pool(contractors)) | ||
|
||
leader = self._get_best_individual(initial_population) | ||
fitness = SAMPO.backend.compute_chromosomes(TimeFitness(), [leader]) | ||
print(f'TABU initial fitness: {fitness}') | ||
|
||
tabu_leader = ChromosomeRW.from_sampo_chromosome(leader) | ||
|
||
opt_ord, opt_res = get_optimiser(tabu_toolbox, | ||
use_vp=True, | ||
optimisers_lifetime=OptimiserLifetime.Short) | ||
tabu_leader = opt_ord.optimize(tabu_leader) | ||
tabu_leader = opt_res.optimize(tabu_leader.position) | ||
|
||
chromosome = tabu_leader.position.to_sampo_chromosome() | ||
fitness = SAMPO.backend.compute_chromosomes(TimeFitness(), [chromosome]) | ||
print(f'TABU fitness: {fitness}') | ||
|
||
return initial_population + [chromosome] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters