end000's picture
Release Sol014 mathematical specialization with paired evaluations, regressions and exact replay artifacts
fc32096 verified
Raw History Blame Contribute Delete
9.89 kB
import json
from transformers import AutoTokenizer
from common import ROOT, save_json
cases = [
('receipts', 'Eight notebooks cost 5 dollars each and three pens cost 4 dollars each. What is the total cost?',
'The notebooks cost 8 times 5, which is 40 dollars. The pens cost 3 times 4, which is 12 dollars.',
'Adding the two purchases gives 40 plus 12, or 52 dollars. Another check is to pay for the notebooks first, then add the separate 12 dollar purchase. Both groups have already been counted exactly once. The total is therefore 52 dollars.',
'But have the notebooks already been counted? They cost 40 dollars. Let me check the pens again. They cost 12 dollars.'),
('linear', 'Solve 5x + 7 = 42.',
'Subtracting 7 from both sides gives 5x = 35.',
'Dividing both sides by 5 gives x equal to 7. Substitution checks the result: five times seven plus seven equals thirty five plus seven, which is forty two. The same value satisfies the original equation, so no further adjustment is needed.',
'But should I subtract 7 again? Five x is 35. Wait, perhaps I should check the subtraction once more.'),
('modular', 'Find the remainder of 3^13 when divided by 7.',
'The powers of 3 modulo 7 cycle through 3, 2, 6, 4, 5, 1 with period 6.',
'Thirteen leaves remainder one upon division by six. Thus the thirteenth power has the same remainder as the first power, namely three. We can check by writing the exponent as twelve plus one: the twelfth power contributes one modulo seven, leaving a factor of three.',
'But is the cycle really six? The powers return to one after six steps. Let me start the cycle again to check.'),
('rectangle', 'A rectangle has perimeter 34 cm and length 11 cm. Find its area.',
'Half the perimeter is 17 cm. Subtracting the length 11 leaves width 6 cm.',
'The area is the product of the two side lengths, eleven times six, giving sixty six square centimetres. The perimeter check is two times the sum eleven plus six, equal to thirty four centimetres. Both conditions agree with the stated dimensions.',
'But perhaps 17 is the width? No, it is half the perimeter. Let me check whether I should subtract eleven again.'),
('probability', 'A bag contains four white balls and three black balls. Draw two without replacement. What is the probability both are white?',
'The probability the first ball is white is 4/7. After that, three white balls remain among six balls.',
'Multiplying four sevenths by three sixths gives twelve forty seconds, or two sevenths. Counting unordered pairs gives the same result: six white pairs out of twenty one possible pairs. The two methods agree because both account for drawing without replacement.',
'But are there still four white balls after drawing one? No, three remain. I should check the remaining number of balls again.'),
('speed', 'A cyclist travels at 72 kilometres per hour for 35 minutes. How many kilometres does the cyclist travel?',
'Thirty five minutes is 35/60 hours. Distance equals speed multiplied by time.',
'The product seventy two times thirty five divided by sixty equals forty two kilometres. Equivalently, the cyclist covers one point two kilometres each minute, and thirty five such minutes give forty two. The conversion is consistent because both calculations use the same duration.',
'But should the minutes be divided by sixty? Yes, an hour has sixty minutes. Let me check the conversion again.'),
('series', 'Find the sum of the first fifteen positive multiples of three.',
'The sum is three times the sum of the integers from 1 through 15.',
'The integer sum is fifteen times sixteen divided by two, equal to one hundred twenty. Multiplying by three gives three hundred sixty. Pairing the first multiple three with the last multiple forty five gives forty eight per pair and yields the same total.',
'But is fifteen the last multiple or the number of terms? It is the number of terms. Let me count the terms again.'),
('roots', 'Find all real roots of x^2 - 9x + 20 = 0.',
'Two numbers whose product is 20 and sum is 9 are 4 and 5.',
'The polynomial factors into the product of x minus four and x minus five. A product equals zero when either factor is zero, giving roots four and five. Their sum is nine and their product is twenty, confirming both coefficients of the original polynomial.',
'But should the roots be negative four and negative five? The factors use minus signs. Let me check the signs again.'),
('transfer_fraction', 'A tank is three fifths full. Adding 18 litres fills it. What is its capacity?',
'The missing two fifths correspond to 18 litres.',
'One fifth therefore corresponds to nine litres. Five such parts give a total capacity of forty five litres. Checking the initial contents, three fifths is twenty seven litres, and adding eighteen reaches forty five. This matches the full capacity.',
'But does eighteen correspond to three fifths? No, it corresponds to the missing part. I should check the missing fraction again.'),
('transfer_triangle', 'Find the hypotenuse of a right triangle whose legs are 9 and 12.',
'The squared hypotenuse is 9 squared plus 12 squared, equal to 81 plus 144.',
'Their sum is two hundred twenty five. Its positive square root is fifteen, so the hypotenuse is fifteen units. The triple nine, twelve, fifteen is three times the familiar triple three, four, five, providing another check of the calculation.',
'But should I add the squares or subtract them? Both given sides are legs. Let me check the same two squares again.'),
('transfer_count', 'How many different committees of two can be chosen from six people?',
'The order of the two members does not matter.',
'There are six choices for a first person and five choices for a different second person. This counts every unordered committee twice, so dividing thirty by two gives fifteen committees. Equivalently, choosing two out of six directly gives the binomial coefficient fifteen.',
'But perhaps the order matters after all? A committee has no first or second member. I should check whether to divide by two again.'),
('transfer_percent', 'A 240 dollar coat is discounted by 15 percent. Find its sale price.',
'Ten percent of 240 is 24, and five percent is 12.',
'The total discount is thirty six dollars. Subtracting thirty six from two hundred forty leaves two hundred four dollars. Multiplying the original price by eighty five percent also gives two hundred four, which verifies the sale price directly.',
'But is thirty six the sale price or the discount? It is the discount. Let me calculate fifteen percent once again.'),
]
tok = AutoTokenizer.from_pretrained(ROOT / 'models/original', local_files_only=True)
instruction = json.loads((ROOT / 'configs/protocol.json').read_text())['instruction']
texts, labels, inputs = [], [], []
for pair, (name, problem, common, productive, loop) in enumerate(cases):
prompt = tok.apply_chat_template([{'role':'user','content':problem+'\n'+instruction}], tokenize=False,
add_generation_prompt=True, enable_thinking=True)
prefix = prompt + common + ' '
for condition, branch in [('productive', productive), ('repetitive', ' '.join([loop] * 5))]:
text = prefix + branch
encoded = tok(text, add_special_tokens=False, return_offsets_mapping=True)
start = next(i for i, (_, end) in enumerate(encoded['offset_mapping']) if end > len(prefix))
tokens = encoded['input_ids']
if condition == 'productive':
matched_length = len(tokens)
else:
if len(tokens) < matched_length:
raise ValueError('Repetition branch is too short for length matching')
tokens = tokens[:matched_length]
text = tok.decode(tokens, skip_special_tokens=False)
labels.append({'text':len(texts), 'pair':pair, 'name':name, 'split':'discovery' if pair < 8 else 'transfer',
'condition':condition,'branch_start':start,'tokens':len(tokens),
'mean_window':[len(tokens)-48, len(tokens)]})
texts.append(text)
inputs.append(tokens)
for pair in range(8, 12):
name, problem, _, _, _ = cases[pair]
prompt = tok.apply_chat_template([{'role':'user','content':problem+'\n'+instruction}], tokenize=False,
add_generation_prompt=True, enable_thinking=True)
prefix = prompt + 'I need to work out the solution. '
text = prefix + '</think>\n\\boxed{0}'
encoded = tok(text, add_special_tokens=False, return_offsets_mapping=True)
start = next(i for i, (_, end) in enumerate(encoded['offset_mapping']) if end > len(prefix))
labels.append({'text':len(texts),'pair':pair,'name':name,'split':'transfer','condition':'premature_close',
'branch_start':start,'tokens':len(encoded['input_ids']),
'mean_window':[max(0,len(encoded['input_ids'])-48),len(encoded['input_ids'])]})
texts.append(text)
inputs.append(encoded['input_ids'])
save_json(ROOT / 'configs/matched_probe_001.json', {'token_ids':inputs,'texts':texts,'chunk_size':256,
'return':{'token_logprobs':True,'topk':0,'hidden_states':list(range(25)),'mlp_act':list(range(24)),'attn_layers':[]}})
save_json(ROOT / 'configs/matched_probe_001_labels.json', labels)
save_json(ROOT / 'configs/transfer_probe_001.json', {'token_ids':inputs[16:],'texts':texts[16:],'chunk_size':256,
'return':{'token_logprobs':True,'topk':0,'hidden_states':[],'mlp_act':[],'attn_layers':[]}})
save_json(ROOT / 'configs/transfer_probe_001_labels.json', [dict(r,text=r['text']-16) for r in labels if r['text']>=16])
print('Prepared 8 discovery pairs and 4 transfer pairs; no network execution.')