Spaces:
Sleeping
Sleeping
Download src/plot2eq/data_prep/canonicalize.py from YauheniShe/Plot2Eq: direct link, hf CLI and curl.
- Browser
- Download file 3.45 kB
-
https://huggingface.co/spaces/YauheniShe/Plot2Eq/resolve/main/src/plot2eq/data_prep/canonicalize.py
- Command line
-
hf download hf://spaces/YauheniShe/Plot2Eq/src/plot2eq/data_prep/canonicalize.py
-
curl -L -o canonicalize.py https://huggingface.co/spaces/YauheniShe/Plot2Eq/resolve/main/src/plot2eq/data_prep/canonicalize.py
3.45 kB
| import gzip | |
| import pickle | |
| from pathlib import Path | |
| import sympy as sp | |
| from sympy.core.cache import clear_cache | |
| from tqdm import tqdm | |
| from plot2eq.core.tokenizer import InvalidExpressionError, Tokenizer | |
| def get_c_node(): | |
| return sp.Symbol("C", real=True) | |
| def has_top_level_shift(expr: sp.Expr) -> bool: | |
| if expr.is_Symbol and str(expr).startswith("C"): | |
| return True | |
| if expr.is_Add: | |
| for arg in expr.args: | |
| if has_top_level_shift(arg): # type: ignore | |
| return True | |
| return False | |
| def replace_cos_unevaluated(expr): | |
| if not expr.args: | |
| return expr | |
| new_args = [replace_cos_unevaluated(arg) for arg in expr.args] | |
| current_func = expr.func | |
| new_func = sp.sin if current_func == sp.cos else current_func | |
| return new_func(*new_args, evaluate=False) | |
| def clean_item(item, tokenizer: Tokenizer): | |
| try: | |
| tokens = item["tokens"] | |
| expr = tokenizer.token_seq_to_expr(tokens) | |
| if expr.has(sp.sin) and expr.has(sp.cos): | |
| return None | |
| processed_expr = replace_cos_unevaluated(expr) if expr.has(sp.cos) else expr | |
| if not has_top_level_shift(processed_expr): | |
| processed_expr = sp.Add(processed_expr, get_c_node(), evaluate=False) | |
| clear_expr = tokenizer.canonicalize_tree_structure(processed_expr) | |
| new_tokens = tokenizer.expr_to_token_seq(clear_expr) | |
| return { | |
| "expr_str": str(clear_expr), | |
| "expr_instantiated_str": item["expr_instantiated_str"], | |
| "tokens": new_tokens, | |
| "points": item["points"], | |
| } | |
| except InvalidExpressionError: | |
| return None | |
| def run_canonicalization(input_dir: Path, output_dir: Path, chunk_size: int = 50000): | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| tokenizer = Tokenizer() | |
| input_files = sorted(input_dir.glob("chunk_*.pkl.gz")) | |
| if not input_files: | |
| print("В папке не найдено чанков для обработки.") | |
| return | |
| cleaned_buffer = [] | |
| new_chunk_index = 0 | |
| total_processed, total_skipped = 0, 0 | |
| operations_count = 0 | |
| print(f"Найдено {len(input_files)} чанков. Начинаю канонизацию формул...") | |
| for filepath in tqdm(input_files, desc="Канонизация"): | |
| with gzip.open(filepath, "rb") as f: | |
| data = pickle.load(f) | |
| for item in data: | |
| operations_count += 1 | |
| if operations_count % 10000 == 0: | |
| clear_cache() | |
| cleaned = clean_item(item, tokenizer) | |
| if cleaned: | |
| cleaned_buffer.append(cleaned) | |
| else: | |
| total_skipped += 1 | |
| if len(cleaned_buffer) >= chunk_size: | |
| savepath = output_dir / f"chunk_{new_chunk_index}.pkl.gz" | |
| with gzip.open(savepath, "wb") as f_out: | |
| pickle.dump(cleaned_buffer[:chunk_size], f_out) | |
| total_processed += chunk_size | |
| cleaned_buffer = cleaned_buffer[chunk_size:] | |
| new_chunk_index += 1 | |
| if cleaned_buffer: | |
| savepath = output_dir / f"chunk_{new_chunk_index}.pkl.gz" | |
| with gzip.open(savepath, "wb") as f_out: | |
| pickle.dump(cleaned_buffer, f_out) | |
| total_processed += len(cleaned_buffer) | |
| print(f"Успешно очищено: {total_processed}. Пропущено ошибок: {total_skipped}.") | |