Files
Jyotisha/scripts/ashtakavarga.py
T
732642856 2c3392703d feat: v3.6.0 全量同步 — 完整印度占星引擎+74篇参考资料+14子命令
## 核心升级(v1.6.0 → v3.6.0)

### 计算引擎(scripts/)
- jyotish_engine.py v3.6.0:14子命令统一引擎(chart/dasha/yoga/predict/varga/celebrity/db-stats/transit/shadbala/ashtakavarga/memory/validate/audit/report)
- 基于 Swiss Ephemeris + Lahiri Ayanamsa 恒星黄道
- shadbala.py:Shadbala六重力量计算(Sthana/Dig/Kala/Chesta/Naisargika/Drik Bala)
- ashtakavarga.py v2.0:BPHS完整8×8矩阵,SAV=337
- validate.py:R1-R10+R2b 数学验证(11项)
- event_prediction_model.py:三层验证事件预测规则引擎
- hermes_memory_core.py + hermes_bridge.py:Hermes记忆系统
- report_builder.py:MD→HTML报告生成器(羊皮纸主题)

### 参考资料(references/)— 74篇
- 新增35篇:AI解盘工作流/Argala/Dasa Convergence/替代推运系统/条件Dasha/Shodasavarga十六分盘/古典文献翻译/专业发展路径等
- 修改8篇:PDF读取v3.0/Ashtakavarga v2.0/名人案例库v2.0/KP占星v2.0等
- 覆盖:行星/星座/宫位/Nakshatra/Yoga/Dasha/Transit/关系占星/年运盘/Jaimini/KP/Varshaphala/补救措施

### 审计管线(P1-P12 + P3/P8/冲突仲裁)
- P3仓库耦合:双宫掌管命运捆绑分析
- P8年龄状态:行星度数→执行模式判定
- 冲突仲裁3条规则:矛盾信号裁决

### 其他
- CHANGELOG.md:完整版本历史
- .gitignore:排除缓存和数据库
- SKILL.md v3.6.0:触发词/子命令表/工作流完整更新
2026-04-24 22:36:57 +08:00

346 lines
12 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
# -*- coding: utf-8 -*-
"""
Ashtakavarga 计算模块 v2.0(八分法)
基于 Brihat Parashara Hora Shastra (BPHS) 完整标准表
核心修正(v2.0 vs v1.0):
- v1.0: BAV_BASE 只有自贡献 + 少量跨源贡献 → SAV=94 ❌
- v2.0: 完整 8×8 贡献矩阵(每颗行星 × 8来源)→ SAV=337 ✅
架构:
- BAV_CONTRIBUTION[planet][source] = 有利宫位列表
- 每颗行星的 BAV = 所有 8 个来源(7行星+Lagna)的贡献之和
- SAV = 7 颗行星 BAV 之和(Lagna 自身 BAV 单独展示,不计入 SAV)
- SAV 总和 = 337(宇宙常数)
BPHS 校正:
- 月亮 BAV → 木星贡献:1,4,7,8,10,116宫,不含12)→ 总49
- 金星 BAV → 水星贡献:3,5,6,9,11,126宫,含12)→ 总52
"""
from typing import Dict, List, Tuple
SIGNS = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo',
'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
# ============================================================================
# 完整 BAV 贡献表(BPHS 标准法)
# BAV_CONTRIBUTION[planet][source] = 从 source 数起的有利宫位列表
# 每颗行星的 BAV 总和 = 所有 8 个来源的贡献数之和
# ============================================================================
# --- 太阳 BAV(总48 ---
# 来源: Sun(8) + Moon(4) + Mars(8) + Mercury(7) + Jupiter(4) + Venus(3) + Saturn(8) + Lagna(6) = 48
_SUN_BAV = {
'Sun': [1, 2, 4, 7, 8, 9, 10, 11],
'Moon': [3, 6, 10, 11],
'Mars': [1, 2, 4, 7, 8, 9, 10, 11],
'Mercury': [3, 5, 6, 9, 10, 11, 12],
'Jupiter': [5, 6, 9, 11],
'Venus': [6, 7, 12],
'Saturn': [1, 2, 4, 7, 8, 9, 10, 11],
'Lagna': [3, 4, 6, 10, 11, 12],
}
# --- 月亮 BAV(总49 ---
# 来源: Sun(6) + Moon(6) + Mars(7) + Mercury(8) + Jupiter(6) + Venus(7) + Saturn(4) + Lagna(5) = 49
# BPHS校正:木星贡献为 1,4,7,8,10,116宫),非 1,4,7,8,10,11,127宫)
_MOON_BAV = {
'Sun': [3, 6, 7, 8, 10, 11],
'Moon': [1, 3, 6, 7, 10, 11],
'Mars': [2, 3, 5, 6, 9, 10, 11],
'Mercury': [1, 3, 4, 5, 7, 8, 10, 11],
'Jupiter': [1, 4, 7, 8, 10, 11], # BPHS校正:不含12
'Venus': [3, 4, 5, 7, 9, 10, 11],
'Saturn': [3, 5, 6, 11],
'Lagna': [3, 6, 10, 11, 12],
}
# --- 火星 BAV(总39 ---
# 来源: Sun(5) + Moon(3) + Mars(7) + Mercury(4) + Jupiter(4) + Venus(4) + Saturn(7) + Lagna(5) = 39
_MARS_BAV = {
'Sun': [3, 5, 6, 10, 11],
'Moon': [3, 6, 11],
'Mars': [1, 2, 4, 7, 8, 10, 11],
'Mercury': [3, 5, 6, 11],
'Jupiter': [6, 10, 11, 12],
'Venus': [6, 8, 11, 12],
'Saturn': [1, 4, 7, 8, 9, 10, 11],
'Lagna': [1, 3, 6, 10, 11],
}
# --- 水星 BAV(总54 ---
# 来源: Sun(5) + Moon(6) + Mars(8) + Mercury(8) + Jupiter(4) + Venus(8) + Saturn(8) + Lagna(7) = 54
_MERCURY_BAV = {
'Sun': [5, 6, 9, 11, 12],
'Moon': [2, 4, 6, 8, 10, 11],
'Mars': [1, 2, 4, 7, 8, 9, 10, 11],
'Mercury': [1, 3, 5, 6, 9, 10, 11, 12],
'Jupiter': [6, 8, 11, 12],
'Venus': [1, 2, 3, 4, 5, 8, 9, 11],
'Saturn': [1, 2, 4, 7, 8, 9, 10, 11],
'Lagna': [1, 2, 4, 6, 8, 10, 11],
}
# --- 木星 BAV(总56 ---
# 来源: Sun(9) + Moon(5) + Mars(7) + Mercury(8) + Jupiter(8) + Venus(6) + Saturn(4) + Lagna(9) = 56
_JUPITER_BAV = {
'Sun': [1, 2, 3, 4, 7, 8, 9, 10, 11],
'Moon': [2, 5, 7, 9, 11],
'Mars': [1, 2, 4, 7, 8, 10, 11],
'Mercury': [1, 2, 4, 5, 6, 9, 10, 11],
'Jupiter': [1, 2, 3, 4, 7, 8, 10, 11],
'Venus': [2, 5, 6, 9, 10, 11],
'Saturn': [3, 5, 6, 12],
'Lagna': [1, 2, 4, 5, 6, 7, 9, 10, 11],
}
# --- 金星 BAV(总52 ---
# 来源: Sun(3) + Moon(9) + Mars(6) + Mercury(6) + Jupiter(5) + Venus(9) + Saturn(7) + Lagna(7) = 52
# BPHS校正:水星贡献为 3,5,6,9,11,126宫,含12),非 3,5,6,9,115宫)
_VENUS_BAV = {
'Sun': [8, 11, 12],
'Moon': [1, 2, 3, 4, 5, 8, 9, 11, 12],
'Mars': [3, 5, 6, 9, 11, 12],
'Mercury': [3, 5, 6, 9, 11, 12], # BPHS校正:含12
'Jupiter': [5, 8, 9, 10, 11],
'Venus': [1, 2, 3, 4, 5, 8, 9, 10, 11],
'Saturn': [3, 4, 5, 8, 9, 10, 11],
'Lagna': [1, 2, 3, 4, 5, 8, 9],
}
# --- 土星 BAV(总39 ---
# 来源: Sun(7) + Moon(3) + Mars(6) + Mercury(6) + Jupiter(4) + Venus(3) + Saturn(4) + Lagna(6) = 39
_SATURN_BAV = {
'Sun': [1, 2, 4, 7, 8, 10, 11],
'Moon': [3, 6, 11],
'Mars': [3, 5, 6, 10, 11, 12],
'Mercury': [6, 8, 9, 10, 11, 12],
'Jupiter': [5, 6, 11, 12],
'Venus': [6, 11, 12],
'Saturn': [3, 5, 6, 11],
'Lagna': [1, 3, 4, 6, 10, 11],
}
# --- Lagna BAV(总49,不计入 SAV 337 ---
# 来源: Sun(6) + Moon(5) + Mars(5) + Mercury(7) + Jupiter(9) + Venus(7) + Saturn(6) + Lagna(4) = 49
_LAGNA_BAV = {
'Sun': [3, 4, 6, 10, 11, 12],
'Moon': [3, 6, 10, 11, 12],
'Mars': [1, 3, 6, 10, 11],
'Mercury': [1, 2, 4, 6, 8, 10, 11],
'Jupiter': [1, 2, 4, 5, 6, 7, 9, 10, 11],
'Venus': [1, 2, 3, 4, 5, 8, 9],
'Saturn': [1, 3, 4, 6, 10, 11],
'Lagna': [3, 6, 10, 11],
}
# 汇总为统一查找表
BAV_CONTRIBUTION = {
'Sun': _SUN_BAV,
'Moon': _MOON_BAV,
'Mars': _MARS_BAV,
'Mercury': _MERCURY_BAV,
'Jupiter': _JUPITER_BAV,
'Venus': _VENUS_BAV,
'Saturn': _SATURN_BAV,
'Lagna': _LAGNA_BAV,
}
# 各行星BAV固定总数(宇宙常数)
BAV_TOTALS = {
'Sun': 48, 'Moon': 49, 'Mars': 39, 'Mercury': 54,
'Jupiter': 56, 'Venus': 52, 'Saturn': 39, 'Lagna': 49
}
# 7颗行星 BAV 总和 = SAV 337
EXPECTED_SAV_TOTAL = 337
# Shodhya Pinda 行星权重
PLANET_WEIGHTS = {
'Sun': 5, 'Moon': 5, 'Mars': 8, 'Mercury': 5,
'Jupiter': 10, 'Venus': 7, 'Saturn': 5
}
# 行星列表
SEVEN_PLANETS = ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn']
ALL_SOURCES = SEVEN_PLANETS + ['Lagna']
def _get_sign_idx(sign_name: str) -> int:
"""星座名称转索引"""
return SIGNS.index(sign_name) if sign_name in SIGNS else 0
def calc_ashtakavarga(planets: Dict, asc_sign_idx: int) -> Dict:
"""
计算完整 Ashtakavargav2.0 BPHS标准法)
Args:
planets: 行星数据 dict,每颗行星需要 {sign, degree, ...}
sign 是星座名称
asc_sign_idx: 上升星座在 SIGNS 中的索引 (0-11)
Returns:
完整的 Ashtakavarga 计算结果,含 BAV、SAV、校验
"""
# 1. 确定每个来源(7行星+Lagna)的星座索引
source_sign_idx = {}
for pname in SEVEN_PLANETS:
if pname in planets:
sign = planets[pname].get('sign', '')
if sign in SIGNS:
source_sign_idx[pname] = SIGNS.index(sign)
source_sign_idx['Lagna'] = asc_sign_idx
# 2. 为每颗行星计算 BAV
# BAV[planet][sign_i] = count of sources that contribute bindhu to sign_i
bav_results = {}
sav = [0] * 12 # 12星座的SAV(仅统计7行星贡献)
lagna_sav = [0] * 12 # Lagna单独的贡献
for planet in ALL_SOURCES:
contribution_rules = BAV_CONTRIBUTION[planet]
bav = [0] * 12 # 12星座的 bindhu 数
for source in ALL_SOURCES:
if source not in source_sign_idx:
continue
# 获取该 source 对该 planet BAV 的有利宫位
favorable_houses = contribution_rules.get(source, [])
source_idx = source_sign_idx[source]
# 从 source 所在星座开始,将有利宫位映射到实际星座
for house in favorable_houses:
target_sign = (source_idx + house - 1) % 12
bav[target_sign] += 1
bav_total = sum(bav)
expected = BAV_TOTALS.get(planet, 0)
bav_results[planet] = {
'bindus': bav,
'total': bav_total,
'expected_total': expected,
'valid': bav_total == expected,
'deviation': abs(bav_total - expected),
}
# 累加到 SAV(仅7行星)
if planet in SEVEN_PLANETS:
for i in range(12):
sav[i] += bav[i]
else:
# Lagna 的贡献单独记录
for i in range(12):
lagna_sav[i] += bav[i]
# 3. 校验 SAV 总分
sav_total = sum(sav)
# 4. SAV 评估
sav_assessment = []
for i in range(12):
score = sav[i]
if score >= 30:
level = "极吉"
elif score >= 28:
level = "吉利"
elif score >= 25:
level = "中等"
else:
level = "挑战"
sav_assessment.append({
'sign': SIGNS[i],
'score': score,
'level': level,
})
# 5. 含 Lagna 的完整 SAV386 = 337 + 49
full_sav = [sav[i] + lagna_sav[i] for i in range(12)]
# 6. Shodhya Pinda 计算
shodhya = {}
for pname in SEVEN_PLANETS:
if pname in source_sign_idx and pname in bav_results:
own_sign = source_sign_idx[pname]
bindu_at_own = bav_results[pname]['bindus'][own_sign]
sign_weight = 4 # 简化:星座权重统一为4
rashi_pinda = bindu_at_own * sign_weight
graha_pinda = bindu_at_own * PLANET_WEIGHTS.get(pname, 5)
shodhya[pname] = {
'rashi_pinda': rashi_pinda,
'graha_pinda': graha_pinda,
'total_pinda': rashi_pinda + graha_pinda,
'bindu_at_own_sign': bindu_at_own,
}
# 7. 排名
ranked_sav = sorted(enumerate(sav_assessment), key=lambda x: x[1]['score'], reverse=True)
# 8. BAV 校验报告
bav_validation = []
all_valid = True
for planet in ALL_SOURCES:
r = bav_results[planet]
status = "" if r['valid'] else f"❌ 偏差{r['deviation']}"
if not r['valid']:
all_valid = False
bav_validation.append({
'planet': planet,
'actual': r['total'],
'expected': r['expected_total'],
'status': status,
})
return {
'method': 'Ashtakavarga八分法(BPHS标准v2.0',
'version': '2.0',
'bav': bav_results,
'sav': {
'scores': {SIGNS[i]: sav[i] for i in range(12)},
'full_scores_with_lagna': {SIGNS[i]: full_sav[i] for i in range(12)},
'assessment': sav_assessment,
'total': sav_total,
'expected_total': EXPECTED_SAV_TOTAL,
'valid': sav_total == EXPECTED_SAV_TOTAL,
'deviation': abs(sav_total - EXPECTED_SAV_TOTAL),
'full_total_with_lagna': sum(full_sav),
},
'bav_validation': bav_validation,
'all_bav_valid': all_valid,
'shodhya_pinda': shodhya,
'strongest_signs': [SIGNS[i] for i, _ in ranked_sav[:3]],
'weakest_signs': [SIGNS[i] for i, _ in ranked_sav[-3:]],
'house_scores': _map_to_houses(sav_assessment, asc_sign_idx),
'house_scores_full': _map_to_houses_values(full_sav, asc_sign_idx),
}
def _map_to_houses(sav_assessment: List[Dict], asc_sign_idx: int) -> Dict:
"""将 SAV 分数映射到宫位"""
houses = {}
for house_num in range(1, 13):
sign_idx = (asc_sign_idx + house_num - 1) % 12
score = sav_assessment[sign_idx]['score']
level = sav_assessment[sign_idx]['level']
houses[f"house_{house_num}"] = {
'sign': SIGNS[sign_idx],
'sav_score': score,
'level': level,
}
return houses
def _map_to_houses_values(scores: List[int], asc_sign_idx: int) -> Dict:
"""将含Lagna的完整SAV映射到宫位"""
houses = {}
for house_num in range(1, 13):
sign_idx = (asc_sign_idx + house_num - 1) % 12
houses[f"house_{house_num}"] = {
'sign': SIGNS[sign_idx],
'sav_score': scores[sign_idx],
}
return houses