19
19
20
20
parser .add_argument ('--solutions' ,
21
21
'-s' ,
22
+ nargs = '*' ,
22
23
default = '' ,
23
- help = 'Filename of AI solutions to add to README, if any.' )
24
+ help = 'Filename(s) of AI solutions to add to README, if any.' )
24
25
25
26
parser .add_argument ('--json' ,
26
27
'-j' ,
50
51
51
52
52
53
def rename_src_var (orig , new , src , count = 0 ):
54
+ if orig == new :
55
+ return
56
+
53
57
def helper (s ):
54
58
return re .sub (r'\b' + orig + r'\b(?!["\'])' , new , s , count )
55
59
@@ -73,22 +77,38 @@ def indent(x, spaces=4):
73
77
return (" " * spaces + x .replace ("\n " , "\n " + " " * spaces ))[:- spaces if x .endswith ("\n " ) else None ]
74
78
75
79
76
- def save_readme (gen_modules , filename , sol_filename ):
77
- ai_sols = run_name = run_desc = None
78
- if sol_filename :
80
+ def save_readme (gen_modules , filename , sol_filenames ):
81
+ ai_sols = {}
82
+ for sol_filename in sol_filenames :
79
83
sols_js = utils .load_json (sol_filename )
80
- run_name = sols_js ["run_name" ]
81
- run_desc = sols_js ["run_desc" ]
82
- ai_sols = {}
83
- for f , entry in sols_js ["sols" ].items ():
84
- assert f .startswith ("def " )
85
- f_name = f [len ("def " ):f .index ("(" )].strip ()
86
- f2 = rename_src_var (f_name , "sat" , f , 1 )
87
- entry2 = ai_sols [f2 ] = entry .copy ()
88
- # g = entry2["sol"]
89
- g_name = "g" # g[len("def "):f.index("(")].strip()
90
- entry2 ["sol" ] = rename_src_var (g_name , "sol" , rename_src_var (f_name , "sat" , entry2 ["sol" ]))
91
- entry2 ["longest_sol" ] = rename_src_var (g_name , "sol" , rename_src_var (f_name , "sat" , entry2 ["longest_sol" ]))
84
+ for experiment in sols_js :
85
+ if "short" in experiment ["experiment" ]:
86
+ continue # skip short experiments
87
+ for s_s in experiment ["sat_sols" ]:
88
+ f = s_s ["sat" ]
89
+ assert f .startswith ("def " )
90
+ f_name = f [len ("def " ):f .index ("(" )].strip ()
91
+ f2 = rename_src_var (f_name , "sat" , f , 1 )
92
+ if f2 not in ai_sols :
93
+ ai_sols [f2 ] = dict (n_sols = 0 , n_attempts = 0 , sols = set ())
94
+ if "failures" in s_s : # bootstrap
95
+ ai_sols [f2 ]["n_attempts" ] += s_s ["failures" ]
96
+ if s_s .get ("sol" ):
97
+ ai_sols [f2 ]["n_sols" ] += 1
98
+ ai_sols [f2 ]["n_attempts" ] += 1
99
+ cur_sols = [s_s .get ("sol" )]
100
+ else :
101
+ ai_sols [f2 ]["n_attempts" ] += experiment ["n" ]
102
+ ai_sols [f2 ]["n_sols" ] += s_s ["n_sols" ]
103
+ cur_sols = [s_s [k ] for k in s_s if k .endswith ("_sol" )]
104
+ if "example_sols" in s_s :
105
+ cur_sols += s_s ["example_sols" ]
106
+ ai_sols [f2 ]["sols" ].update (rename_src_var (f_name , "sat" , sol ) for sol in cur_sols if sol )
107
+
108
+ for entry in ai_sols .values ():
109
+ entry ["sol" ] = (min (entry ["sols" ], key = len ) if entry ["sols" ] else "" )
110
+ entry ['longest_sol' ] = (max (entry ["sols" ], key = len ) if len (entry ["sols" ]) > 1 else "" )
111
+ entry ["success_rate" ] = entry ["n_sols" ]/ entry ["n_attempts" ]
92
112
93
113
table = ""
94
114
content = ""
@@ -106,7 +126,7 @@ def py(src):
106
126
puzzles = module_stuff ['examples' ]
107
127
if ai_sols :
108
128
puzzles = sorted (puzzles ,
109
- key = lambda f : ( ai_sols . get ( f ['sat' ]) or {}). get ( "num_sols" , 0 ) ,
129
+ key = lambda f : ai_sols [ f ['sat' ]][ "success_rate" ] if f [ 'sat' ] in ai_sols else 0 ,
110
130
reverse = True )
111
131
n = len (puzzles )
112
132
link = f"[{ sec_name } ](#{ anchor (sec_name )} )"
@@ -124,10 +144,10 @@ def py(src):
124
144
if ai_sols :
125
145
sol_entry = ai_sols .get (f )
126
146
if sol_entry :
127
- num_ai_sols = sol_entry ['num_sols ' ]
128
- puzzle_text += f"{ num_ai_sols :, } AI solution { 's' if num_ai_sols != 1 else '' } , "
147
+ num_ai_sols = sol_entry ['n_sols ' ]
148
+ puzzle_text += f"{ sol_entry [ 'success_rate' ] * 100 :.2g } % Codex success rate , "
129
149
else :
130
- puzzle_text += f"{ run_name } was not run on this puzzle, "
150
+ puzzle_text += f"Codex was not run on this puzzle, "
131
151
sol_bodies = puzzle ['sol_bodies' ]
132
152
n_sols = len (sol_bodies )
133
153
puzzle_text += f"{ n_sols :,} hand-written solution{ 's' if n_sols != 1 else '' } "
@@ -137,10 +157,14 @@ def py(src):
137
157
puzzle_text += "Solution docstring (*not* usually provided)\n \n "
138
158
puzzle_text += py (puzzle ['sol_docstring' ])
139
159
if num_ai_sols :
140
- puzzle_text += f"Shortest solution from { run_name } :\n "
141
- puzzle_text += py (sol_entry ['sol' ])
142
- puzzle_text += f"Longest solution from { run_name } :\n "
143
- puzzle_text += py (sol_entry ['longest_sol' ])
160
+ if sol_entry ['longest_sol' ]:
161
+ puzzle_text += f"Shortest Codex solution:\n "
162
+ puzzle_text += py (sol_entry ['sol' ])
163
+ puzzle_text += f"Longest Codex solution:\n "
164
+ puzzle_text += py (sol_entry ['longest_sol' ])
165
+ else :
166
+ puzzle_text += f"Codex solution:\n "
167
+ puzzle_text += py (sol_entry ['sol' ])
144
168
if n_sols :
145
169
for body in sol_bodies :
146
170
puzzle_text += "Hand-written solution:\n "
@@ -155,14 +179,14 @@ def py(src):
155
179
table += f"\n Total ({ tot_puzzles :,} problems, { tot_instances :,} instances)\n "
156
180
157
181
content = TOP .format (table ) + content
158
- if run_name :
182
+ if ai_sols :
159
183
content = content .replace (
160
184
"Summary of Puzzles" ,
161
- f"Summary of Puzzles and { run_name } solutions\n { run_desc } " ,
185
+ f"Summary of Puzzles and Codex solutions" ,
162
186
1
163
187
).replace (
164
188
"----" ,
165
- f"----\n \n The puzzles in each module are sorted by number of { run_name } solutions\n \n " ,
189
+ f"----\n \n The puzzles in each module are sorted by percent of Codex correct solutions\n \n " ,
166
190
1
167
191
)
168
192
0 commit comments