Files
Jyotisha/scripts/jaimini.py
T
732642856 63fb547dda v6.0.14: 新增 Yogas + Doshas + Special Lagnas + Darakaraka 技法
- scripts/jaimini.py: 新增 calc_darakaraka 等5个函数(DK/婚姻分析)
- scripts/yogas_doshas.py: 新文件,11个函数(Raj/Dhana/PanchaMahapurusha/NeechaBhanga/MangalDosha/KaalSarp/Pitra/SadeSati/ArudhaLagna/UpapadaLagna)
- scripts/jyotish_engine.py: cmd_full_reading 新增 Step 4.9 调用 calc_all_yogas_doshas
- references/technique_registry.json: 新增11个技法注册(darakaraka/raj_yoga/.../upapada_lagna)
- references/strict-workflow-router.md: Audit Table 模板新增11行
- CHANGELOG.md: 新增 v6.0.14 条目
- SKILL.md: 版本号 6.0.13 → 6.0.14
2026-06-04 05:12:35 +08:00

559 lines
22 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 -*-
"""
Jaimini占星体系模块 v1.1
Parashara传承中的Jaimini子系统
支持:
- Chara Karaka: 7/8个功能指示星(按度数排序)
- Karakamsha: AK在Navamsa中的上升(灵魂方向)
- Chara Dasha: 当前为简化 timing 实现,v6.0.9 后标注为 partial,不得单独作为高置信度应期依据
- Jaimini Sutras关键规则
"""
from typing import Dict, List, Tuple, Optional
import math
SIGNS = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo',
'Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces']
SIGN_LORDS = {'Aries':'Mars','Taurus':'Venus','Gemini':'Mercury','Cancer':'Moon',
'Leo':'Sun','Virgo':'Mercury','Libra':'Venus','Scorpio':'Mars',
'Sagittarius':'Jupiter','Capricorn':'Saturn','Aquarius':'Saturn','Pisces':'Jupiter'}
# Chara Karaka 定义(7星制,排除Rahu
KARAKA_7 = {
1: 'Atmakaraka', # AK - 灵魂指示星(度数最高)
2: 'Amatyakaraka', # AmK - 事业/顾问
3: 'Bhratrikaraka', # BK - 兄弟/勇气
4: 'Matrikaraka', # MK - 母亲
5: 'Putrakaraka', # PK - 子女
6: 'Gnatikaraka', # GK - 敌人/障碍
7: 'Darakaraka', # DK - 配偶(度数最低)
}
# 8星制(含Rahu,用绝对度数)
KARAKA_8 = {
1: 'Atmakaraka', 2: 'Amatyakaraka', 3: 'Bhratrikaraka', 4: 'Matrikaraka',
5: 'Putrakaraka', 6: 'Gnatikaraka', 7: 'Darakaraka', 8: 'Pitrukaraka',
}
KARAKA_CN = {
'Atmakaraka': '灵魂星AK', 'Amatyakaraka': '事业星AmK',
'Bhratrikaraka': '兄弟星BK', 'Matrikaraka': '母亲星MK',
'Putrakaraka': '子女星PK', 'Gnatikaraka': '障碍星GK',
'Darakaraka': '配偶星DK', 'Pitrukaraka': '父亲星PiK',
}
KARAKA_DOMAINS = {
'Atmakaraka': '灵魂使命、核心自我、人生最高目标',
'Amatyakaraka': '事业方向、主要谋士、权力代理',
'Bhratrikaraka': '兄弟姐妹、勇气、冒险精神',
'Matrikaraka': '母亲、家庭根基、情感安全感',
'Putrakaraka': '子女、创造力、学生、智能成果',
'Gnatikaraka': '竞争对手、疾病、障碍、转化力量',
'Darakaraka': '配偶特质、伴侣关系、婚姻质量',
'Pitrukaraka': '父亲、祖先业力、传统传承',
}
def calc_chara_karaka_7(planet_degrees: Dict[str, float]) -> Dict:
"""
计算7星制Chara Karaka(度数最高→AK,最低→DK)
参数: planet_degrees = {'Sun': 12.5, 'Moon': 8.3, ...}
每个行星在星座内的度数(0-30)
返回: {karaka_name: {'planet': str, 'degree': float, 'domain': str}}
"""
# 排除Rahu和Ketu
exclude = {'Rahu', 'Ketu'}
planets = {k: v for k, v in planet_degrees.items() if k not in exclude}
# 按度数降序排列(度数最高的=AK
sorted_planets = sorted(planets.items(), key=lambda x: x[1], reverse=True)
results = {}
for rank, (pname, deg) in enumerate(sorted_planets, 1):
if rank > 7:
break
karaka = KARAKA_7[rank]
results[karaka] = {
'planet': pname,
'degree_in_sign': round(deg, 4),
'rank': rank,
'domain': KARAKA_DOMAINS.get(karaka, ''),
'cn_name': KARAKA_CN.get(karaka, karaka),
}
# 额外分析
ak = results.get('Atmakaraka', {})
dk = results.get('Darakaraka', {})
return {
'karaka_table': results,
'summary': {
'AK': f"{ak.get('planet','?')} ({ak.get('degree_in_sign',0):.1f}°)",
'DK': f"{dk.get('planet','?')} ({dk.get('degree_in_sign',0):.1f}°)",
'AK_domain': ak.get('domain', ''),
'DK_domain': dk.get('domain', ''),
}
}
def calc_chara_karaka_8(planet_degrees: Dict[str, float]) -> Dict:
"""
计算8星制Chara Karaka(含Rahu,使用30-度数来处理Rahu逆行)
"""
planets = {}
for pname, deg in planet_degrees.items():
if pname == 'Ketu':
continue
if pname == 'Rahu':
# Rahu直接使用星座内度数(与其它行星相同),不做取反
planets[pname] = deg
else:
planets[pname] = deg
sorted_planets = sorted(planets.items(), key=lambda x: x[1], reverse=True)
results = {}
for rank, (pname, deg) in enumerate(sorted_planets, 1):
if rank > 8:
break
karaka = KARAKA_8[rank]
results[karaka] = {
'planet': pname,
'degree_in_sign': round(deg, 4),
'rank': rank,
'domain': KARAKA_DOMAINS.get(karaka, ''),
'cn_name': KARAKA_CN.get(karaka, karaka),
}
return {'karaka_table_8': results}
def calc_chara_dasha(asc_sign_idx: int,
planet_longitudes: Dict[str, float],
birth_year: int, birth_month: int) -> Dict:
"""
Chara Dasha计算(简化实现;v6.0.9 后能力状态为 partial
规则:
- 从上升星座开始
- 奇数星座(Aries, Gemini...):正向顺序
- 偶数星座(Taurus, Cancer...):反向顺序
- 每个大运长度 = 12 - 该星座内的行星数量(用特定规则)
- 注意:该实现不是 KN Rao / PVN Rao / Iranganti 完整传统算法;只能作低权重辅助
"""
# 确定顺序方向
is_odd = asc_sign_idx % 2 == 0
direction = 1 if is_odd else -1
# 生成大运序列
dasha_sequence = []
current = asc_sign_idx
# 简化 Chara Dasha: 按上升星座顺/逆排列;不等同于 KN Rao/PVN Rao/Iranganti 完整传统算法
for i in range(12):
sign_idx = (current + direction * i) % 12
sign_name = SIGNS[sign_idx]
lord = SIGN_LORDS[sign_name]
# 大运长度计算(简化版:基于星座的默认年数)
# 标准法:大运长度 = 基于该星座中行星的Karakamsa计算
# 简化法:每个大运1年
duration = _chara_dasha_duration(sign_idx, planet_longitudes)
dasha_sequence.append({
'sign': sign_name,
'sign_idx': sign_idx,
'lord': lord,
'duration_years': duration,
'order': i + 1,
})
# 计算日期
total_years = sum(d['duration_years'] for d in dasha_sequence)
current_year = birth_year
current_month = birth_month
for d in dasha_sequence:
d['start_date'] = f"{current_year}-{current_month:02d}"
end_month = current_month + int(d['duration_years'] * 12)
end_year = current_year + end_month // 12
end_month = end_month % 12
if end_month == 0:
end_month = 12
end_year -= 1
d['end_date'] = f"{end_year}-{end_month:02d}"
current_year = end_year
current_month = end_month + 1
if current_month > 12:
current_month = 1
current_year += 1
return {
'ascendant': SIGNS[asc_sign_idx],
'direction': 'forward' if is_odd else 'backward',
'dasha_sequence': dasha_sequence,
'total_years': total_years,
}
def calc_chara_dasha_with_antardasha(asc_sign_idx: int,
planet_longitudes: Dict[str, float],
birth_year: int, birth_month: int) -> Dict:
"""
Chara Dasha 计算含 Antardasha 子周期(简化 timing 实现,能力状态 partial
Antardasha 规则:
- 在每个 Mahadasha 内,Antardasha 从 Mahadasha 星座开始
- 方向与 Mahadasha 方向相同
- 每个 Antardasha 时长 = (该子星座大运年数 / 总大运年数) * Mahadasha 年数
- 生成 12 个 Antardasha
"""
# 先算 Mahadasha
base = calc_chara_dasha(asc_sign_idx, planet_longitudes, birth_year, birth_month)
is_odd = asc_sign_idx % 2 == 0
direction = 1 if is_odd else -1
base_total = sum(_chara_dasha_duration((asc_sign_idx + direction * i) % 12, planet_longitudes) for i in range(12))
# 为每个 Mahadasha 计算 Antardasha
for md in base['dasha_sequence']:
md_sign_idx = md['sign_idx']
md_duration = md['duration_years']
antardasha_list = []
# Antardasha 也从该 Mahadasha 星座开始,同方向
for j in range(12):
ad_sign_idx = (md_sign_idx + direction * j) % 12
ad_sign = SIGNS[ad_sign_idx]
ad_lord = SIGN_LORDS[ad_sign]
# 子周期时长 = (该星座独立年数 / 总年数) * Mahadasha 年数
ad_independent_duration = _chara_dasha_duration(ad_sign_idx, planet_longitudes)
ad_duration = round((ad_independent_duration / base_total) * md_duration, 2)
if ad_duration < 0.01:
ad_duration = 0.01 # 最小约4天
antardasha_list.append({
'sign': ad_sign,
'sign_idx': ad_sign_idx,
'lord': ad_lord,
'duration_years': ad_duration,
'order': j + 1,
})
# 计算 Antardasha 日期
start_year, start_month = map(int, md['start_date'].split('-'))
for ad in antardasha_list:
ad['start_date'] = f"{start_year}-{start_month:02d}"
total_months = round(ad['duration_years'] * 12)
end_month = start_month + total_months
end_year = start_year + (end_month - 1) // 12
end_month = ((end_month - 1) % 12) + 1
ad['end_date'] = f"{end_year}-{end_month:02d}"
# 下一个 Antardasha 的开始
if end_month < 12:
start_year = end_year
start_month = end_month + 1
else:
start_year = end_year + 1
start_month = 1
md['antardashas'] = antardasha_list
base['has_antardasha'] = True
return base
def _chara_dasha_duration(sign_idx, planet_lons):
"""计算Chara Dasha单个大运的年数"""
# 标准方法:12 - 落入该星座的行星数量(最少1年,最多12年)
count = 0
for pname, lon in planet_lons.items():
if pname in ('Rahu', 'Ketu'):
continue
p_sign = int(lon / 30) % 12
if p_sign == sign_idx:
count += 1
return max(1, 12 - count)
def calc_karakamsha(ak_sign_in_d9: str, ak_degree_in_d9: float) -> Dict:
"""
Karakamsha分析:AKAtmakaraka,灵魂星)在D9中的位置作为"灵魂上升"
这是Jaimini体系中判断人生终极方向的关键技法
经典定义:Karakamsha = Atmakaraka在Navamsa(D9)中落入的星座
从这个星座看12宫的布局,分析灵魂方向
⚠️ 2026-05-03修正:此前版本错误使用DK(配偶星),现已修正为AK(灵魂星)
参数:
ak_sign_in_d9: AK(灵魂星)在D9中的星座
ak_degree_in_d9: AK在D9中的度数
"""
sign_idx = SIGNS.index(ak_sign_in_d9) if ak_sign_in_d9 in SIGNS else 0
lord = SIGN_LORDS.get(ak_sign_in_d9, '')
# Karakamsha Lagna = AK(灵魂星)在D9中的位置
# 从这个位置看12宫的布局,分析灵魂方向
interpretations = _karakamsha_interpretations(ak_sign_in_d9, lord)
return {
'karakamsha_sign': ak_sign_in_d9,
'karakamsha_degree': ak_degree_in_d9,
'karakamsha_lord': lord,
'soul_direction': interpretations,
}
def _karakamsha_interpretations(sign, lord):
"""Karakamsha的灵魂方向解读"""
directions = {
'Aries': '灵魂追求独立、开拓、成为先驱',
'Taurus': '灵魂追求稳定、物质安全感、感官和谐',
'Gemini': '灵魂追求知识、沟通、多元体验',
'Cancer': '灵魂追求情感连接、家庭、滋养他人',
'Leo': '灵魂追求创造力、领导力、自我表达',
'Virgo': '灵魂追求服务、完善、分析能力',
'Libra': '灵魂追求平衡、关系和谐、美学',
'Scorpio': '灵魂追求转化、深层真相、神秘学',
'Sagittarius': '灵魂追求真理、哲学、智慧传播',
'Capricorn': '灵魂追求成就、结构、社会贡献',
'Aquarius': '灵魂追求革新、人道主义、群体觉醒',
'Pisces': '灵魂追求灵性、超越、无条件的爱',
}
lord_meanings = {
'Sun': '通过权威、创造力和自我实现达成',
'Moon': '通过情感智慧、直觉和公众影响力达成',
'Mars': '通过行动力、勇气和技术能力达成',
'Mercury': '通过智慧、沟通和学习能力达成',
'Jupiter': '通过智慧、教导和灵性成长达成',
'Venus': '通过美学、关系和创造力达成',
'Saturn': '通过耐力、自律和长期承诺达成',
}
return {
'sign_direction': directions.get(sign, ''),
'lord_method': lord_meanings.get(lord, ''),
}
# ============================================================================
# Darakaraka (DK) 计算 —— v6.0.14 新增
# ============================================================================
def calc_darakaraka(planet_degrees: Dict[str, float],
use_8karaka: bool = False) -> Dict:
"""
计算 Darakaraka (DK) —— Jaimini 体系中代表配偶/伴侣的行星。
规则(7星制):
- 排除 Rahu/Ketu,剩余7颗行星按度数升序排列
- 度数最低的行星 = Darakaraka (DK) —— 配偶特质星
- 度数最高的行星 = Atmakaraka (AK) —— 灵魂星
规则(8星制):
- 含 Rahu,8颗行星按度数升序排列
- 度数最低的 = DK,度数最高的 = AK
参数:
planet_degrees: {行星名: 星座内度数(0-30)}
use_8karaka: 是否使用8星制(含Rahu
返回:
{
'DK': {'planet': str, 'degree': float, 'rank': 7(7星制)或8(8星制)},
'AK': {'planet': str, 'degree': float, 'rank': 1},
'all_karaka': {rank: {'planet','degree','name'}},
'dk_interpretation': str,
'marriage_significator': str,
}
"""
if use_8karaka:
planets = {k: v for k, v in planet_degrees.items() if k != 'Ketu'}
karaka_def = KARAKA_8
total = 8
else:
planets = {k: v for k, v in planet_degrees.items()
if k not in ('Rahu', 'Ketu')}
karaka_def = KARAKA_7
total = 7
# 按度数升序排列(度数最低=DK
sorted_p = sorted(planets.items(), key=lambda x: x[1])
all_karaka = {}
dk_info = None
ak_info = None
for rank, (pname, deg) in enumerate(sorted_p[:total], 1):
karaka_name = karaka_def[rank]
entry = {
'planet': pname,
'degree_in_sign': round(deg, 4),
'rank': rank,
'name': karaka_name,
'cn_name': KARAKA_CN.get(karaka_name, karaka_name),
'domain': KARAKA_DOMAINS.get(karaka_name, ''),
}
all_karaka[rank] = entry
if karaka_name == 'Darakaraka':
dk_info = entry
if karaka_name == 'Atmakaraka':
ak_info = entry
# 解读 DK
dk_planet = dk_info['planet'] if dk_info else '?'
dk_interp = _dk_interpretation(dk_planet)
marriage_sig = _marriage_significator(dk_planet, ak_info['planet'] if ak_info else '?')
return {
'DK': dk_info,
'AK': ak_info,
'all_karaka': all_karaka,
'dk_planet': dk_planet,
'dk_degree': dk_info['degree_in_sign'] if dk_info else None,
'dk_interpretation': dk_interp,
'marriage_significator': marriage_sig,
'use_8karaka': use_8karaka,
}
def _dk_interpretation(dk_planet: str) -> str:
"""Darakaraka 行星的配偶特质解读"""
interpretations = {
'Sun': '配偶有权威感、领导力强,可能比命主年长或地位高;关系中需要尊重和认可',
'Moon': '配偶情感丰富、重视家庭,情绪敏感;关系以情感连接为核心',
'Mars': '配偶行动力强、有魄力,可能性格急躁;关系中需要空间和尊重',
'Mercury': '配偶聪明、善于沟通,可能从事文书/教育/商业;关系以交流为基础',
'Jupiter': '配偶有智慧、教导型人格,可能从事教育/法律/宗教;关系有成长导向',
'Venus': '配偶有魅力、重视美学和享受,浪漫且物质条件好;关系充满爱和美好',
'Saturn': '配偶成熟稳重、有责任感,可能年龄差距较大;关系需要时间和承诺',
'Rahu': '配偶背景复杂、有野心,可能来自不同文化/阶层;关系有非常规色彩',
'Ketu': '配偶有灵性倾向、可能疏离,关系有超脱/宿命感',
}
return interpretations.get(dk_planet, f'DK={dk_planet},需结合全盘分析')
def _marriage_significator(dk: str, ak: str) -> str:
"""AK-DK 关系对婚姻的综合指示"""
# AK=灵魂,DK=配偶,两者关系反映灵魂与伴侣的互动模式
relations = {
('Sun', 'Moon'): '灵魂(Sun)与情感(Moon)结合,婚姻中有父性保护色彩',
('Moon', 'Sun'): '情感(Moon)与权威(Sun)结合,配偶可能是引导者/权威人物',
('Venus', 'Jupiter'): '爱(Venus)与智慧(Jupiter)结合,婚姻有成长和教育意义',
('Jupiter', 'Venus'): '智慧(Jupiter)与爱(Venus)结合,配偶带来美感和快乐',
}
key = (ak, dk)
return relations.get(key, f'AK={ak}与DK={dk}的组合,需结合两者星座/宫位深入分析')
def calc_dk_marriage_analysis(dk_planet: str,
dk_sign: str,
dk_house: int,
ak_sign: str,
ak_house: int,
venus_sign: str,
venus_house: int,
seventh_lord: str,
seventh_lord_sign: str) -> Dict:
"""
综合 DK 信息进行婚姻分析(v6.0.14 新增)
参数:
dk_planet: DK行星名
dk_sign: DK所在星座
dk_house: DK所在宫位(1-12
ak_sign: AK所在星座
ak_house: AK所在宫位
venus_sign: Venus所在星座
venus_house: Venus所在宫位
seventh_lord: 第七宫宫主星
seventh_lord_sign: 第七宫宫主星所在星座
返回:婚姻分析字典
"""
# DK 在宫位的解读
dk_house_meaning = _dk_house_meaning(dk_house)
# Venus 与 DK 的关系
venus_dk_relation = _venus_dk_relation(venus_sign, dk_sign, venus_house, dk_house)
# 第七宫分析
seventh_analysis = _seventh_house_analysis(seventh_lord, seventh_lord_sign)
# 综合婚姻时机指示
marriage_timing = _marriage_timing_indication(dk_planet, venus_sign, seventh_lord)
return {
'dk_planet': dk_planet,
'dk_sign': dk_sign,
'dk_house': dk_house,
'dk_house_meaning': dk_house_meaning,
'venus_dk_relation': venus_dk_relation,
'seventh_analysis': seventh_analysis,
'marriage_timing': marriage_timing,
'summary': f"配偶星DK={dk_planet}{dk_sign}{dk_house}宫;{dk_house_meaning}",
}
def _dk_house_meaning(house: int) -> str:
"""DK所在宫位对婚姻的意义"""
meanings = {
1: '配偶与命主高度相似,自我认同与伴侣融合',
2: '配偶带来财富/家庭资源,可能通过婚姻改善经济状况',
3: '配偶是命主的勇气来源,可能有兄弟姐妹牵线',
4: '配偶带来情感安全感,家庭和谐,可能有房产',
5: '配偶与子女/创造力有关,浪漫关系,可能有年龄差',
6: '配偶可能是工作伙伴/竞争对手,关系中需注意健康/债务',
7: '配偶是命主的直接伙伴,婚姻关系最直接',
8: '配偶带来深层转化,可能涉及神秘事务/遗产/危机',
9: '配偶有灵性/哲学导向,可能来自不同文化背景',
10: '配偶与事业/社会地位有关,可能因工作相识',
11: '配偶带来收益/社交网络,朋友变伴侣',
12: '配偶涉及潜意识/海外/隐秘事务,可能是异地/外籍',
}
return meanings.get(house, '')
def _venus_dk_relation(venus_sign: str, dk_sign: str,
venus_house: int, dk_house: int) -> str:
"""Venus与DK的关系分析"""
# 简化:看两者是否同一星座或相邻宫位
venus_idx = SIGNS.index(venus_sign) if venus_sign in SIGNS else -1
dk_idx = SIGNS.index(dk_sign) if dk_sign in SIGNS else -1
if venus_idx >= 0 and dk_idx >= 0:
diff = abs(venus_idx - dk_idx)
if diff <= 1 or diff >= 11:
return 'Venus与DK能量融合,爱与婚姻高度一致'
elif diff <= 3:
return 'Venus与DK有一定张力,爱情与婚姻选择可能有分歧'
else:
return 'Venus与DK度数较远,爱情观与婚姻现实有差距'
return 'Venus/DK关系需结合全盘确定'
def _seventh_house_analysis(seventh_lord: str, seventh_lord_sign: str) -> str:
"""第七宫宫主星分析"""
lord_meanings = {
'Sun': '配偶有领导力,可能从事管理/政府工作',
'Moon': '配偶情感丰富,可能从事护理/餐饮/海洋相关',
'Mars': '配偶有行动力,可能从事技术/军事/体育',
'Mercury': '配偶聪明善辩,可能从事教育/写作/商业',
'Jupiter': '配偶有智慧,可能从事教育/法律/宗教',
'Venus': '配偶有魅力,可能从事艺术/娱乐/美容',
'Saturn': '配偶成熟稳重,可能从事结构/建筑/长期项目',
}
return lord_meanings.get(seventh_lord, f'第七宫主星={seventh_lord},需结合全盘')
def _marriage_timing_indication(dk_planet: str, venus_sign: str,
seventh_lord: str) -> str:
"""婚姻时机的简化指示(需结合Dasha/Transit使用)"""
return (f"婚姻窗口与DK={dk_planet}、Venus在{venus_sign}"
f"第七宫主星={seventh_lord}的Dasha/Transit高度相关;"
f"具体应期需结合Vimshottari Dasha和Gochara(过境)确定")