fix: tighten yoga precision pass

This commit is contained in:
732642856
2026-06-05 16:39:05 +08:00
parent 44221191f6
commit 4b840b5c2a
6 changed files with 1300 additions and 1517 deletions
+29
View File
@@ -1,5 +1,34 @@
# 印度占星 Skill 更新日志
## v6.0.352026-06-05)—— Yoga 精度二次提升与 Top FP 收窄
> **目标**:在 v6.0.34 已大幅提升 F1 后,继续按验证报告 Top FP/FN 队列修正高影响规则,优先降低过宽误报,同时保持质量门禁通过。
### 对齐与修复
- 修正 `matsya_yoga`:从过宽的“吉星三方+凶星凶宫”改为 PyJHora/PVR method=2 口径:Lagna 与 9宫仅吉星,5宫同时有吉/凶星,4宫与8宫仅凶星。
- 修正 `sankha_yoga`:补齐 PyJHora/BVR-12 双分支:上升主强且5/6宫主互为 Kendra,或1/10宫主合于变动星座且9宫主强。
- 修正 `bvr_103_guru_mangala_yoga`:从“木火互为 Kendra”收窄为 PyJHora 定义:木星与火星同宫或互为7宫。
- 调整 `bvr_rogagrastha_precise`:对齐 PyJHora D1-safe 条件:上升主在Lagna合凶宫主,或弱上升主合角/三方主。
- 修正 `bvr_kaalanirdesat_puthranaasa_yoga`:从单一“5宫主受土/Rahu伤”改为 PyJHora 229/230 组合条件。
- 修复 `validate_logic_v2.py``kaahala_yoga` 的历史别名映射,确保 PyJHora `kaahala_yoga` 正确归入现有 `kahala_yoga`
- 为 custom Yoga 表达式新增 `occupants()``only_benefics_in_house()``only_malefics_in_house()``house_has_benefic()``house_has_malefic()``house_sign()``movable_house()``MOVABLE_SIGNS`,支持更接近源码的规则表达。
### 当前验证结果
- `scripts/validate_logic_v2.py`Precision **83.84%**Recall **69.64%**F1 **76.08%**
- 相比 v6.0.34 的 F1 **74.13%**,提升 **+1.95 个百分点**;相比 v6.0.32/v6.0.33 基线 **58.08%**,累计提升 **+18.00 个百分点**。
- `pytest tests/test_yoga_rules_integrity.py tests/test_dasha.py`25 passed。
- `scripts/run_quality_gate.py --skip-yoga-logic`:通过;完整 pytest 35 passedBPHS/Ashtakavarga 不变量 18/18 通过,golden case 通过。
### 已知后续优化点
- 剩余 FN 主要集中在 `mathibhramana``matrunasa``rogagrastha``bahu_puthra``kahala``nishkapata``swaveeryaddhana` 等规则,其中部分需要 D9/Navamsa、tithi/waning Moon 或 Gulika 等当前 D1 静态验证数据未携带的信息。
- 剩余 FP 主要集中在 `vanchana_chora_bheethi``sankha``bhratruvriddhi``mridanga``dehasthoulya``bahu_puthra``bandhu_pujya` 等规则。
- v6.0.36 建议优先升级验证数据结构,把 D9、tithi、Gulika/Upagraha 等上下文纳入同盘验证,避免 D1-only 规则反复在召回和准确率之间拉扯。
---
## v6.0.342026-06-05)—— Yoga 逻辑对齐与 F1 提升
> **目标**:继续 v6.0.32 的“同盘逻辑正确性”路线,优先修复验证报告中高 FP/FN 的规则,而不是只堆规则名称。
+4 -4
View File
@@ -1,6 +1,6 @@
---
name: jyotish-vedic-astrology
version: 6.0.34
version: 6.0.35
description: 印度占星(Jyotish)专业解盘与推运系统。核心能力:PDF星盘输入→严谨解盘→精确推运应期输出。触发词:印度占星、吠陀占星、Jyotish、解盘、推运、星盘分析、Dasha、Transit、Nakshatra、Yoga、出生时间矫正、PDF星盘、读取PDF、分析PDF星盘、现代解读、误判纠错、Varga分盘、综合分析、过境分析、合盘、婚姻匹配、年运盘、Prashna、Argala、Jaimini、Shadbala、Ashtakavarga、HTML报告、深度解盘。
---
@@ -10,7 +10,7 @@ description: 印度占星(Jyotish)专业解盘与推运系统。核心能力
> **严格路由**`references/strict-workflow-router.md`(⭐涉及事业/婚恋/财务/应期/技法验证时必须优先读取)
> **覆盖矩阵**`references/technique-capability-matrix.md`(⭐判断技法 covered/partial/missing 时必须参考)
> **机器注册表**`references/technique_registry.json` + `scripts/audit_capabilities.py`(⭐用于自动审计与CI门禁)
> **版本**v6.0.34-yoga-logic-alignment | **详细变更**`CHANGELOG.md`
> **版本**v6.0.35-yoga-precision-pass | **详细变更**`CHANGELOG.md`
---
@@ -301,9 +301,9 @@ $PYTHON $SCRIPT <子命令> [参数]
---
**版本**v6.0.34-yoga-logic-alignment
**版本**v6.0.35-yoga-precision-pass
**创建日期**2026-04-20
**最后更新**2026-06-05v6.0.34 对齐 PyJHora/B.V. Raman 多个高影响 Yoga 条件;当前 473 条 JSON 规则、379 条启用规则,D1/Rasi 逻辑验证 F1=74.13%,报告以 `references/validation_logic_report.json` 为准)
**最后更新**2026-06-05v6.0.35 继续对齐 PyJHora/B.V. Raman 高影响 Yoga 条件,重点收窄 Top FP 并修复 Kahala 映射;当前 473 条 JSON 规则、379 条启用规则,D1/Rasi 逻辑验证 F1=76.08%,报告以 `references/validation_logic_report.json` 为准)
---
File diff suppressed because it is too large Load Diff
+15 -52
View File
@@ -1278,8 +1278,8 @@
"category": "auspicious",
"logic": {
"type": "custom",
"expr": "\nlord_5 = lord(5)\nlord_6 = lord(6)\nif lord_5 in ctx.planets and lord_6 in ctx.planets:\n l5h = house_of(lord_5)\n l6h = house_of(lord_6)\n (kendra(l5h) or trikona(l5h)) and (kendra(l6h) or trikona(l6h))\nelse:\n False\n",
"combo_template": "5宫主与6宫主均在有力宫位"
"expr": "\n# PyJHora/BVR-12: (L1 strong and L5/L6 in mutual kendras) OR\n# (L1 and L10 together in a movable sign and L9 strong).\nl1, l5, l6, l9, l10 = [lord(h) for h in [1, 5, 6, 9, 10]]\nif not all(p in ctx.planets for p in [l1, l5, l6, l9, l10]):\n False\nelse:\n l1h, l5h, l6h, l9h, l10h = [house_of(p) for p in [l1, l5, l6, l9, l10]]\n cond1 = strong(l1) and offset(l5h, l6h) in [0, 3, 6, 9] and offset(l6h, l5h) in [0, 3, 6, 9]\n cond2 = strong(l9) and same_house(l1, l10) and movable_house(l1h)\n cond1 or cond2\n",
"combo_template": "上升主强且5/6宫主互为Kendra,或1/10宫主合于变动星座且9宫主强"
},
"effects": [
"学识渊博",
@@ -1386,8 +1386,8 @@
"category": "auspicious",
"logic": {
"type": "custom",
"expr": "\nben_in_trikona = [p for p in BENEFICS if p in ctx.planets and house_of(p) in [5, 9]]\nmal_in_dusthana = [p for p in MALEFICS if p in ctx.planets and house_of(p) in [6, 8]]\nbool(ben_in_trikona and mal_in_dusthana)\n",
"combo_template": "吉星在三方宫+凶星在凶宫"
"expr": "\n# PyJHora/PVR method=2: benefics only in Lagna and 9th; 5th contains\n# both benefic and malefic; 4th and 8th contain only malefics.\ncond1 = only_benefics_in_house(1) and only_benefics_in_house(9)\ncond2 = house_has_benefic(5) and house_has_malefic(5)\ncond3 = only_malefics_in_house(4) and only_malefics_in_house(8)\ncond1 and cond2 and cond3\n",
"combo_template": "Lagna/9宫仅吉星,5宫吉凶同在,4/8宫仅凶星"
},
"effects": [
"聪慧过人",
@@ -9081,8 +9081,8 @@
"category": "health",
"logic": {
"type": "custom",
"expr": "\n# PyJHora BVR-11: (a) Lagna lord in Lagna joined by dusthana lord;\n# (b) weak Lagna lord in kendra/trikona joined by a kendra/trine lord.\nasc_lord = lord(1)\ndusthana_lords = [lord(h) for h in [6, 8, 12]]\nquad_trine_lords = [lord(h) for h in [1, 4, 5, 7, 9, 10]]\nif asc_lord not in ctx.planets:\n False\nelse:\n h = house_of(asc_lord)\n condition_a = h == 1 and any(dl in ctx.planets and same_house(asc_lord, dl) for dl in dusthana_lords)\n condition_b = (kendra(h) or trikona(h)) and not strong(asc_lord) and any(qtl in ctx.planets and same_house(asc_lord, qtl) for qtl in quad_trine_lords if qtl != asc_lord)\n condition_a or condition_b\n",
"combo_template": "上升主与凶宫主或角/三方主形成疾病格局"
"expr": "\n# PyJHora BVR-11 exact D1-safe logic: (a) Lagna lord in Lagna joined by\n# dusthana lord; (b) weak Lagna lord joined by any kendra/trine lord.\nasc_lord = lord(1)\ndusthana_lords = [lord(h) for h in [6, 8, 12]]\nquad_trine_lords = [lord(h) for h in [1, 4, 5, 7, 9, 10]]\nif asc_lord not in ctx.planets:\n False\nelse:\n condition_a = house_of(asc_lord) == 1 and any(dl in ctx.planets and same_house(asc_lord, dl) for dl in dusthana_lords)\n condition_b = (not strong(asc_lord)) and any(qtl in ctx.planets and same_house(asc_lord, qtl) for qtl in quad_trine_lords)\n condition_a or condition_b\n",
"combo_template": "上升主在Lagna合凶宫主,或弱上升主合角/三方主"
},
"effects": [
"疾病",
@@ -11236,14 +11236,9 @@
"bvr_id": null,
"category": "putra",
"logic": {
"type": "compound_conditions",
"conditions": [
{
"type": "5th_lord_afflicted_by_saturn_or_rahu",
"note": "5th lord afflicted by Saturn or Rahu"
}
],
"note": "Loss of children at specific times"
"type": "custom",
"expr": "\n# PyJHora 229/230 D1-safe logic. Variant 229: Rahu in 5th, L5 joined\n# malefic, Jupiter debilitated. Variant 230: malefics occupy/aspect both\n# 5th from Lagna and 5th from Jupiter.\nl5 = lord(5)\nif l5 not in ctx.planets or 'Jupiter' not in ctx.planets:\n False\nelse:\n cond229 = house_of('Rahu') == 5 and debil('Jupiter') and any(m in ctx.planets and same_house(l5, m) for m in MALEFICS if m != l5)\n j5 = ((house_of('Jupiter') - 1 + 4) % 12) + 1\n mal_lagna5 = any(m in ctx.planets and (house_of(m) == 5 or aspects_house(m, 5)) for m in MALEFICS)\n mal_jupiter5 = any(m in ctx.planets and (house_of(m) == j5 or aspects_house(m, j5)) for m in MALEFICS)\n cond229 or (mal_lagna5 and mal_jupiter5)\n",
"combo_template": "Rahu/L5/木星或凶星影响Lagna与木星起算第5宫"
},
"effects": [
"Loss of progeny at predetermined periods"
@@ -11631,32 +11626,9 @@
"bvr_id": null,
"category": "special",
"logic": {
"type": "compound_conditions",
"conditions": [
{
"type": "compound",
"operator": "OR",
"conditions": [
{
"type": "jupiter_in_lagna_mars_in_7th",
"note": "Jupiter in Lagna and Mars in 7th"
},
{
"type": "saturn_in_lagna_mars_in_5_7_9",
"note": "Saturn in Lagna and Mars in 9th/5th/7th"
},
{
"type": "saturn_in_12th_with_waning_moon",
"note": "Saturn in 12th with waning Moon"
},
{
"type": "moon_mercury_in_kendra_with_planet",
"note": "Moon and Mercury in kendra with another planet"
}
]
}
],
"note": ""
"type": "custom",
"expr": "\n# PyJHora 291/292/294 D1-safe variants. Variant 293 needs tithi/waning Moon\n# and remains unavailable from static planet_positions_60 data.\njm = 'Jupiter' in ctx.planets and 'Mars' in ctx.planets and house_of('Jupiter') == 1 and house_of('Mars') == 7\nsm = 'Saturn' in ctx.planets and 'Mars' in ctx.planets and house_of('Saturn') == 1 and house_of('Mars') in [5, 7, 9]\nmoon_mercury = False\nif 'Moon' in ctx.planets and 'Mercury' in ctx.planets:\n moon_mercury = kendra(house_of('Moon')) and kendra(house_of('Mercury')) and any(p != 'Moon' and aspect(p, 'Moon') for p in ctx.planets) and any(p != 'Mercury' and aspect(p, 'Mercury') for p in ctx.planets)\njm or sm or moon_mercury\n",
"combo_template": "木火1/7、土升火5/7/9,或月水角宫并受相位"
},
"effects": [
"Mental disturbance, confusion, erratic behavior"
@@ -13633,18 +13605,9 @@
"bvr_id": null,
"category": "raja",
"logic": {
"type": "compound_conditions",
"conditions": [
{
"type": "planets_in_mutual_kendras_or_conjunction",
"planets": [
"Jupiter",
"Mars"
],
"note": "Jupiter and Mars in mutual kendras or in conjunction"
}
],
"note": "Jupiter and Mars in mutual kendras or conjunction"
"type": "custom",
"expr": "\n# PyJHora: Jupiter and Mars are together or in the 7th from each other.\n'Jupiter' in ctx.planets and 'Mars' in ctx.planets and offset(house_of('Jupiter'), house_of('Mars')) in [0, 6]\n",
"combo_template": "木星与火星同宫或互为7宫"
},
"effects": [
"Courage, wisdom, leadership, military success"
+1 -1
View File
@@ -96,7 +96,7 @@ PYJHORA_VARIANTS = {
# Kedara
'kedara_yoga': 'bvr_kedaara_yoga',
# Kaahala/Kahala
'kaahala_yoga': 'bvr_kahala_yoga',
'kaahala_yoga': 'kahala_yoga',
# Direct mappings for common yogas
'vosi_yoga': 'bvr_vosi_precise',
'sunaphaa_yoga': 'bvr_sunaphaa_precise',
+31
View File
@@ -44,6 +44,7 @@ PLANET_CN = {
}
BENEFICS = ['Jupiter', 'Venus', 'Mercury', 'Moon']
MALEFICS = ['Mars', 'Saturn', 'Sun', 'Rahu', 'Ketu']
MOVABLE_SIGNS = ['Aries', 'Cancer', 'Libra', 'Capricorn']
ALL_PLANETS = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn', 'Rahu', 'Ketu']
@@ -921,6 +922,31 @@ class YogaEngine:
# PyJHora temporary friends: 2/3/4/10/11/12 from a planet.
return offset(ctx.house_of(a), ctx.house_of(b)) in [1, 2, 3, 9, 10, 11]
def occupants(h):
return ctx.planets_in_house(h) if h is not None else []
def only_benefics_in_house(h):
ps = occupants(h)
return bool(ps) and all(p in BENEFICS for p in ps)
def only_malefics_in_house(h):
ps = occupants(h)
return bool(ps) and all(p in MALEFICS for p in ps)
def house_has_benefic(h):
return any(p in BENEFICS for p in occupants(h))
def house_has_malefic(h):
return any(p in MALEFICS for p in occupants(h))
def house_sign(h):
if h is None:
return None
return SIGNS[(ctx.asc_idx + h - 1) % 12]
def movable_house(h):
return house_sign(h) in MOVABLE_SIGNS
def exal(p): return ctx.is_exalted(p)
def lord_of_house(h): return ctx.lord_of_house(h)
def sign(p): return ctx.sign_of(p)
@@ -955,6 +981,7 @@ class YogaEngine:
"SIGNS": SIGNS, "SIGN_LORDS": SIGN_LORDS,
"EXALTATION": EXALTATION, "DEBILITATION": DEBILITATION,
"PLANET_CN": PLANET_CN, "BENEFICS": BENEFICS, "MALEFICS": MALEFICS,
"MOVABLE_SIGNS": MOVABLE_SIGNS,
"ALL_PLANETS": ALL_PLANETS, "MOOLATRIKONA_SIGN": MOOLATRIKONA_SIGN,
# 基础查询
"house_of": house_of, "sign_of": sign_of, "deg_of": deg_of,
@@ -977,6 +1004,10 @@ class YogaEngine:
# v6.0.32: 同宫与相位检查(custom规则常用)
"same_house": same_house, "aspect": aspect, "aspects_house": aspects_house,
"strong": strong, "associated": associated, "temporal_friend": temporal_friend,
"occupants": occupants, "only_benefics_in_house": only_benefics_in_house,
"only_malefics_in_house": only_malefics_in_house,
"house_has_benefic": house_has_benefic, "house_has_malefic": house_has_malefic,
"house_sign": house_sign, "movable_house": movable_house,
"exal": exal, "lord_of_house": lord_of_house, "sign": sign,
"check_amala_from": check_amala_from,
"Benefics": BENEFICS, "Malefics": MALEFICS,