File size: 4,801 Bytes
3240d27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#evaluate_formulas.py
import re
import json
import os
from typing import List
from semantic_head import FormulaEvaluator, ExplanationLLM  

# -------------------------------------------------
# 0. Preprocessing / Cleaning garbled LaTeX
# -------------------------------------------------
def clean_garbled_latex(formula: str) -> str:
    formula = re.sub(r"\\underline\{\{.*?\}\}", "", formula)  # remove \underline{{...}}
    formula = re.sub(r"\\mit|\\bf", "", formula)               # remove OCR font artifacts
    formula = re.sub(r"\\l\\ell|\\L", "", formula)            # remove garbled letters
    formula = formula.replace(r"\rlap/", "")                  # remove broken \rlap/
    formula = re.sub(r"[\^\_]{2,}", "", formula)             # remove multiple consecutive ^ or _
    formula = re.sub(r"\{\s*\}", "", formula)                # remove empty braces
    formula = formula.strip()
    if len(formula) < 2:
        return ""
    return formula


# -------------------------------------------------
# 1. Extract formulas from LaTeX
# -------------------------------------------------
MATH_ENV_PATTERNS = [
    r"\$(.*?)\$",
    r"\\\((.*?)\\\)",
    r"\\\[(.*?)\\\]",
    r"\\begin\{equation\}(.*?)\\end\{equation\}",
]

def extract_formulas_from_tex(tex_content: str) -> List[str]:
    formulas = []
    for pattern in MATH_ENV_PATTERNS:
        matches = re.findall(pattern, tex_content, re.DOTALL)
        formulas.extend([m.strip() for m in matches])
    return formulas

# -------------------------------------------------
# 2. Automatic minor LaTeX fixes
# -------------------------------------------------
def fix_latex(formula: str) -> str:
    # Common minor fixes
    formula = re.sub(r"\\backslash\s*([A-Za-z])", r"\\setminus \1", formula)
    formula = formula.replace(r"\implies", r"\Rightarrow")
    return formula

# -------------------------------------------------
# 3. Evaluate formulas and store results
# -------------------------------------------------
def evaluate_tex_file(tex_path: str, output_dir: str, base_model=None, lora_dir=None):
    os.makedirs(output_dir, exist_ok=True)
    with open(tex_path, "r", encoding="utf-8") as f:
        tex_content = f.read()

    formulas = extract_formulas_from_tex(tex_content)
    print(f"Found {len(formulas)} formulas.")

    explainer = ExplanationLLM(base_model=base_model, lora_dir=lora_dir)
    evaluator = FormulaEvaluator(explainer)

    results = []
    for formula in formulas:
        cleaned = clean_garbled_latex(formula)
        if not cleaned:
            print(f"Skipping garbled formula: {formula[:30]}...")
            continue
        fixed_formula = fix_latex(cleaned)
        res = evaluator.evaluate(fixed_formula)
        res_entry = {
            "original_formula": formula,
            "fixed_formula": fixed_formula,
            **res
        }
        results.append(res_entry)

    # Save as JSON
    json_path = os.path.join(output_dir, "results_final.json")
    with open(json_path, "w", encoding="utf-8") as f:
        json.dump(results, f, indent=2)

    # Save as TXT summary
    txt_path = os.path.join(output_dir, "results_final.txt")
    with open(txt_path, "w", encoding="utf-8") as f:
        for r in results:
            f.write(f"Original Formula: {r['original_formula']}\n")
            f.write(f"Fixed Formula: {r['fixed_formula']}\n")
            f.write(f"Syntactically correct: {r['syntactically_correct']}\n")
            f.write(f"Mathematically correct: {r['mathematically_correct']}\n")
            f.write(f"Error type: {r['error_type']}\n")
            f.write(f"Confidence: {r['confidence']}\n")
            f.write(f"Source: {r['source']}\n")
            f.write(f"Suggested fix: {r.get('suggested_fix')}\n")
            f.write(f"Explanation:\n{r['explanation']}\n")
            f.write("="*80 + "\n")

    print(f"Results saved to {json_path} and {txt_path}")

# -------------------------------------------------
# 4. CLI usage
# -------------------------------------------------
if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(
        description="Evaluate formulas in a LaTeX file with automatic minor fixes and optional LoRA model."
    )
    parser.add_argument("tex_file", help="Path to the LaTeX file")
    parser.add_argument("--out", default="output", help="Output directory")
    parser.add_argument("--base_model", default="Qwen/Qwen2.5-Math-1.5B-Instruct",
                        help="Base model name")
    parser.add_argument("--lora_dir", default=None,
                        help="LoRA directory for fine-tuned model")

    args = parser.parse_args()

    evaluate_tex_file(
        tex_path=args.tex_file,
        output_dir=args.out,
        base_model=args.base_model,
        lora_dir=args.lora_dir
    )