Reverse lookup
solar_dates_by_bazi and reverse_chart - the functions and types for recovering candidate birth dates from BaZi pillars or chart features.
Recover candidate birth dates from four BaZi pillars or from chart features. Both entry points are "pruned enumeration + full re-charting", so results have zero divergence from forward charting. Concepts, how pillars follow the Config boundaries, and the multi-solution / truncation semantics are on the reverse lookup guide.
use x_iztro::*;
let cands = solar_dates_by_bazi(
(HeavenlyStem::Geng, EarthlyBranch::Chen),
(HeavenlyStem::Jia, EarthlyBranch::Shen),
(HeavenlyStem::Bing, EarthlyBranch::Wu),
(HeavenlyStem::Geng, EarthlyBranch::Yin),
(1900, 2100),
&Config::default(),
)?;Everything is defined in x_iztro::astro::reverse and re-exported at the crate
root.
Types
BirthCandidate
One candidate birth moment, ready to hand to by_solar.
| Field | Type | Meaning |
|---|---|---|
solar_date | String | solar date, YYYY-M-D |
time_index | u8 | hour index 0–12 (0 = early Zi hour, 12 = late Zi hour) |
StarPosition
A star and the branch of the palace it sits in: the atomic condition of a feature lookup.
| Field | Type | Meaning |
|---|---|---|
star | StarKey | the star (natal chart stars only; horoscope-scope flow stars are rejected) |
branch | EarthlyBranch | the branch of its palace |
ReverseCriteria
The condition set of a feature lookup. Implements Default; the idiomatic
construction gives the conditions and closes with ..Default::default().
Every condition is optional, but at least one must be given.
| Field | Type | Default | Meaning |
|---|---|---|---|
soul_branch | Option<EarthlyBranch> | None | soul palace branch |
body_branch | Option<EarthlyBranch> | None | body palace branch |
five_elements_class | Option<FiveElementsClass> | None | five elements class |
stars | Vec<StarPosition> | empty | star placements, all of which must hold |
mutagens | [Option<StarKey>; 4] | all None | which star carries each birth-year mutagen [Lu, Quan, Ke, Ji] |
year_range | (i64, i64) | (1900, 2100) | inclusive solar year range, within 1583–9999 |
fix_leap | bool | true | leap month correction, same meaning as the charting parameter |
limit | usize | 0 | candidate cap; 0 takes DEFAULT_REVERSE_LIMIT |
ReverseResult
| Field | Type | Meaning |
|---|---|---|
candidates | Vec<BirthCandidate> | the birth candidates satisfying every condition |
truncated | bool | whether the search stopped early at the candidate cap; later solutions were never searched |
DEFAULT_REVERSE_LIMIT
pub const DEFAULT_REVERSE_LIMIT: usize = 512;The candidate cap used when ReverseCriteria::limit is 0.
solar_dates_by_bazi
Recover solar birth dates from four BaZi pillars.
pub fn solar_dates_by_bazi(
yearly: (HeavenlyStem, EarthlyBranch),
monthly: (HeavenlyStem, EarthlyBranch),
daily: (HeavenlyStem, EarthlyBranch),
hourly: (HeavenlyStem, EarthlyBranch),
year_range: (i64, i64),
config: &Config,
) -> Result<Vec<BirthCandidate>, IztroError>The pillars are interpreted under the boundary readings of config
(year_divide for the year pillar, horoscope_divide for the month pillar,
day_divide for the late Zi hour) — the same semantics as the
raw_dates.chinese_date a charted astrolabe reports, so reversing any chart's
pillars always includes that chart's birth moment. A set of pillars recurs
roughly every 60 years within the range; an hour branch of Zi may yield two
candidates on adjacent days because of the early/late Zi hour split.
Example
let a = by_solar("2000-8-16", 2, Gender::Female, true, Language::EnUS, Config::default())?;
let p = a.raw_dates.chinese_date;
let cands = solar_dates_by_bazi(p.yearly, p.monthly, p.daily, p.hourly, (1900, 2100), &Config::default())?;
for c in &cands {
println!("{} {}", c.solar_date, c.time_index);
}Output
1940-8-31 2
2000-8-16 2
2060-8-1 2Errors A pillar with mismatched stem/branch polarity (such as 甲丑 Jia-Chou — a yang stem on a yin branch), or a
year range that is reversed or outside 1583–9999, returns
IztroError::InvalidArgument.
reverse_chart
Recover candidate birth dates from chart features.
pub fn reverse_chart(
criteria: &ReverseCriteria,
config: &Config,
) -> Result<ReverseResult, IztroError>Judgement runs entirely under config: the mutagen table, the school and every
boundary follow it, so charting a candidate with the same config is
guaranteed to satisfy every condition. Chart layout does not depend on gender
(gender only affects the direction the decadal horoscope advances), so the
criteria carry no gender.
Example
let r = reverse_chart(
&ReverseCriteria {
soul_branch: Some(EarthlyBranch::Wu),
five_elements_class: Some(FiveElementsClass::Wood3rd),
stars: vec![StarPosition { star: StarKey::ZiweiMaj, branch: EarthlyBranch::Wu }],
mutagens: [Some(StarKey::TaiyangMaj), None, None, None],
year_range: (1998, 2002),
..Default::default()
},
&Config::default(),
)?;
println!("{} {}", r.candidates.len(), r.truncated);Output
39 falseErrors Empty criteria, a horoscope-scope flow star in stars, or an
invalid year range returns
IztroError::InvalidArgument.
truncated means truncation, not sampling
Reaching limit stops the search; later solutions never appear in the result.
On truncated = true, narrow year_range or add conditions and query again.