farmOS / farm_grazing

Rotational grazing planning module for farmOS v1. For newer efforts, see https://drupal.org/project/farm_grazing_plan
4 stars 1 forks source link

Integer vs floating grazing days #27

Open woodbri opened 6 years ago

woodbri commented 6 years ago

Currently the database and the mathematics around planning computes floating point numbers for grazing days. The plotting software rounds grazing days to an integer so number <0.5 round to zero days.

It seems that in reality, grazing days need to be whole days.

This presents a few problems that need to be sorted out.

woodbri commented 6 years ago

This is related to issue #4

mstenta commented 6 years ago

Yea, I think it makes sense to represent rotation durations in whole numbers. While I could see the potential usefulness for rotating animals more than once a day, I think it is a real limited use-case, and in either case the rest of the module doesn't necessarily handle it well as-is currently (ie: start dates do not currently show TIME of rotation - it is assumed that you won't have more than one movement in the same day). And we can always add it back in the future (along with other changes to make it more "complete") if there is demand for that. For now, converting to whole numbers will simplify a lot of things, I think.

the math for planning needs to be adjusted to only generate plans with integer grazing days

I made one change to this already in my rotations_form branch: https://github.com/mstenta/farm_grazing/commit/7b68da68fddbc26498dff48d9eecee5e3fc1d578

But as you discovered, that is not complete - because the database is still capable of storing floats, and old data is still being represented as decimals. So we will need another update hook to round all of that data (and if anything rounds down to zero we should make it == 1 instead). I can tackle that piece - not hard.

what do we do with a small paddock or large herd that generates a value(s) less than one grazing day

I think if this happens, we should still allow it - but we should highlight it to the user somehow - maybe via a warning when they create the rotation? Perhaps something to the effect of "The paddock [X] may not have enough forage to support the herd for a whole day."

The farmer knows best though - so we shouldn't prevent anything. It's always going to be possible that our calculations are not perfectly reflective of the real world (this will be the case more often than not, I would assume) - so ultimately we should always leave it up to the user to decide what they want to do.

what is the impact of of rounding grazing days on many paddocks, for example a 100 strip grazing paddocks, where the accumulated rounding error becomes significant.

That's a good point - for example if you have 20 paddocks, and each should only be grazed for 0.5 days - rounding up to 1 on all of them would mean a total of 20 grazing days, when it should be 10.

Not sure what the best way to deal with this is...

mstenta commented 6 years ago

If we do decide to use whole numbers, does that mean we can just close #4 as a duplicate of this (more general) issue? That one is just about the plotting (which is already rounding to whole numbers), right? So if we use whole numbers everywhere, then the plotting won't be wrong anymore.

The potential for accumulating rounding error is still a possible issue though... it just becomes more of a system-wide issue instead of just in the plotting.

mstenta commented 6 years ago

Maybe the code could keep track of the rounding remainders as it is doing calculations, and factor it back in somehow?

mstenta commented 6 years ago

I took the rounding commit I made originally in the rotation_form branch, and moved it to a new branch called issue27: https://github.com/mstenta/farm_grazing/commit/0d30f13e1da6ea201a5ca6f8b542a2e857b00747

So we can use that branch moving forward to work on this.

I'm going to go ahead and add an update hook for converting the database column to an integer, and rounding all existing data. We'll want to test that with some real data, of course, but it will provide a start.

mstenta commented 6 years ago

With regard to the cumulative rounding errors, one idea might be to always round down to the nearest whole number. So you are always erring on the side of too much forage, and not too little. This could even be configurable.

The one exception is that it still should never round down to zero - a rotation should always have a duration >= 1 day(s). And if that happens (it gets rounded up to 1), a warning can be displayed to the user - letting them know that the paddock may not support a full day of grazing.

woodbri commented 6 years ago

Jess Maier says:

I wouldn't round. Sometimes you want to have really high density short duration grazing which means multiple moves per day. Maybe if you do want to round you could adjust it manually.

So maybe we need to set this as a config option that users can set globally for the install or for a plan?

For plotting, since we converted over to SVG, the bar widths can be floating point numbers, so they do not need to be rounded.

mstenta commented 6 years ago

Added two commits to the issue27 branch:

Convert grazing rotation durations to whole numbers: https://github.com/mstenta/farm_grazing/commit/d6fb4136a994f0a3f19b0b5a2902e406930e82b4

Round down to the nearest whole integer using floor(): https://github.com/mstenta/farm_grazing/commit/2b0028d2d1c10850f7a0e7fdacd035e16dd7b0ce

mstenta commented 6 years ago

Ha! Just saw that too. :-)

If we don't round, we'll need to address a few things regardless: the start_date of the rotations are assuming whole days, as is the plotting (#4).

woodbri commented 6 years ago

Also when we talk about a grazing day, what does that mean from the animals point of view, they are not grazing at night for example. If I go back to the math, I think it works like this: we take the animals weight and type and compute their daily intake and then we compare that to ADA/H * acres to compute the grazing days. So 0.5 grazing day is literally half of the "grazing part of a day" for the animal and not 12 hrs. or half of a 24 hr day.

mstenta commented 6 years ago

My reply to Jess this morning - with some thoughts about potential next steps:

Thanks Jess - that's good to know.

That makes sense for rotations that are less than one day. Is it OK to round down rotations that are greater than one day, though? Example: 15.5 days round down to 15? I assume if you're grazing a paddock for 2+ weeks, you're not really timing it to the half day, right? So maybe we could just make the high-density grazing feature for rotations less than 1 day?

In either case it sounds like we may need to expand this into a new feature request.

Rotations are currently calculated with fractions of a day, but the other (arguably more important) parts of the system are already rounding to whole numbers. So in order to be able to actually handle fractional days, we would need to expand those pieces to be able to fully support them.

For example: the "start date" and "end date" of a rotation is always assuming whole days. So are the plotted green and orange bars.

If more than one rotation is going to happen in a single day, then the start/end times of the rotation will need to have a TIME, as well as the date. The tricky part with that is that simply auto-calculating a time right now would result in times all over the place - ie: during the night - which wouldn't make sense. Maybe we could add some more logic to it so that it always has rotation times during the daylight hours, but that will take some figuring out...

As for right now... we may be able to just leave it as-is - knowing that it will calculate fractional days, but the start/end dates will be rounded to whole days. So it's not perfect as-is, but it still works for the most part.

Or, we could just temporarily force it to round to whole days - until we have a chance to work out all the details for enabling fractional days.

Thoughts?

mstenta commented 6 years ago

Spoke with Kelly at Paicines Ranch - he echoed Jess that having fractional grazing days is really useful - especially when strip grazing a single paddock, moving the animals more than once per day.

One idea that came up is to denominate durations less than 1 day in hours, and assume that you can fit 12 hours of grazing into 1 day. This assumption would be used when determining the start date of each rotation. For example, if you have 6 rotations that are each 4 hours, the first three would be one day, and the last three would be the day after.

woodbri commented 6 years ago

Under config, give chart of days of year, and hours of daylight based on latitude and allow user to set the number of hours in a "grazing day"