Files
Jyotisha/benchmarks/jyotish/scripts/run_chara_dasha_knrao.py
T
732642856 c4c0eff67a v6.1.12: Chara Dasha KN Rao Benchmark正式通过(95.83%)
PyJHora oracle benchmark 10案例×120字段:
- Sign Sequence: 120/120 = 100.00%
- Duration: 110/120 = 91.67%
- Overall: 230/240 = 95.83% >= 95%  PASS

修复:
- <=0检查顺序对齐PyJHora(先于尊贵调整)
- _PLANET_DIGNITY_KNRAO表(含Rahu/Ketu+set检查+Mercury own sign排除)
- _resolve_chara_dasha_lord()动态宫主判定框架
- bench脚本含Rahu/Ketu行星映射

已知限制: ~4.2%差异来自Aquarius/Scorpio共主动态判定(未来优化)
2026-06-11 13:40:50 +08:00

173 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Chara Dasha KN Rao Benchmark v1.1
比较 v6.1.11 yinduzhanxing Chara Dasha 与 PyJHora KN Rao method。
策略:用 PyJHora 计算行星位置作为共享输入,两个实现基于相同数据运行。
这样隔离算法差异,消除天文计算差异。
依赖: pip install jhora numpy
"""
import sys, json, os
# 添加scripts路径
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'scripts')))
from jaimini import SIGNS, _chara_dasha_duration_knrao, _chara_progression_knrao, _EVEN_FOOTED_SIGNS
# PyJHora
from jhora.horoscope.dhasa.raasi import chara as pj_chara
from jhora.horoscope.chart import charts
from jhora.panchanga import drik
from jhora import const, utils
# ─────────────────────────────────────────────
# 10个测试案例(与Round 7相同)
# ─────────────────────────────────────────────
TEST_CASES = [
{"id": "smoke_beijing_1990_noon", "year":1990, "month":6, "day":15, "hour":12, "minute":0, "lat":39.9, "lon":116.4, "tz":8},
{"id": "smoke_newyork_1985_morning", "year":1985, "month":3, "day":22, "hour":9, "minute":30, "lat":40.7, "lon":-74.0, "tz":-5},
{"id": "smoke_london_1970_evening", "year":1970, "month":9, "day":12, "hour":19, "minute":0, "lat":51.5, "lon":-0.1, "tz":0},
{"id": "smoke_delhi_2000_midnight", "year":2000, "month":1, "day":1, "hour":0, "minute":0, "lat":28.6, "lon":77.2, "tz":5.5},
{"id": "smoke_sydney_1999_afternoon", "year":1999, "month":8, "day":7, "hour":15, "minute":45, "lat":-33.9, "lon":151.2, "tz":10},
{"id": "smoke_tokyo_1964_noon", "year":1964, "month":10, "day":10,"hour":12, "minute":0, "lat":35.7, "lon":139.7, "tz":9},
{"id": "smoke_cairo_1952_dawn", "year":1952, "month":7, "day":23, "hour":6, "minute":0, "lat":30.0, "lon":31.2, "tz":2},
{"id": "smoke_paris_1989_noon", "year":1989, "month":11,"day":9, "hour":12, "minute":30, "lat":48.9, "lon":2.3, "tz":1},
{"id": "smoke_losangeles_1995_night", "year":1995, "month":2, "day":14, "hour":22, "minute":15, "lat":34.1, "lon":-118.2,"tz":-8},
{"id": "smoke_sao_paulo_2004_morning","year":2004, "month":12,"day":25, "hour":7, "minute":0, "lat":-23.5, "lon":-46.6, "tz":-3},
]
# 行星名称到PyJHora ID
PLANET_NAMES = {
const.SUN_ID: "Sun", const.MOON_ID: "Moon", const.MARS_ID: "Mars",
const.MERCURY_ID: "Mercury", const.JUPITER_ID: "Jupiter", const.VENUS_ID: "Venus",
const.SATURN_ID: "Saturn", const.RAHU_ID: "Rahu", const.KETU_ID: "Ketu",
}
def run_benchmark():
total_sign = 0; sign_match = 0
total_dur = 0; dur_match = 0
detail_lines = []
sample_details = []
for case in TEST_CASES:
# 1. 用 PyJHora 获取行星位置
dob = drik.Date(case["year"], case["month"], case["day"])
tob = (case["hour"], case["minute"], 0)
place = drik.Place(f'test_{case["id"]}', case["lat"], case["lon"], case["tz"])
jd = utils.julian_day_number(dob, tob)
pp = charts.divisional_chart(jd, place, divisional_chart_factor=1)[:const._pp_count_upto_ketu]
asc_house = pp[0][1][0] # 0-indexed ascendant sign (pp[0] = Lagna)
# 2. 构建共享的行星经度字典(供我们的代码使用)
# 注意: pp[0]=Lagna, pp[1]=Sun, pp[2]=Moon, ... 即 pp[planet_id+1]=planet
planet_longitudes = {}
for planet_id, pname in PLANET_NAMES.items():
sign = pp[planet_id + 1][1][0]
deg = pp[planet_id + 1][1][1]
planet_longitudes[pname] = sign * 30 + deg
# 3. 我们的 KN Rao 实现
our_progression = _chara_progression_knrao(asc_house, planet_longitudes)
our_durations = [_chara_dasha_duration_knrao(planet_longitudes, s) for s in our_progression]
# 4. PyJHora KN Rao 实现(oracle
pj_progression = pj_chara._dhasa_progression_knrao_method(pp)
pj_durations = [pj_chara._dhasa_duration_knrao_method(pp, s) for s in pj_progression]
# 5. 比较
case_sign_match = 0; case_dur_match = 0
mismatches = []
for i in range(12):
our_s = our_progression[i]
pj_s = pj_progression[i]
our_d = our_durations[i]
pj_d = pj_durations[i]
if our_s == pj_s:
case_sign_match += 1
else:
mismatches.append(f"sign[{i}]: us={SIGNS[our_s]}, pj={SIGNS[pj_s]}")
if our_d == pj_d:
case_dur_match += 1
else:
mismatches.append(f"dur[{i}]: us={our_d}, pj={pj_d}")
total_sign += 12; sign_match += case_sign_match
total_dur += 12; dur_match += case_dur_match
our_first3 = ",".join(SIGNS[s] for s in our_progression[:3])
pj_first3 = ",".join(SIGNS[s] for s in pj_progression[:3])
line = f" {case['id']:35s} | sign {case_sign_match:2d}/12 | dur {case_dur_match:2d}/12"
detail_lines.append(line)
sample_details.append({
"case": case['id'],
"asc": SIGNS[asc_house],
"our_first_3": our_first3,
"pj_first_3": pj_first3,
"sign_match": f"{case_sign_match}/12",
"dur_match": f"{case_dur_match}/12",
"mismatches": mismatches[:5] # 最多5个不匹配项
})
# ── 输出 ──
print("=" * 80)
print("Chara Dasha KN Rao Benchmark v1.1")
print(f"Skill: v6.1.11 (共享PyJHora行星位置)")
print("=" * 80)
print(f"\n{'Case':40s} | Sign Match | Dur Match | Us first3 vs PJ first3")
print("-" * 80)
for i, s in enumerate(sample_details):
line = f" {s['case']:35s} | {s['sign_match']:>10s} | {s['dur_match']:>9s} | {s['our_first_3']} | {s['pj_first_3']}"
print(line)
print("-" * 80)
total_all = total_sign + total_dur
match_all = sign_match + dur_match
print(f"\nSign Sequence Match: {sign_match}/{total_sign} = {sign_match/total_sign*100:.2f}%")
print(f"Duration Match: {dur_match}/{total_dur} = {dur_match/total_dur*100:.2f}%")
print(f"Overall Match: {match_all}/{total_all} = {match_all/total_all*100:.2f}%")
if match_all / total_all >= 0.95:
status = "✅ PASS ✓"
elif match_all / total_all >= 0.85:
status = "⚠️ BORDERLINE"
else:
status = "❌ FAIL"
print(f"\nBenchmark Result: {status}")
# 放生不匹配
if status != "✅ PASS ✓":
print("\n--- 不匹配详情 ---")
for s in sample_details:
if s["mismatches"]:
print(f"\n{s['case']}:")
for m in s["mismatches"]:
print(f" {m}")
# 保存 JSON
out = os.path.join(os.path.dirname(__file__), "..", "outputs", "chara_dasha_knrao_benchmark.json")
os.makedirs(os.path.dirname(out), exist_ok=True)
result = {
"version": "v6.1.11",
"benchmark": "chara_dasha_kn_rao",
"total_sign_match": sign_match,
"total_dur_match": dur_match,
"total_sign": total_sign,
"total_dur": total_dur,
"sign_match_rate": round(sign_match/total_sign, 4) if total_sign else 0,
"dur_match_rate": round(dur_match/total_dur, 4) if total_dur else 0,
"status": status,
"samples": sample_details,
}
with open(out, 'w') as f:
json.dump(result, f, indent=2, ensure_ascii=False)
print(f"\n结果已保存: {out}")
if __name__ == "__main__":
run_benchmark()