| | import re |
| | import ast |
| | import numpy as np |
| | from typing import Dict, Any, List, Optional, Set, Tuple |
| |
|
| | from validators.base import BaseValidator, Validator |
| |
|
| | class PhysicsValidator(BaseValidator, Validator): |
| | """物理シミュレーションのコード検証を行うクラス""" |
| | |
| | def __init__(self, client=None): |
| | """物理シミュレーション検証クラスの初期化""" |
| | super().__init__(client) |
| | self.validation_results = {} |
| | |
| | |
| | self.physics_keywords = { |
| | "mechanics": [ |
| | "force", "acceleration", "velocity", "position", "momentum", "energy", |
| | "力", "加速度", "速度", "位置", "運動量", "エネルギー", "質量", "重力" |
| | ], |
| | "fluid_dynamics": [ |
| | "pressure", "density", "viscosity", "flow", "drag", "lift", "reynolds", |
| | "圧力", "密度", "粘性", "流れ", "抵抗", "揚力", "レイノルズ" |
| | ], |
| | "thermodynamics": [ |
| | "temperature", "heat", "entropy", "thermal", "specific_heat", |
| | "温度", "熱", "エントロピー", "熱的", "比熱" |
| | ], |
| | "electromagnetism": [ |
| | "charge", "field", "magnetic", "electric", "potential", "current", |
| | "電荷", "場", "磁気", "電気", "ポテンシャル", "電流" |
| | ], |
| | "units": [ |
| | "meter", "kilogram", "second", "ampere", "kelvin", "newton", "joule", "watt", "pascal", |
| | "メートル", "キログラム", "秒", "アンペア", "ケルビン", "ニュートン", "ジュール", "ワット", "パスカル" |
| | ], |
| | "constants": [ |
| | "gravity", "g", "lightspeed", "c", "planck", "boltzmann", "avogadro", |
| | "重力定数", "光速", "プランク定数", "ボルツマン定数", "アボガドロ定数" |
| | ] |
| | } |
| | |
| | |
| | self.physics_patterns = { |
| | "newton_laws": [ |
| | r"F\s*=\s*m\s*[*]\s*a", |
| | r"force\s*=\s*mass\s*[*]\s*acceleration", |
| | r"action\s*[.=]\s*reaction", |
| | r"運動方程式", |
| | r"作用反作用" |
| | ], |
| | "conservation": [ |
| | r"energy\s*conserv", |
| | r"momentum\s*conserv", |
| | r"エネルギー保存", |
| | r"運動量保存" |
| | ], |
| | "fluid_equations": [ |
| | r"bernoulli", |
| | r"navier[\s-]*stokes", |
| | r"reynolds", |
| | r"ベルヌーイ", |
| | r"ナビエ[・\s]*ストークス", |
| | r"レイノルズ数" |
| | ], |
| | "integration_methods": [ |
| | r"euler\s*method", |
| | r"runge[\s-]*kutta", |
| | r"verlet", |
| | r"leapfrog", |
| | r"オイラー法", |
| | r"ルンゲ[・\s]*クッタ", |
| | r"ヴェルレ", |
| | r"リープフロッグ" |
| | ] |
| | } |
| | |
| | |
| | self.physics_libraries = { |
| | "python": ["numpy", "scipy", "matplotlib", "sympy", "pandas"], |
| | "cpp": ["eigen", "armadillo", "boost", "odeint", "gsl"], |
| | "julia": ["DifferentialEquations", "Flux", "Optim", "StaticArrays"] |
| | } |
| | |
| | |
| | self.numerical_issues = [ |
| | r"dt\s*>\s*[0-9.]+", |
| | r"step\s*>\s*[0-9.]+", |
| | r"dx\s*>\s*[0-9.]+", |
| | r"float", |
| | r"divide\s*by\s*zero", |
| | r"sqrt\s*\(\s*-", |
| | r"log\s*\(\s*[0<]", |
| | r"overflow", |
| | r"ゼロ除算", |
| | r"精度" |
| | ] |
| | |
| | async def validate(self, code, context=None): |
| | """物理シミュレーションの検証を実行する(インターフェース実装)""" |
| | physics_analysis = self.analyze_physics_simulation(code) |
| | |
| | if physics_analysis["is_physics_simulation"]: |
| | physics_correctness = self.analyze_physical_correctness( |
| | code, physics_analysis["physics_domain"] |
| | ) |
| | edge_cases = self.detect_edge_cases(code) |
| | |
| | self.validation_results = { |
| | "physics_analysis": physics_analysis, |
| | "physics_correctness": physics_correctness, |
| | "edge_cases": edge_cases |
| | } |
| | |
| | |
| | if not physics_correctness["is_physically_correct"]: |
| | code = self._add_physics_issues_as_comments(code, physics_correctness["issues"]) |
| | else: |
| | self.validation_results = {"is_physics_simulation": False} |
| | |
| | return code |
| | |
| | def get_result_summary(self): |
| | """検証結果の要約を返す(インターフェース実装)""" |
| | if not self.validation_results: |
| | return "物理シミュレーション検証はまだ実行されていません。" |
| | |
| | if not self.validation_results.get("is_physics_simulation", False): |
| | return "物理シミュレーションとして認識されませんでした。" |
| | |
| | correctness = self.validation_results.get("physics_correctness", {}) |
| | |
| | if correctness.get("is_physically_correct", True): |
| | return "物理シミュレーションは正確です。" |
| | |
| | issues = correctness.get("issues", []) |
| | return f"物理シミュレーションに問題があります: {', '.join(issues[:3])}" |
| | |
| | def _add_physics_issues_as_comments(self, code, issues): |
| | """物理的問題を元のコードに注釈として追加する""" |
| | |
| | header = "# 物理シミュレーションの問題点:\n" |
| | comments = "\n".join([f"# - {issue}" for issue in issues]) |
| | |
| | return f"{header}{comments}\n\n{code}" |
| | |
| | def analyze_physics_simulation(self, code: str, language: str = "python") -> Dict[str, Any]: |
| | """物理シミュレーションコードを分析する""" |
| | result = { |
| | "is_physics_simulation": False, |
| | "physics_domain": None, |
| | "implemented_laws": [], |
| | "numerical_method": None, |
| | "issues": [], |
| | "missing_elements": [], |
| | "stability_concerns": [], |
| | "accuracy_score": 0.0, |
| | "recommendations": [] |
| | } |
| | |
| | |
| | physics_terms_count = 0 |
| | for domain, terms in self.physics_keywords.items(): |
| | for term in terms: |
| | if re.search(r'\b' + re.escape(term) + r'\b', code, re.IGNORECASE): |
| | physics_terms_count += 1 |
| | if result["physics_domain"] is None and domain not in ["units", "constants"]: |
| | result["physics_domain"] = domain |
| | |
| | |
| | if physics_terms_count >= 5: |
| | result["is_physics_simulation"] = True |
| | else: |
| | |
| | return result |
| | |
| | |
| | for law_type, patterns in self.physics_patterns.items(): |
| | for pattern in patterns: |
| | if re.search(pattern, code, re.IGNORECASE): |
| | result["implemented_laws"].append(law_type) |
| | break |
| | |
| | |
| | result["implemented_laws"] = list(set(result["implemented_laws"])) |
| | |
| | |
| | if any(re.search(pattern, code, re.IGNORECASE) for pattern in self.physics_patterns["integration_methods"]): |
| | for pattern in self.physics_patterns["integration_methods"]: |
| | match = re.search(pattern, code, re.IGNORECASE) |
| | if match: |
| | result["numerical_method"] = match.group(0) |
| | break |
| | else: |
| | |
| | result["missing_elements"].append("explicit_numerical_method") |
| | result["recommendations"].append("明示的な数値積分法(オイラー法、ルンゲ・クッタ法など)を実装することを推奨します。") |
| | |
| | |
| | for issue_pattern in self.numerical_issues: |
| | if re.search(issue_pattern, code, re.IGNORECASE): |
| | result["stability_concerns"].append(issue_pattern) |
| | |
| | |
| | time_step_match = re.search(r'dt\s*=\s*([0-9.]+)', code) |
| | if time_step_match: |
| | dt_value = float(time_step_match.group(1)) |
| | if dt_value > 0.1: |
| | result["stability_concerns"].append("large_time_step") |
| | result["recommendations"].append(f"タイムステップ値({dt_value})が大きすぎる可能性があります。より小さな値を検討してください。") |
| | |
| | |
| | units_used = [] |
| | for unit in self.physics_keywords["units"]: |
| | if re.search(r'\b' + re.escape(unit) + r'\b', code, re.IGNORECASE): |
| | units_used.append(unit) |
| | |
| | if not units_used: |
| | result["missing_elements"].append("explicit_units") |
| | result["recommendations"].append("単位系を明示的に定義することを推奨します(例:SI単位系)。") |
| | |
| | |
| | if "conservation" not in result["implemented_laws"]: |
| | result["missing_elements"].append("conservation_laws") |
| | result["recommendations"].append("エネルギー保存則や運動量保存則の実装を検討してください。") |
| | |
| | |
| | if not re.search(r'boundary|境界条件|境界', code, re.IGNORECASE): |
| | result["missing_elements"].append("boundary_conditions") |
| | result["recommendations"].append("境界条件の明示的な処理を実装することを推奨します。") |
| | |
| | |
| | accuracy_score = 0.0 |
| | |
| | |
| | if result["numerical_method"] is not None: |
| | if "runge" in result["numerical_method"].lower() or "クッタ" in result["numerical_method"]: |
| | accuracy_score += 2.0 |
| | elif "verlet" in result["numerical_method"].lower() or "ヴェルレ" in result["numerical_method"]: |
| | accuracy_score += 1.5 |
| | else: |
| | accuracy_score += 1.0 |
| | |
| | |
| | if "conservation" in result["implemented_laws"]: |
| | accuracy_score += 1.0 |
| | |
| | |
| | if units_used: |
| | accuracy_score += 0.5 |
| | |
| | |
| | if "boundary_conditions" not in result["missing_elements"]: |
| | accuracy_score += 0.5 |
| | |
| | |
| | if not result["stability_concerns"]: |
| | accuracy_score += 1.0 |
| | |
| | result["accuracy_score"] = min(5.0, accuracy_score) |
| | |
| | |
| | self._add_additional_recommendations(result, code, language) |
| | |
| | return result |
| | |
| | def _add_additional_recommendations(self, result: Dict[str, Any], code: str, language: str) -> None: |
| | """追加の分析と推奨事項を生成する""" |
| | |
| | if language in self.physics_libraries: |
| | recommended_libraries = self.physics_libraries[language] |
| | libraries_used = [] |
| | |
| | for lib in recommended_libraries: |
| | if re.search(r'(import|using|include).*\b' + re.escape(lib) + r'\b', code, re.IGNORECASE): |
| | libraries_used.append(lib) |
| | |
| | |
| | usage_ratio = len(libraries_used) / len(recommended_libraries) |
| | |
| | if usage_ratio < 0.3 and result["is_physics_simulation"]: |
| | missing_libs = [lib for lib in recommended_libraries if lib not in libraries_used] |
| | result["recommendations"].append(f"物理シミュレーションに有用なライブラリの使用を検討してください: {', '.join(missing_libs[:3])}") |
| | |
| | |
| | if not re.search(r'(test|check|verify|validate).*edge.*case', code, re.IGNORECASE) and not re.search(r'境界|エッジケース|極端', code, re.IGNORECASE): |
| | result["recommendations"].append("極端な入力値や境界条件でのテストコードを追加することを推奨します。") |
| | |
| | |
| | if result["numerical_method"] is not None: |
| | if "euler" in result["numerical_method"].lower() or "オイラー" in result["numerical_method"]: |
| | |
| | result["recommendations"].append("オイラー法は単純ですが精度が低いです。より高精度な数値積分法(ルンゲクッタ法など)の使用を検討してください。") |
| | elif "runge" in result["numerical_method"].lower() or "クッタ" in result["numerical_method"]: |
| | |
| | if not re.search(r'adaptive|step.*size|可変|ステップ.*サイズ', code, re.IGNORECASE): |
| | result["recommendations"].append("適応的なステップサイズ制御を使用して計算効率を向上させることを検討してください。") |
| | |
| | |
| | stability_terms = ["stability", "cfl", "courant", "安定性", "クーラン"] |
| | has_stability_analysis = any(re.search(r'\b' + re.escape(term) + r'\b', code, re.IGNORECASE) for term in stability_terms) |
| | |
| | if not has_stability_analysis: |
| | result["recommendations"].append("数値安定性の解析(CFLなど)を追加することを推奨します。") |
| | |
| | |
| | validation_terms = ["error", "validate", "verification", "accuracy", "誤差", "検証", "精度"] |
| | has_validation = any(re.search(r'\b' + re.escape(term) + r'\b', code, re.IGNORECASE) for term in validation_terms) |
| | |
| | if not has_validation: |
| | result["recommendations"].append("シミュレーション結果の誤差評価または検証の追加を検討してください。") |
| | |
| | def analyze_physical_correctness(self, code: str, physics_type: str = None) -> Dict[str, Any]: |
| | """物理シミュレーションの物理的正確性を分析する""" |
| | result = { |
| | "is_physically_correct": True, |
| | "issues": [], |
| | "correctness_score": 0.0 |
| | } |
| | |
| | |
| | basic_analysis = self.analyze_physics_simulation(code) |
| | |
| | |
| | if not basic_analysis["is_physics_simulation"]: |
| | result["is_physically_correct"] = False |
| | result["issues"].append("物理シミュレーションとして認識できるコードではありません。") |
| | return result |
| | |
| | |
| | physics_domain = physics_type or basic_analysis["physics_domain"] |
| | |
| | |
| | if physics_domain == "mechanics": |
| | |
| | self._check_mechanics_correctness(code, result) |
| | elif physics_domain == "fluid_dynamics": |
| | |
| | self._check_fluid_dynamics_correctness(code, result) |
| | elif physics_domain == "thermodynamics": |
| | |
| | self._check_thermodynamics_correctness(code, result) |
| | elif physics_domain == "electromagnetism": |
| | |
| | self._check_electromagnetism_correctness(code, result) |
| | |
| | |
| | self._check_general_physics_correctness(code, result) |
| | |
| | |
| | for missing in basic_analysis["missing_elements"]: |
| | if missing == "conservation_laws": |
| | result["is_physically_correct"] = False |
| | result["issues"].append("保存則(エネルギー保存、運動量保存など)が実装されていません。") |
| | elif missing == "boundary_conditions": |
| | result["issues"].append("境界条件の明示的な処理が見つかりません。") |
| | |
| | for concern in basic_analysis["stability_concerns"]: |
| | result["issues"].append(f"数値的安定性の問題: {concern}") |
| | |
| | |
| | correctness_score = basic_analysis["accuracy_score"] * 2.0 |
| | |
| | |
| | correctness_score -= len(result["issues"]) * 0.5 |
| | |
| | |
| | result["correctness_score"] = max(0.0, min(10.0, correctness_score)) |
| | |
| | |
| | result["is_physically_correct"] = result["correctness_score"] >= 7.0 and not any("保存則" in issue for issue in result["issues"]) |
| | |
| | return result |
| | |
| | def _check_mechanics_correctness(self, code: str, result: Dict[str, Any]) -> None: |
| | """力学シミュレーションの正確性をチェックする""" |
| | |
| | if not re.search(r'F\s*=\s*m\s*[*]\s*a|force\s*=\s*mass\s*[*]\s*acceleration|運動方程式', code, re.IGNORECASE): |
| | result["is_physically_correct"] = False |
| | result["issues"].append("ニュートンの運動方程式(F = ma)が明示的に実装されていません。") |
| | |
| | |
| | if re.search(r'gravity|重力', code, re.IGNORECASE) and not re.search(r'9\.8|G\s*=\s*6\.67', code): |
| | result["issues"].append("重力定数の適切な値が使用されていない可能性があります。") |
| | |
| | |
| | if re.search(r'collision|衝突', code, re.IGNORECASE): |
| | if not re.search(r'elastic|inelastic|coefficient\s*of\s*restitution|反発係数|弾性', code, re.IGNORECASE): |
| | result["issues"].append("衝突処理において反発係数や弾性/非弾性の区別が明確でありません。") |
| | |
| | def _check_fluid_dynamics_correctness(self, code: str, result: Dict[str, Any]) -> None: |
| | """流体力学シミュレーションの正確性をチェックする""" |
| | |
| | if not re.search(r'continuity|divergence|連続の式|発散', code, re.IGNORECASE): |
| | result["is_physically_correct"] = False |
| | result["issues"].append("流体の連続の式が実装されていません。") |
| | |
| | |
| | if not re.search(r'navier[\s-]*stokes|ナビエ[・\s]*ストークス', code, re.IGNORECASE): |
| | if not re.search(r'bernoulli|euler\s*equation|ベルヌーイ|オイラー方程式', code, re.IGNORECASE): |
| | result["issues"].append("標準的な流体方程式(ナビエ・ストークス、オイラー、ベルヌーイなど)が見つかりません。") |
| | |
| | |
| | if re.search(r'viscos|粘性', code, re.IGNORECASE): |
| | if not re.search(r'reynolds|レイノルズ', code, re.IGNORECASE): |
| | result["issues"].append("粘性流体のレイノルズ数による特性評価が見つかりません。") |
| | |
| | def _check_thermodynamics_correctness(self, code: str, result: Dict[str, Any]) -> None: |
| | """熱力学シミュレーションの正確性をチェックする""" |
| | |
| | if not re.search(r'first\s*law|熱力学第一法則|エネルギー保存', code, re.IGNORECASE): |
| | result["is_physically_correct"] = False |
| | result["issues"].append("熱力学第一法則(エネルギー保存則)が実装されていません。") |
| | |
| | |
| | if not re.search(r'entropy|second\s*law|エントロピー|熱力学第二法則', code, re.IGNORECASE): |
| | result["issues"].append("熱力学第二法則(エントロピー増大の法則)が考慮されていません。") |
| | |
| | |
| | if re.search(r'temperature|温度', code, re.IGNORECASE) and not re.search(r'kelvin|ケルビン|絶対温度', code, re.IGNORECASE): |
| | if re.search(r'<\s*0', code): |
| | result["issues"].append("温度が絶対零度未満になる可能性があります。絶対温度(ケルビン)を使用してください。") |
| | |
| | def _check_electromagnetism_correctness(self, code: str, result: Dict[str, Any]) -> None: |
| | """電磁気学シミュレーションの正確性をチェックする""" |
| | |
| | maxwell_terms = ["maxwell", "gauss", "ampere", "faraday", "マクスウェル", "ガウス", "アンペール", "ファラデー"] |
| | has_maxwell = any(re.search(r'\b' + re.escape(term) + r'\b', code, re.IGNORECASE) for term in maxwell_terms) |
| | |
| | if not has_maxwell: |
| | result["is_physically_correct"] = False |
| | result["issues"].append("マクスウェル方程式または関連法則(ガウス、アンペール、ファラデーなど)が実装されていません。") |
| | |
| | |
| | if re.search(r'charge|電荷', code, re.IGNORECASE) and not re.search(r'coulomb|クーロン', code, re.IGNORECASE): |
| | result["issues"].append("電荷間の相互作用にクーロンの法則が使用されていない可能性があります。") |
| | |
| | |
| | if re.search(r'(electric.*magnetic|磁場.*電場|電場.*磁場)', code, re.IGNORECASE): |
| | if not re.search(r'lorentz|ローレンツ', code, re.IGNORECASE): |
| | result["issues"].append("電磁場における荷電粒子の運動にローレンツ力が考慮されていない可能性があります。") |
| | |
| | def _check_general_physics_correctness(self, code: str, result: Dict[str, Any]) -> None: |
| | """一般的な物理シミュレーションの正確性をチェックする""" |
| | |
| | units_pattern = r'\b(meters?|kilograms?|seconds?|amperes?|kelvins?|newtons?|joules?|watts?|pascals?|メートル|キログラム|秒|アンペア|ケルビン|ニュートン|ジュール|ワット|パスカル)\b' |
| | units_mentioned = re.findall(units_pattern, code, re.IGNORECASE) |
| | |
| | if units_mentioned: |
| | |
| | si_units = ["meter", "kilogram", "second", "ampere", "kelvin", "メートル", "キログラム", "秒", "アンペア", "ケルビン"] |
| | non_si_units = ["feet", "pound", "mile", "gallon", "フィート", "ポンド", "マイル", "ガロン"] |
| | |
| | uses_si = any(re.search(r'\b' + re.escape(unit) + r'\b', code, re.IGNORECASE) for unit in si_units) |
| | uses_non_si = any(re.search(r'\b' + re.escape(unit) + r'\b', code, re.IGNORECASE) for unit in non_si_units) |
| | |
| | if uses_si and uses_non_si: |
| | result["is_physically_correct"] = False |
| | result["issues"].append("SI単位系と非SI単位系が混在しています。単位系を統一してください。") |
| | |
| | |
| | physics_constants = { |
| | "gravity": r"g\s*=\s*9\.8", |
| | "light_speed": r"c\s*=\s*299792458", |
| | "planck": r"h\s*=\s*6\.626", |
| | "boltzmann": r"k\s*=\s*1\.380649", |
| | "gravitational": r"G\s*=\s*6\.674", |
| | "avogadro": r"N_A\s*=\s*6\.022" |
| | } |
| | |
| | for const_name, pattern in physics_constants.items(): |
| | if re.search(r'\b' + const_name + r'\b', code, re.IGNORECASE) and not re.search(pattern, code): |
| | approximate_pattern = pattern.split('.')[0] + r"\." |
| | if not re.search(approximate_pattern, code): |
| | result["issues"].append(f"{const_name}定数の値が標準的な物理定数と一致していない可能性があります。") |
| | |
| | |
| | if not re.search(r'initial\s*condition|初期条件', code, re.IGNORECASE): |
| | result["issues"].append("明示的な初期条件の設定が見つかりません。") |
| | |
| | if not re.search(r'boundary\s*condition|境界条件', code, re.IGNORECASE): |
| | result["issues"].append("明示的な境界条件の設定が見つかりません。") |
| | |
| | |
| | if re.search(r'time\s*step|time\s*evolution|dt\s*=|時間ステップ|時間発展', code, re.IGNORECASE): |
| | if not re.search(r'forward|backward|前進|後退', code, re.IGNORECASE): |
| | result["issues"].append("時間発展の方向性(前進法/後退法)が明示されていません。") |
| | |
| | def detect_edge_cases(self, code: str) -> List[Dict[str, Any]]: |
| | """物理シミュレーションコードにおけるエッジケースを検出する""" |
| | edge_cases = [] |
| | |
| | |
| | division_patterns = [ |
| | r'/\s*0', |
| | r'/\s*\(\s*[a-zA-Z_]\w*\s*\)', |
| | r'/\s*\(\s*.*\s*\)' |
| | ] |
| | |
| | for pattern in division_patterns: |
| | for match in re.finditer(pattern, code): |
| | context = code[max(0, match.start() - 20):min(len(code), match.end() + 20)] |
| | edge_cases.append({ |
| | "type": "zero_division", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": context, |
| | "description": "ゼロ除算の可能性があります。分母がゼロになる場合の処理を追加してください。" |
| | }) |
| | |
| | |
| | sqrt_patterns = [ |
| | r'sqrt\s*\(\s*-', |
| | r'sqrt\s*\(\s*[a-zA-Z_]\w*\s*\)' |
| | ] |
| | |
| | for pattern in sqrt_patterns: |
| | for match in re.finditer(pattern, code): |
| | context = code[max(0, match.start() - 20):min(len(code), match.end() + 20)] |
| | edge_cases.append({ |
| | "type": "negative_sqrt", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": context, |
| | "description": "平方根の引数が負になる可能性があります。値のチェックを追加してください。" |
| | }) |
| | |
| | |
| | log_patterns = [ |
| | r'log\s*\(\s*0', |
| | r'log\s*\(\s*-', |
| | r'log\s*\(\s*[a-zA-Z_]\w*\s*\)' |
| | ] |
| | |
| | for pattern in log_patterns: |
| | for match in re.finditer(pattern, code): |
| | context = code[max(0, match.start() - 20):min(len(code), match.end() + 20)] |
| | edge_cases.append({ |
| | "type": "invalid_log", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": context, |
| | "description": "対数の引数がゼロまたは負になる可能性があります。値のチェックを追加してください。" |
| | }) |
| | |
| | |
| | array_access_patterns = [ |
| | r'\[\s*i\s*\]', |
| | r'\[\s*j\s*\]', |
| | r'\[\s*k\s*\]', |
| | r'\[\s*i\s*\+', |
| | r'\[\s*i\s*\-', |
| | ] |
| | |
| | for pattern in array_access_patterns: |
| | for match in re.finditer(pattern, code): |
| | |
| | context_start = max(0, match.start() - 50) |
| | context_end = min(len(code), match.end() + 50) |
| | context = code[context_start:context_end] |
| | |
| | |
| | range_check = re.search(r'if\s*\(\s*[ijk]\s*[<>=]', context) |
| | |
| | if not range_check: |
| | edge_cases.append({ |
| | "type": "index_out_of_bounds", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": context, |
| | "description": "配列の範囲外アクセスの可能性があります。インデックスの範囲チェックを追加してください。" |
| | }) |
| | |
| | |
| | loop_patterns = [ |
| | r'while\s*\(\s*true\s*\)', |
| | r'while\s*\(\s*1\s*\)', |
| | r'for\s*\(\s*;', |
| | r'while\s*\(\s*[a-zA-Z_]\w*\s*\)' |
| | ] |
| | |
| | for pattern in loop_patterns: |
| | for match in re.finditer(pattern, code): |
| | |
| | context_start = match.end() |
| | context_end = min(len(code), match.end() + 200) |
| | loop_body = code[context_start:context_end] |
| | |
| | |
| | break_condition = re.search(r'break|return|exit', loop_body) |
| | |
| | if not break_condition: |
| | edge_cases.append({ |
| | "type": "infinite_loop", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": code[max(0, match.start() - 20):match.end() + 20], |
| | "description": "無限ループの可能性があります。脱出条件を追加してください。" |
| | }) |
| | |
| | |
| | physics_var_patterns = [ |
| | (r'mass\s*=\s*-', "負の質量"), |
| | (r'density\s*=\s*-', "負の密度"), |
| | (r'temperature\s*=\s*-273', "絶対零度以下の温度"), |
| | (r'速度\s*=\s*[0-9.]+e[+]?[0-9]+', "光速を超える可能性のある速度"), |
| | (r'velocity\s*=\s*[0-9.]+e[+]?[0-9]+', "光速を超える可能性のある速度") |
| | ] |
| | |
| | for pattern, desc in physics_var_patterns: |
| | for match in re.finditer(pattern, code): |
| | edge_cases.append({ |
| | "type": "invalid_physics_value", |
| | "pattern": pattern, |
| | "location": match.span(), |
| | "context": code[max(0, match.start() - 20):min(len(code), match.end() + 20)], |
| | "description": f"物理的に不適切な値の可能性: {desc}. 値の範囲チェックを追加してください。" |
| | }) |
| | |
| | return edge_cases |