10BC0 Code to optimize the choice of new moon by sffc · Pull Request #7053 · unicode-org/icu4x · GitHub
[go: up one dir, main page]

Skip to content

Conversation

sffc
Copy link
Member
@sffc sffc commented Oct 9, 2025

Trying to pick the best value for the new moon. Output of this test:

OptimizationResult:
    Solver:        BrentOpt
    param (best):  0.5961012372892227
    cost (best):   244.805785003407
    iters (best):  2
    iters (total): 6
    termination:   Solver converged
    time:          621.786µs

which equates to about 14:18 UTC on Jan 6, 2000, as compared to 18:14 on that day as we currently have.

CC @robertbastian

type Output = f64;
fn cost(&self, param: &f64) -> Result<f64, Error> {
let candidate = self.center_moment + *param;
Ok(self.new_moon_moments.iter().map(|(i, x)| (candidate - *x) - self.mean_synodic_length * (self.new_moon_number - i) as f64).map(|v| v * v).sum::<f64>())
Copy link
Member
@robertbastian robertbastian Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this uses mean absolute error for the new moon dates. but the date of the new moon is not the only thing our algorithm approximates.

the cost should be the count of months where the simple approximation doesn't match the GB/T calculations for >2100 (and potentially the ground truth for <1900, weighted appropriately)

Comment on lines +194 to +196
let jan1900 = fixed_from_gregorian(1900, 1, 1);
let jan2000 = fixed_from_gregorian(2000, 1, 1);
let jan2100 = fixed_from_gregorian(2100, 1, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the one range where the approximation isn't used, so why optimise over that?

let cost_fn = NewMoons {
new_moon_moments,
mean_synodic_length: MEAN_SYNODIC_MONTH_LENGTH_F64,
center_moment: Moment::try_from_rata_die(fixed_from_gregorian(2000, 1, 6)).unwrap(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: our LocalMoment is milliseconds-i64. optimising a Moment, which is day-f64, is not equivalent

const MEAN_SYNODIC_MONTH_LENGTH: Milliseconds = day_fraction_to_ms!(295305888531 / 10000000000i64);

#[cfg(test)]
const MEAN_SYNODIC_MONTH_LENGTH_F64: f64 = 29.5305888531;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: this is not an exact version of MEAN_SYNODIC_MONTH_LENGTH

@robertbastian
Copy link
Member

which equates to about 14:18 UTC on Jan 6, 2000, as compared to 18:14 on that day as we currently have.

18:14 which actually happened

if you want to do this, we should optimise the choice of actual new moon, instead of inventing one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0