rogermt commited on
Commit
2199265
·
verified ·
1 Parent(s): f00e06a

Move own-solver/neurogolf_solver/submission.py to own-solver/

Browse files
own-solver/neurogolf_solver/submission.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Submission file generation and task running with W&B logging."""
3
+
4
+ import os
5
+ import csv
6
+ import io
7
+ import math
8
+ import zipfile
9
+ from collections import Counter
10
+ from .profiler import score_network
11
+ from .constants import MAX_ONNX_FILESIZE, EXCLUDED_TASKS
12
+
13
+ try:
14
+ import wandb
15
+ except ImportError:
16
+ wandb = None
17
+
18
+
19
+ def run_tasks(task_nums, tasks, output_dir, providers, conv_budget, excluded_tasks, use_wandb):
20
+ """Run all tasks and collect results.
21
+
22
+ Returns: (results, costs_dict, total_score)
23
+ """
24
+ from .solvers.solver_registry import solve_task
25
+
26
+ results = {}
27
+ costs_dict = {}
28
+ total_score = 0
29
+
30
+ for tn in task_nums:
31
+ if tn not in tasks:
32
+ continue
33
+
34
+ td = tasks[tn]['data']
35
+ ok, sname, sz, t_task, model_path = solve_task(
36
+ tn, td, output_dir, providers, conv_budget, excluded_tasks
37
+ )
38
+
39
+ if ok:
40
+ macs, memory, params = score_network(model_path)
41
+ if macs is None:
42
+ macs, memory, params = 0, 0, 0
43
+ cost = macs + memory + params
44
+ score = max(1.0, 25.0 - math.log(max(1, cost)))
45
+ total_score += score
46
+
47
+ # Check per-file size limit
48
+ if sz and sz > MAX_ONNX_FILESIZE:
49
+ print(f"Task {tn:3d}: {sname:25s} OVER SIZE LIMIT ({sz:,} > {MAX_ONNX_FILESIZE:,})")
50
+ continue
51
+
52
+ results[tn] = (sname, t_task, sz)
53
+ costs_dict[tn] = cost
54
+ print(f"Task {tn:3d}: {sname:25s} {score:7.3f} {cost:>12} {t_task:7.3f}s ({sz:>8,} bytes)")
55
+ else:
56
+ score = 0
57
+ cost = 0
58
+ print(f"Task {tn:3d}: UNSOLVED {t_task:7.3f}s")
59
+
60
+ if use_wandb and wandb is not None:
61
+ wandb.log({
62
+ "task_id": tn,
63
+ "solver": sname if ok else "unsolved",
64
+ "onnx_bytes": sz if ok else 0,
65
+ "task_time_sec": t_task,
66
+ "cost": cost,
67
+ "score": score,
68
+ })
69
+
70
+ return results, costs_dict, total_score
71
+
72
+
73
+ def generate_submission(output_dir, results, costs_dict, active_tasks):
74
+ """Generate submission.zip and submission.csv.
75
+
76
+ Returns dict with submission info.
77
+ """
78
+ n_files = len([f for f in os.listdir(output_dir) if f.endswith('.onnx')])
79
+ total_size = sum(os.path.getsize(os.path.join(output_dir, f))
80
+ for f in os.listdir(output_dir) if f.endswith('.onnx'))
81
+
82
+ # Check per-file size limits
83
+ oversized = []
84
+ for f in os.listdir(output_dir):
85
+ if f.endswith('.onnx'):
86
+ fsize = os.path.getsize(os.path.join(output_dir, f))
87
+ if fsize > MAX_ONNX_FILESIZE:
88
+ oversized.append((f, fsize))
89
+
90
+ # Create submission.zip
91
+ parent_dir = os.path.dirname(output_dir) or '/kaggle/working/'
92
+ zip_path = os.path.join(parent_dir, 'submission.zip')
93
+ buf = io.BytesIO()
94
+ with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
95
+ for f in sorted(os.listdir(output_dir)):
96
+ if f.endswith('.onnx'):
97
+ zf.write(os.path.join(output_dir, f), f)
98
+ zip_bytes = buf.getvalue()
99
+ with open(zip_path, 'wb') as f:
100
+ f.write(zip_bytes)
101
+ zip_size = len(zip_bytes)
102
+
103
+ # Create submission.csv
104
+ csv_path = os.path.join(parent_dir, 'submission.csv')
105
+ with open(csv_path, 'w', newline='') as f:
106
+ w = csv.writer(f)
107
+ w.writerow(['task_id', 'total_cost'])
108
+ for tn in sorted(costs_dict.keys()):
109
+ w.writerow([f'task{tn:03d}', costs_dict[tn]])
110
+
111
+ unsolved_count = len(active_tasks) - len(results)
112
+ total_score = sum(max(1.0, 25.0 - math.log(max(1, cost))) for cost in costs_dict.values())
113
+ total_cost = sum(costs_dict.values())
114
+
115
+ return {
116
+ 'n_files': n_files,
117
+ 'total_size': total_size,
118
+ 'zip_path': zip_path,
119
+ 'zip_size': zip_size,
120
+ 'csv_path': csv_path,
121
+ 'total_score': total_score,
122
+ 'total_cost': total_cost,
123
+ 'unsolved_count': unsolved_count,
124
+ 'oversized': oversized,
125
+ }
126
+
127
+
128
+ def print_summary(results, submission_info, elapsed):
129
+ """Print summary statistics."""
130
+ active_count = submission_info['unsolved_count'] + len(results)
131
+
132
+ print(f"\n{'=' * 70}")
133
+ print(f"Solved: {len(results)}/{active_count} tasks in {elapsed:.0f}s")
134
+ solver_names = [v[0] for v in results.values()]
135
+ sc = Counter(solver_names)
136
+ for s, c in sc.most_common():
137
+ print(f" {s}: {c}")
138
+
139
+ print(f"\n{submission_info['n_files']} ONNX files, {submission_info['total_size'] / 1024:.1f} KB uncompressed")
140
+ print(f"ZIP size: {submission_info['zip_size'] / 1024:.1f} KB")
141
+
142
+ if submission_info['oversized']:
143
+ print(f"WARNING: {len(submission_info['oversized'])} files exceed 1.44MB limit:")
144
+ for f, sz in submission_info['oversized']:
145
+ print(f" {f}: {sz / 1024:.1f} KB")
146
+
147
+ print(f"\nEstimated LB score: {submission_info['total_score']:.1f}")
148
+ print(f"Total cost: {submission_info['total_cost']:,}")
149
+ print(f"Solved: {len(results)} | Unsolved: {submission_info['unsolved_count']}")
150
+ print(f"Written: {submission_info['zip_path']} | {submission_info['csv_path']}")