-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain_solver.py
132 lines (115 loc) · 4.27 KB
/
main_solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3
import itertools
import sys
import time
from datetime import datetime as dt
import loader
import our_timer
import strategies.greedy as greedy
from loader import Problem
from strategies.genetic import Genetic
from strategies.greedy import ALL_LIBR_BOOK_PAIRS, ALL_LIBR_GREEDY
from strategies.strategies import SimpleCandidate, Strategy
from submission import Submission
def solve_for_this_instance(instance: Problem, only_greedy=False) -> Submission:
"""Run the algorithm(s) on this `instance`."""
greedy_solutions: list[SimpleCandidate] = []
# t1 = dt.now()
t1 = our_timer.process_time_ns()
_bk_sorters = ALL_LIBR_BOOK_PAIRS
if instance.every_book_has_equal_score:
# why would we even sort these books
_bk_sorters = ALL_LIBR_GREEDY
# example b) how many stars have to align:
# 1. Same score
# 2. unique, one (or zero) copies
# 3. every library has
# 4. N_j > D (or D/M) for all libraries
_b_type_instance = False
if instance.every_book_has_equal_score and instance.is_every_book_unique:
M_max = max(instance.library_efficiency)
M_min = min(instance.library_efficiency)
if M_max == M_min and all(
(len(instance.library_book_ids[y]) >= (instance.D * M_max))
for y in range(instance.L)):
_b_type_instance = True
for GRR in _bk_sorters:
gr_solver = GRR(instance)
out = gr_solver()
if out is not None:
out.books_improver()
greedy_solutions.append(out)
# check if the solution already is an upper bound
# (for example in input "a")
for i in greedy_solutions:
out_sub = out.to_submission()
sc = out_sub.get_submission_score()
if sc == instance.upper_bound:
# early exit
return out_sub
# additional heuristics which are separate
# from the Cartesian product above
# if instance.L <= 1_001:
# print('both', file=sys.stderr)
# for grr3 in [
# greedy.GreedyChooseLibrary,
# greedy.GreedyDynamic,
# ]:
# gr_solver = grr3(instance)
# out = gr_solver()
# if out is not None:
# out.books_improver()
# greedy_solutions.append(out)
if instance.L <= 10_001: # <-- limit z c)
print('only dynamic', file=sys.stderr)
solver_m = greedy.GreedyDynamic(instance)
out = solver_m()
if out is not None:
out.books_improver()
greedy_solutions.append(out)
elif (instance.L <= 30_002 # <-- (d) only
and instance.every_book_has_equal_score
and max(len(x) for x in instance.library_book_ids) < 30):
print('only choose-library', file=sys.stderr)
solver_j = greedy.GreedyChooseLibrary(instance)
out = solver_j()
if out is not None:
# it takes duplicates into account
# out.books_improver()
greedy_solutions.append(out)
else:
print(f'L = {instance.L}', file=sys.stderr)
... # O(L^2 * ...) is too bad for those
greedy.GreedyFast.POW = 1.05
gr = greedy.GreedyFast(instance)
out = gr()
out.books_improver()
greedy_solutions.append(out)
t2 = our_timer.process_time_ns()
print(f'greedy part took {(t2-t1)*1e-9:.2f}', file=sys.stderr)
if only_greedy:
print('best greedy solution', file=sys.stderr)
return max((x.to_submission() for x in greedy_solutions),
key=lambda x: x.get_submission_score())
solver = Genetic(instance, )
solver.sub_to_cand(greedy_solutions)
final = solver()
return final
def main():
"""
Entry point for the final project
"""
instance = loader.read_lines(sys.stdin.readlines())
sub = solve_for_this_instance(instance)
sub.write(file=sys.stdout)
# the process CPU time should be less than 5 minutes = 300 seconds
print(f'process_time: {time.process_time()} s', file=sys.stderr)
score = sub.get_submission_score()
print(f'score {score}', file=sys.stderr)
# not sure if 80% of bound is good...
s = (100*score / instance.upper_bound)
if s >= 80:
print(f'The score is {s:5.2f} % of upper bound',
file=sys.stderr)
if __name__ == '__main__':
main()