Test the new autodialer

@k1rsty When you look at the autodialer dashboard, what does it say the 30d average is for that goal?

I’m pretty certain it said 0/w yesterday. Today it says 0.23/w. But I’ve just realised I’ve added another datapoint to that goal today which might confuse things?

ETA: I’ve just pressed force run and it’s updated ot 0.23/w but I think that’s only half the rate it should be now there are 2 datapoints in the last 30 days?

I’m loving the new autodialer so far. Thanks, @nathur for building this!

I was wondering about a possible extra feature. The autodialer would be perfect to slowly force yourself to get better at a thing you have to get better at.

The autodialer currently dials up the number when I do the goal more often. However, if I could provide a setting of #autoConstRate=<number> in the fineprint and the autodialer slowly cranks up the goal up until #autodialMax that would be amazing.

Example:
Say I wanted to get myself to meditate more. Say currently, I’m at a rate of once per week, and over the year I want to become a daily meditator (so 7/w). So #autodialMax=7 needs to be set and then I can set a very ambitious increase of 1/w with #autodialConstInc=1 so I’d be a daily meditator after almost 2 months or boil the frog slowly with #autodialConstInc=.1 where I’d meditate twice per week after 10 weeks, and thrice per week after another 10 weeks, after 1.3 years I’d have made it to become a daily meditator.

Implementation:
I feel like this would be quite possible with the current infrastructure and the clipping method in dial.ts but I’m not smart enough to figure out the code for a proper PR (and have never coded in TypeScript).

I wonder if this would already be enough for the logic in dial.ts in addition to the settings.ts, but I’m sure I’m making an error…:

type Options = {
min?: number,
max?: number,
rate?: number
}

// Takes a goal g which includes roadall and data, returns new roadall
export function dial(
    g: GoalVerbose,
    opts: Options = {},
): Roadall | false {
const t = now();
const {min = -Infinity, max = Infinity, rate = 0} = opts;
// seconds in rate units
const siru = UNIT_SECONDS[g.runits];
// average rate per second
const arps = getRollingAverageRate(g);
const len = t - g.fullroad[0][0];
const oldRate = g.mathishard[2];
const naturalRate = arps * siru;
const newRate = oldRate + rate;
if (Math.abs(naturalRate) > Math.abs(newRate)) newRate = naturalRate;
const monthCompletion = Math.min(len / (SID * 30), 1);
const rateDiff = oldRate - newRate;
const modulatedRate = oldRate - (rateDiff * monthCompletion);
const clippedRate = clip(modulatedRate, min, max);

I understand of course if this is not part of your vision or too niche.

1 Like

@mufflon Huh, good thoughts… I think from an implementation perspective this would be a hard sell for me. Currently the autodialer can run using only the last month of a goal’s data, and without storing any extra state for each goal, regardless of how frequently the dialer is run. If I were to support a monthly additional rate change I’d need to keep track of when I last made the addition some how, which I think would mean storing mutable state if I’m understanding right…

Perhaps relatedly, I have considered in the past the possibility of an option to disallow the autodialer from ever making the goal easier (I think @dreev was in favor of that idea). You can get pretty close to that by enabling autoratcheting along with the autodialer, but maybe having that additional option would get you closer to what you’d like to achieve? Interested to hear your thoughts!

2 Likes

Maybe one way to get a similar kind of thing would be to add some constant amount to the rate every day?

Say I have a goal where I want the rate to increase by 1 every day and my data from the last 30 days would put the rate at 50 normally, you might set the rate at 51 instead. Whatever the data for the past 30 days comes to, you always add the 1. No need to remember anything, just constantly up the requirements by some amount.

I feel like there are probably a lot of ways that could go wrong that I haven’t thought of, but it could possibly work?

Also, I’d love to have the option to disallow the autodialer from ever making the goal easier!

1 Like

Unfortunately, daily has the same challenge as I don’t want to restrict myself to only running once daily. Currently users can force it to run as much as they like.

Ok, good to hear that only-harder is a mode you’d value!

1 Like

Ah, I see what you mean now. You can’t increase the rate relative to the previous day’s rate, which was how I was thinking of it.

Still, I think it could be useful to add a constant amount to the rate every time, relative to the 30-day average?

The way I’m seeing it now, going back to my example with a 30-day average of 50 (and a new monthly rate of 51), running it a second time would do the same thing again - take the average, add 1, and set the rate to 51 per month. No matter how many times I ran it, the same thing would happen. And if I add some data that increases the average to 55, running it again would lead to a rate of 56.
Of course, if the rate stays the same the next day, the rate after the adjustment will still be 51 per month, so it’s not a constant thing. But after 30 days (plus a week for the change to take effect), I’ll have reported at least 51 units, which will lead to the rate being increased to 52 per month, and so on.

I can see some weird behaviour coming from this, with goals that have sparser data taking longer to increase than goals with more constant data, etc. But it still seems useful to be able to say “whatever my 30-day average is, add X to it and set that as my rate”.

1 Like

I’ve added the strict option! Use #autodialStrict to enable it. Doing so will prevent the autodialer from ever dialing your goal easier.

3 Likes

Thanks so much! I’m going to get a lot of use out of this :grin:

1 Like

So this isn’t really a user-visible improvement, but up to today the datastore was global-writable (not readable) in order to simplify development. Today I finally fixed that, moving the datastore writing to cloud functions and locking down the datastore so it’s no longer global-writable.

2 Likes

Idly wondering whether there’s a straightforward stateless way to soften ‘never’ to only-after-a-derailment.

Philosophically, that seems like the ideal point to reset expectations for a goal.

1 Like

Hi @narthur, I’m pretty sure the autodialer broke my goal. Support has already been pinged, but it’s probably best you’re the one to take a look at it.

The goal is ianminds/read-alittlelife. It started out as a goal with a fixed rate and an end point (720). Yesterday I was annoyed, since I noticed the goal had somehow been changed to end in the late 600s. I edited my slope to set the right target again. Today, probably after the autodialer ran, the goal has a negative target and I can no longer fix it myself.

You can fix it by setting an explicit end date of 720 on March 3rd. I’ll disable the autodialer myself.

2 Likes

Ah, ok. After looking at your goal I have a hypothesis as to what happened. I think the autodialer may not be checking to see if the end of the akrasia horizon is beyond the end of the graph, so it just happily keeps adding rows to the end of the akraisa horizon, even when that results in adding rows after the end of the graph, which then breaks the goal.

In addition to that, the autodialer currently does not support using an end value instead of an end rate. It will happily squash the end row of your graph to convert it from value to rate. Would be helpful for me to know, though: What did you expect the autodialer to do, given you explicitly defined both an end date and an end value, which implies a specific end rate?

I never set an explicit end date; somehow the goal ended up with one?! This goal started with a target and a set rate of something like 1/day or 10/week. I may have changed the slope manually sometimes, and then I enabled the autodialer. If the autodialer is not meant for goals like this that’s fine; I only enabled it because you were looking for testers. I’d expected it would keep the user-set target as sacrosanct and only adjust to rate to get there sooner or later.

The goal is currently “broken” again, in that the target is now 723 instead of 720. Could you fix that up? Possibly my disabling of the autodialer on this goal didn’t work (I appended an x to each hashtag yesterday).

2 Likes

This option seems to be preventing any change at all? I have a Do More goal with an average of .56 and a minimum of .5, and no rate change is scheduled with the strict option on (but it works fine when I turn it off).

2 Likes

@ianminds Ah, ok, that makes sense. I definitely think I should try to support end val + end rate.

And thank you for testing! You’re definitely helping me find some bugs I otherwise wouldn’t have found for quite a while longer probably! :smiley:

2 Likes

@narthur I’ve opened a pull request that should solve this problem - strict mode is currently setting the current rate as both a strict minimum and maximum, so I’ve changed it to take the yaw into account.

3 Likes

@ncyrocks Thank you!! Deployed!

2 Likes

@narthur Looks like it failed to deploy due to my edits making the lines >80 chars… my bad! Made a pull request for another fix.

1 Like