feat: add Ekadhipatya Shodhana

(cherry picked from commit 868f1dadb69e870fbf20223e4fcd0550286bc220)
This commit is contained in:
732642856
2026-10-02 23:40:59 +08:00
committed by Jesse_Chen
parent 54f6930b23
commit 67aa1b33d7
2 changed files with 52 additions and 1 deletions
+42
View File
@@ -620,3 +620,45 @@ def calc_trikona_shodhana(sav_scores: List[int]) -> Dict:
'status': 'executed',
'claim_boundary': 'Standalone classical reduction; Ekadhipatya Shodhana remains a separate layer.',
}
EKADHIPATYA_SIGN_PAIRS = ((0, 7), (1, 6), (2, 5), (8, 11), (9, 10))
def calc_ekadhipatya_shodhana(
rows: Dict[str, List[int]], occupied_signs: set[int]
) -> Dict:
"""Apply PyJHora/PVR Ekadhipatya Shodhana to post-Trikona rows."""
reduced = {planet: list(values) for planet, values in rows.items()}
audit = []
for planet, values in reduced.items():
if len(values) != 12:
raise ValueError('each BAV row must contain exactly 12 signs')
for first, second in EKADHIPATYA_SIGN_PAIRS:
first_value, second_value = values[first], values[second]
if first_value == 0 or second_value == 0:
continue
first_occupied = first in occupied_signs
second_occupied = second in occupied_signs
before = [first_value, second_value]
if first_occupied and second_occupied:
continue
if first_occupied != second_occupied:
occupied, vacant = (first, second) if first_occupied else (second, first)
values[vacant] = values[occupied] if values[occupied] < values[vacant] else 0
elif first_value == second_value:
values[first] = values[second] = 0
elif first_value > second_value:
values[first] = second_value
else:
values[second] = first_value
audit.append({'planet': planet, 'pair': [first, second], 'before': before,
'after': [values[first], values[second]]})
return {
'method': 'Ekadhipatya Shodhana',
'rows': reduced,
'occupied_signs': sorted(occupied_signs),
'audit': audit,
'status': 'executed',
'claim_boundary': 'Applied after Trikona Shodhana; source profile follows PyJHora/PVR rule ordering.',
}
+10 -1
View File
@@ -5,10 +5,19 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'scripts'))
from ashtakavarga import calc_trikona_shodhana # noqa: E402
from ashtakavarga import calc_ekadhipatya_shodhana, calc_trikona_shodhana # noqa: E402
def test_trikona_shodhana_removes_each_trine_baseline() -> None:
result = calc_trikona_shodhana(list(range(1, 13)))
assert result['reduced_scores'] == [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8]
assert result['trikona_groups'][0]['baseline_removed'] == 1
def test_ekadhipatya_shodhana_records_occupied_vacant_pair() -> None:
result = calc_ekadhipatya_shodhana(
{'Sun': [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0]},
{9},
)
assert result['rows']['Sun'][9:11] == [6, 0]
assert result['audit'][0]['pair'] == [9, 10]