Loading adc2019system.py +5 −1 Changes for adc2019system.py: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ import json from roles import Host, Solver from roles import Host, Solver, MergeSolver config = None role = None Loading Loading @@ -32,7 +32,11 @@ def set_role(role_name, config_data): if role_name == 'host': role = Host(config_data) elif role_name == 'solver': if not 'partial_mode' in config_data: config['partial_mode'] = False role = Solver(config_data) elif role_name == 'merge_solver': role = MergeSolver(config_data) def call_api(method, cmd, params): Loading roles/__init__.py +1 −0 Changes for roles/__init__.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line from .host import Host from .solver import Solver from .merge_solver import MergeSolver roles/host.py +27 −4 Changes for roles/host.py: 27 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import threading import time import requests from utils import Problem from utils import Problem, GroupPart import utils.adcclilib as adccli class Host(object): Loading Loading @@ -74,7 +74,31 @@ class Host(object): return None def store_solution(self, solution): # request_idをチェックする機能もつくておく if 'part_id' in solution: if solution['status'] != 'done': return {'status': 'ignored'} problem_key = solution['problem'] if problem_key in self.problems: res = self.problems[problem_key].put_partial_solution(solution) else: res = False print(solution['solution']) print(solution['line_map'], solution['block_map']) if res: merge_problem = self.problems[problem_key].partial_merge_problem # print(merge_problem) merge_problem['request_id'] = solution['request_id'] merge_problem['timeout'] = 10000 for k, v in self.worker_manager.workers.items(): if v.role == 'merge_solver': v.post('solve', merge_problem) return {'status': 'done'} else: request_id = solution['request_id'] if request_id in self.request: self.request[request_id].store_response(solution) Loading Loading @@ -259,7 +283,7 @@ class Worker(object): self.host = params['host'] self.role = params['role'] self.params = params self.status = 'Not ready' self.status = 'Ready' self.configure() Loading Loading @@ -316,7 +340,6 @@ class Request(object): return self.request_data def store_response(self, data): # TODO: 1つのrequest_idに対し同一のworkerから2つ以上答えが返ってきた場合の例外処理 worker = data['worker'] self.response[worker] = data Loading roles/merge_solver.py 0 → 100644 +79 −0 Changes for roles/merge_solver.py: 79 added lines, 0 removed lines. Original line number Diff line number Diff line import re from roles import Solver class MergeSolver(Solver): def __init__(self, config): super().__init__(config) self.type = 'merge_solver' self.partial_mode = False def __repr__(self): return "MergeSolver" def start_solver(self, params): if 'merge_problem' in params: return super().start_solver(params) else: return {'status': 'N/A'} def submit_solution(self, params, solution): if solution['status'] == 'done': _lines = solution['solution'].splitlines() parts_pos = list() for _l in _lines: l = _l.strip() if l.startswith('SIZE'): board_size_str = l.strip().split()[1] board_solution_size = [int(v) for v in board_size_str.split('X')] bw = board_solution_size[0] bh = board_solution_size[1] elif l.startswith('BLOCK'): print(l) p = r'BLOCK#([0-9]+) +@\(([0-9]+), *([0-9]+)\)' m = re.match(p, l) bi = int(m.group(1)) bx = int(m.group(2)) by = int(m.group(3)) parts_pos.append((bx, by)) _map = list() _blocks = dict() for _y in range(bh): _map.append([0 for _x in range(bw)]) for (px, py), part in zip(parts_pos, params['parts']): for _y, _r in enumerate(part['remap']): for _x, _c in enumerate(_r): if _c != 0: _map[py+_y][px+_x] = _c for (px, py), part in zip(parts_pos, params['parts']): for bi, (_bx, _by) in part['remap_block'].items(): _blocks[bi] = (px+_bx, py+_by) _sorted_blocks = sorted(_blocks.items(), key=lambda x:x[0]) solution_text = '' solution_text += f'SIZE {bw}X{bh}\n' for _r in _map: solution_text += ','.join([str(v) for v in _r]) solution_text += '\n' for bi, (_bx, _by) in _sorted_blocks: solution_text += f'BLOCK#{bi} @({_bx},{_by})\n' solution['solution'] = solution_text data = { 'request_id': params['request_id'], 'problem': params['name'], 'worker': self.address } data.update(solution) self.post('problem/solution', data) roles/solver.py +30 −4 Changes for roles/solver.py: 30 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -5,8 +5,10 @@ import requests import sys import time import threading import traceback from collections import OrderedDict from utils import Problem class Solver(object): Loading @@ -16,6 +18,7 @@ class Solver(object): self.host = config['host'] self.address = config['address'] self.name = config['name'] self.partial_mode = config['partial_mode'] self.solver = importlib.import_module(f"solvers.{config['solver']}") self.queue = OrderedDict() Loading Loading @@ -50,6 +53,7 @@ class Solver(object): self.solve(params) except Exception as e: print("E: An error has occurred in the solver thread") print(traceback.format_exc()) self.solving = None self.set_status('Ready') else: Loading @@ -57,6 +61,28 @@ class Solver(object): def solve(self, params): if self.partial_mode and len(params['group_problems']) > 1: for i, (gproblem, gline_map, gblock_map) in enumerate(params['group_problems']): data = params.copy() data['problem'] = gproblem start_time = time.time() solution = self.solver.solve(data) end_time = time.time() elapsed_time = end_time - start_time if not 'elapsed_time' in solution: solution['elapsed_time'] = elapsed_time solution['part_id'] = i solution['line_map'] = gline_map solution['block_map'] = gblock_map self.submit_solution(data, solution) else: start_time = time.time() solution = self.solver.solve(params) end_time = time.time() Loading Loading @@ -114,15 +140,15 @@ class Solver(object): for k, v in self.queue.items(): if k == request_id: self.queue.pop(k, None) if self.solving['request_id'] == request_id: self.solver.stop()() if self.solving is not None and self.solving['request_id'] == request_id: self.solver.stop() elif 'problem' in params: problem_name = params['problem'] for k, v in self.queue.items(): if v['name'] == problem_name: self.queue.pop(k, None) if self.solving['name'] == problem_name: self.solver.stop()() if self.solving is not None and self.solving['name'] == problem_name: self.solver.stop() return {'status': 'canceled'} Loading Loading
adc2019system.py +5 −1 Changes for adc2019system.py: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ import json from roles import Host, Solver from roles import Host, Solver, MergeSolver config = None role = None Loading Loading @@ -32,7 +32,11 @@ def set_role(role_name, config_data): if role_name == 'host': role = Host(config_data) elif role_name == 'solver': if not 'partial_mode' in config_data: config['partial_mode'] = False role = Solver(config_data) elif role_name == 'merge_solver': role = MergeSolver(config_data) def call_api(method, cmd, params): Loading
roles/__init__.py +1 −0 Changes for roles/__init__.py: 1 added line, 0 removed lines. Original line number Diff line number Diff line from .host import Host from .solver import Solver from .merge_solver import MergeSolver
roles/host.py +27 −4 Changes for roles/host.py: 27 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ import threading import time import requests from utils import Problem from utils import Problem, GroupPart import utils.adcclilib as adccli class Host(object): Loading Loading @@ -74,7 +74,31 @@ class Host(object): return None def store_solution(self, solution): # request_idをチェックする機能もつくておく if 'part_id' in solution: if solution['status'] != 'done': return {'status': 'ignored'} problem_key = solution['problem'] if problem_key in self.problems: res = self.problems[problem_key].put_partial_solution(solution) else: res = False print(solution['solution']) print(solution['line_map'], solution['block_map']) if res: merge_problem = self.problems[problem_key].partial_merge_problem # print(merge_problem) merge_problem['request_id'] = solution['request_id'] merge_problem['timeout'] = 10000 for k, v in self.worker_manager.workers.items(): if v.role == 'merge_solver': v.post('solve', merge_problem) return {'status': 'done'} else: request_id = solution['request_id'] if request_id in self.request: self.request[request_id].store_response(solution) Loading Loading @@ -259,7 +283,7 @@ class Worker(object): self.host = params['host'] self.role = params['role'] self.params = params self.status = 'Not ready' self.status = 'Ready' self.configure() Loading Loading @@ -316,7 +340,6 @@ class Request(object): return self.request_data def store_response(self, data): # TODO: 1つのrequest_idに対し同一のworkerから2つ以上答えが返ってきた場合の例外処理 worker = data['worker'] self.response[worker] = data Loading
roles/merge_solver.py 0 → 100644 +79 −0 Changes for roles/merge_solver.py: 79 added lines, 0 removed lines. Original line number Diff line number Diff line import re from roles import Solver class MergeSolver(Solver): def __init__(self, config): super().__init__(config) self.type = 'merge_solver' self.partial_mode = False def __repr__(self): return "MergeSolver" def start_solver(self, params): if 'merge_problem' in params: return super().start_solver(params) else: return {'status': 'N/A'} def submit_solution(self, params, solution): if solution['status'] == 'done': _lines = solution['solution'].splitlines() parts_pos = list() for _l in _lines: l = _l.strip() if l.startswith('SIZE'): board_size_str = l.strip().split()[1] board_solution_size = [int(v) for v in board_size_str.split('X')] bw = board_solution_size[0] bh = board_solution_size[1] elif l.startswith('BLOCK'): print(l) p = r'BLOCK#([0-9]+) +@\(([0-9]+), *([0-9]+)\)' m = re.match(p, l) bi = int(m.group(1)) bx = int(m.group(2)) by = int(m.group(3)) parts_pos.append((bx, by)) _map = list() _blocks = dict() for _y in range(bh): _map.append([0 for _x in range(bw)]) for (px, py), part in zip(parts_pos, params['parts']): for _y, _r in enumerate(part['remap']): for _x, _c in enumerate(_r): if _c != 0: _map[py+_y][px+_x] = _c for (px, py), part in zip(parts_pos, params['parts']): for bi, (_bx, _by) in part['remap_block'].items(): _blocks[bi] = (px+_bx, py+_by) _sorted_blocks = sorted(_blocks.items(), key=lambda x:x[0]) solution_text = '' solution_text += f'SIZE {bw}X{bh}\n' for _r in _map: solution_text += ','.join([str(v) for v in _r]) solution_text += '\n' for bi, (_bx, _by) in _sorted_blocks: solution_text += f'BLOCK#{bi} @({_bx},{_by})\n' solution['solution'] = solution_text data = { 'request_id': params['request_id'], 'problem': params['name'], 'worker': self.address } data.update(solution) self.post('problem/solution', data)
roles/solver.py +30 −4 Changes for roles/solver.py: 30 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -5,8 +5,10 @@ import requests import sys import time import threading import traceback from collections import OrderedDict from utils import Problem class Solver(object): Loading @@ -16,6 +18,7 @@ class Solver(object): self.host = config['host'] self.address = config['address'] self.name = config['name'] self.partial_mode = config['partial_mode'] self.solver = importlib.import_module(f"solvers.{config['solver']}") self.queue = OrderedDict() Loading Loading @@ -50,6 +53,7 @@ class Solver(object): self.solve(params) except Exception as e: print("E: An error has occurred in the solver thread") print(traceback.format_exc()) self.solving = None self.set_status('Ready') else: Loading @@ -57,6 +61,28 @@ class Solver(object): def solve(self, params): if self.partial_mode and len(params['group_problems']) > 1: for i, (gproblem, gline_map, gblock_map) in enumerate(params['group_problems']): data = params.copy() data['problem'] = gproblem start_time = time.time() solution = self.solver.solve(data) end_time = time.time() elapsed_time = end_time - start_time if not 'elapsed_time' in solution: solution['elapsed_time'] = elapsed_time solution['part_id'] = i solution['line_map'] = gline_map solution['block_map'] = gblock_map self.submit_solution(data, solution) else: start_time = time.time() solution = self.solver.solve(params) end_time = time.time() Loading Loading @@ -114,15 +140,15 @@ class Solver(object): for k, v in self.queue.items(): if k == request_id: self.queue.pop(k, None) if self.solving['request_id'] == request_id: self.solver.stop()() if self.solving is not None and self.solving['request_id'] == request_id: self.solver.stop() elif 'problem' in params: problem_name = params['problem'] for k, v in self.queue.items(): if v['name'] == problem_name: self.queue.pop(k, None) if self.solving['name'] == problem_name: self.solver.stop()() if self.solving is not None and self.solving['name'] == problem_name: self.solver.stop() return {'status': 'canceled'} Loading