rhannequin / astronoby

Ruby library based on astronomy and astrometry books
https://dev.to/rhannequin/series/17782
MIT License
59 stars 2 forks source link

Infinite Loop Calculating Moon Observation Events #109

Closed billyyarosh closed 1 week ago

billyyarosh commented 1 week ago

Description

It's not clear what's causing this infinite loop, but given specific coordinates and time data, we are running into infinite loops computing observation events for moon phases. I could only reproduce this for Nov 10, 2024, with longitudes in the western hemisphere.

Reproduction Steps

lat = 41.02054 
lon = -72.15608
date = Date.new(2024, 11, 10)

observer = Astronoby::Observer.new(
  latitude: Astronoby::Angle.from_degrees(lat),
  longitude: Astronoby::Angle.from_degrees(lon)
)

moon = Astronoby::Moon.new(time: date.to_time)
moon_events = moon.observation_events(observer: observer) # <-- infinite loop hit

Expected behavior

Results returned

Actual behavior

Infinite Loop in ObservationEvents line 95.

def iterate(initial_rising, initial_transit, initial_setting)
        delta = 1
        corrected_rising = initial_rising
        corrected_transit = initial_transit
        corrected_setting = initial_setting
        until delta < ITERATION_PRECISION <--- delta oscillates between two values > `ITERATION_PRECISION`
          iterate = RiseTransitSetIteration.new(
            observer: @observer,
            date: @date,
            coordinates_of_the_next_day: @coordinates_of_the_next_day,
            coordinates_of_the_day: @coordinates_of_the_day,
            coordinates_of_the_previous_day: @coordinates_of_the_previous_day,
            shift: shift,
            initial_rising: corrected_rising,
            initial_transit: corrected_transit,
            initial_setting: corrected_setting
          ).iterate
          delta = iterate.sum
          puts delta
          corrected_rising = rationalize_decimal_time corrected_rising + iterate[0]
          corrected_transit = rationalize_decimal_time corrected_transit + iterate[1]
          corrected_setting = rationalize_decimal_time corrected_setting + iterate[2]
        end
        [corrected_rising, corrected_transit, corrected_setting]
      end

Output of delta value:

Delta: 1 | ITERATION_PRECISION 0.0001
Delta: 0.05579327610748758 | ITERATION_PRECISION 0.0001
Delta: 0.9685195308025412 | ITERATION_PRECISION 0.0001
Delta: 0.03219316342944962 | ITERATION_PRECISION 0.0001
Delta: 0.9678321976156058 | ITERATION_PRECISION 0.0001
Delta: 0.03216888120673453 | ITERATION_PRECISION 0.0001
Delta: 0.9678311688422382 | ITERATION_PRECISION 0.0001
Delta: 0.03216883356000096 | ITERATION_PRECISION 0.0001
Delta: 0.9678311665568381 | ITERATION_PRECISION 0.0001
Delta: 0.032168833448871344 | ITERATION_PRECISION 0.0001
Delta: 0.9678311665514086 | ITERATION_PRECISION 0.0001
Delta: 0.03216883344860502 | ITERATION_PRECISION 0.0001
Delta: 0.9678311665513957 | ITERATION_PRECISION 0.0001
Delta: 0.03216883344860461 | ITERATION_PRECISION 0.0001
Delta: 0.9678311665513954 | ITERATION_PRECISION 0.0001
Delta: 0.03216883344860461 | ITERATION_PRECISION 0.0001
......
Delta: 0.9678311665513957 | ITERATION_PRECISION 0.0001
Delta: 0.03216883344860461 | ITERATION_PRECISION 0.0001
Delta: 0.9678311665513954 | ITERATION_PRECISION 0.0001
Delta: 0.03216883344860461 | ITERATION_PRECISION 0.0001

System configuration

astronoby version: 0.5.0 ruby version: ruby 3.1.4p223

rhannequin commented 1 week ago

Thank you for opening this issue, @billyyarosh I'm also quite happy to have feedback and to see that some people might be using the library.

I've opened #110 to fix the issue. This is a simple workaround as I haven't been able to identify a deeper problem with the algorithm. It feels right to set a limit to a loop anyway.

If you're interested, feel free to have a look and give a review. Otherwise, I will probably merge the fix over the weekend.