# AIMO: 36th Place Solution

Thanks to
[@abdurrafae](https://www.kaggle.com/abdurrafae)
's early sharing, we had a solid foundation already and we started with that. Initially what worked well are:
Improved the parsing method, so that there are less noise during voting
Early stopping of iterations, for example, we introduced something like the following in the begining of the iteration loop:
jj >= n_repetitions-: 
     len(occurances)>=:
        , freq2 = occurances[][], occurances[][]
         freq1 - freq2>=:
             = True
             best_stats[][], cond_iter_increase
If,
cond_iter_increase = True
then we could use an extra round of iteration in the next problem.
We observed from the log and the validation set that, for easier problems, if the answer is found, it can be found in even 10 or 11 iterations. But there are some problems (1-2 problems generally out of 50 problems in the validation set) where it helps with more iterations. After some experiments, we realised that, we can afford around 20/ 21 iterations for 50% of the problems and 10/11 iterations for the rest. So, we had the following setup:
prob_count = 
increase = False

 PRIVATE:
     test, sample_submission  iter_test:
        prob_count = prob_count + 
         prob_count>:
            n_repetitions =   increase  
        :
            n_repetitions =   increase  
        answer, increase = (test, n_repetitions)
        sample_submission = answer
        env(sample_submission)
        (test)
        (sample_submission)
The submission notebook is here:
[https://www.kaggle.com/code/indranilbhattacharya/aimo-2024-private-36th-place-solution/notebook](https://www.kaggle.com/code/indranilbhattacharya/aimo-2024-private-36th-place-solution/notebook)
While this was done a month ago, we picked this strategically as we reckoned that there could be many teams with same score, so we picked an older submission. Later we also tried with few other ideas. While, we still think some of them has potential, we could not get a steady result from validation and public LB.
Student- Teacher setup (Student generating the initial response and teacher validating that response)
Identify difficult problems earlier.
MCQ rounds for medium and difficult problems after early stopping. This gave good results in validation but without stability, so skipped this idea after a while. The idea is briefly as follows:
def final_pred(problem, n_repetitions, n_repetitions_mcq):
    occurances, best_stats, cond_iter_increase, hard = predict(problem, n_repetitions)
    (occurances)
    ()
    (best_stats)

      occurances   best_stats:
        return 24,  ## This happens when time limit exceeds  all other problems are predicted as 24

     len(occurances)<2:
        (, best_stats[0][0])
        return best_stats[0][0], cond_iter_increase

    option1, option2 = occurances[0][0], occurances[1][0]
    freq1, freq2 = occurances[0][1], occurances[1][1]

     freq1>=5:
        (, best_stats[0][0])
        return best_stats[0][0], cond_iter_increase

    all_options = [opt[0]  opt  occurances]

    ans_dict = {ans:freq  ans, freq  occurances}

    (, all_options)

    global model,tokenizer,USE_PAST_KEY

    final_message = f
    prompt = f
    (prompt)

    final_iterations = []

     m  tqdm(range(n_repetitions_mcq)):

        torch.cuda.empty_cache()
        gc.collect()

        model_inputs = tokenizer(prompt, =).to(model.device)
        input_len = len(model_inputs[][0])
        generation_output = model.generate(**model_inputs,
                                            =TOTAL_TOKENS,
                                            =USE_PAST_KEY,
                                            =,
                                            temperature = 0.7,
                                            top_p = 1.0,
                                            =1, =stopping_criteria)

        output_ids = generation_output.sequences[0]
        raw_output = tokenizer.decode(output_ids[input_len:], =)
        (f)
        result_output = process_text_output(raw_output)

        (, m,  , result_output)
         result_output!=-1:
            final_iterations.append(result_output)
             result_output  ans_dict:
                ans_dict[result_output] = ans_dict[result_output] + 1
                 ans_dict[result_output]>=5:
                    ()
                    return result_output, cond_iter_increase
            :
                ans_dict[result_output] = 1

    sorted_answers_combined = sorted(ans_dict.items(), =lambda x: x[1], =)

    combined_ans, combined_freq = sorted_answers_combined[0][0], sorted_answers_combined[0][1]
     combined_freq>=4:
        return combined_ans, cond_iter_increase

    counter = Counter(final_iterations)
    sorted_answers_mcq = sorted(counter.items(), =lambda x: x[1], =)

    ()
    (sorted_answers_mcq)

     sorted_answers_mcq  sorted_answers_mcq[0][1]>=2:
        final_try = sorted_answers_mcq[0][0]
         final_try  all_options:
            (, final_try)
            return final_try, cond_iter_increase 
         final_try   all_options:
            (,final_try)
            return final_try, cond_iter_increase 
        :
            ()
            return option1, cond_iter_increase

    :
        (, option1)
        return option1, cond_iter_increase