Final Version Perfected: An Underused Execution Algorithm

post by willbradshaw · 2020-11-27T10:43:02.796Z · LW · GW · 26 comments

Contents

  TLDR
  Introduction
  The FVP Algorithm
  A long-ish example
  FVP: Why and why not
None
26 comments

TLDR

Introduction

Execution is the Last Mile Problem of productivity infrastructure. You can put as much effort as you like into organising your goals, organising your To-Do lists, organising your calendar, but sooner or later you will be presented with more than one thing you could reasonably be doing with your time. When that happens, you will need some sort of method for choosing what that thing will be, and actually getting started.

Most people, I think, face this problem by either just doing the thing that is top-of-mind or looking through their To-Do list and picking something out. This works fine when the next thing to do is obvious, and you have no problems getting started on it. But when you have many potential things to do and aren’t sure which is best, or when you kind of know what the best next thing is but are avoiding it for one reason or another, you need a better system.

That system needs to be quick to execute, easy to remember, and effective at actually having you do the best next task. It needs to be robust to your psychological weaknesses, minimising procrastination, indecision, and ugh fields. It needs to be efficient, requiring as little work as possible to identify the most valuable task.

Enter Final Version Perfected.

The FVP Algorithm

The algorithm for executing tasks under FVP is pretty simple. You can find a description of it by the designer here, but here’s my version:

  1. Put all the tasks you have to choose from into one big unsorted list.
  2. Mark the first item on the list. Don’t do it yet.
  3. For each subsequent item on the list, ask yourself, "Do I want to do this task more than the last task I marked?" If yes, mark it. If no, don't mark it. Move on to the next item.
  4. When you reach the end of the list, trace back up to find the bottom-most marked task. Do it, then cross it off the list.
  5. Beginning with the next unmarked task after the task you just crossed off, repeat step 3, comparing each task to the bottom-most uncrossed marked task (i.e. the one prior to the one you just crossed out).
  6. Go to step 4. Repeat until you run out of time or list items.

In FVP, then, you perform a series of pairwise comparisons between tasks, in each case asking whether the new task is something you want to do more than the old task. The “want to do more than” comparison is deliberately vague: Depending on context, it might be the thing that would best move your project forward, the thing that would have the worst consequences if you didn’t do it, or the thing you would most enjoy doing. The key thing is that at each stage, you’re only comparing each task to the most recent task you marked, ignoring all previous tasks.

I'll talk more in a moment about why I think this algorithm is a good one, but first, let’s work through an example. (If you're sure you already understand the algorithm, click here [LW · GW] to go straight to the pros and cons.)

A long-ish example

Let's say this is my to-do list for today:

I start by marking the first item:

Then I compare it to the next item on the list. Which do I want to do more, finish the term paper or buy milk? Well, the term paper is due today, and I don't need milk until tomorrow, so I decide to do the term paper first.

Moving on to item 3. I already decided I want to finish the term paper before buying milk, so I can ignore the milk for now. Do I want to play video games or finish my term paper? Well, in some sense I want to play video games more, but my all-things-considered endorsement is to finish the term paper first, so I leave item 3 unmarked.

Next, item 4: do I want to finish the term paper or work out? Well, in some sense I'd rather not do either, and in another sense the term paper is more urgent, but working out is important, I've heard it has cognitive benefits, and I know from experience that if I don't do it first thing I won't do it, so it takes precedence:

Item 5: oh yeah, I forgot, I need to save the world today. Damn. Well, I can't work out if there's no world to work out in, so I guess I’ll do that first.

Ditto for walking the dog: much though I love him, I won't have anywhere to walk him if I don't save the world first, so that takes precedence again.

I've finished the list now, so it's time to do the last item on the list. Looks like that's saving the world. Luckily, it doesn't take long:

Now that I've done the highest priority task on the list, I go back to FVP to determine the next one. There's actually only one comparison I need to make: work out or walk the dog? Walking the dog can wait until the evening, so it’s time to head to the gym.

Again, there's only one more comparison I need to do to determine my next top task: do I want to finish my term paper, or walk the dog? And again, walking the dog isn't that urgent, so I spend a few hours on the term paper.

Now I'm all the way back to the top of the list! But now there are two more comparisons to make to decide on the next task. First, do I want to buy milk, or play video games? I've worked pretty hard so far today, and buying milk isn't that important, so let's play games first:

Finally, do I want to walk the dog or play video games? The dog has been waiting for hours for a walk now, and I could do with some fresh air, and I'd feel guilty just gaming without taking him out, so let's do that first:

There's no unmarked tasks in the list now, so to finish I just work up the list in order: first walking the dog, then playing games, then, finally, buying milk.

FVP: Why and why not

The usefulness of FVP depends on a few key assumptions.

When these conditions are met, FVP is a very effective method for guiding action. It is both efficient and exhaustive: guaranteed to identify the top-priority task while avoiding most of the work involved in producing a complete ranking. It is a simple algorithm, easy to remember and quick to perform. After doing it for a while, I find it scarcely requires conscious thought – but still reliably identifies the most valuable task for me to work on.

The biggest benefit I get from FVP, though, is how much easier it makes it to do important things I'd rather avoid. There is something about a bald, pairwise comparison between two tasks that is highly effective at overcoming my aversion to difficult things. If an important but unpleasant task is nestled within a long to-do list of minor-but-rewarding busywork, it is easy for my eye to skip over the difficult task, defer it till tomorrow, and work on something more pleasant instead. It's much harder to do that when comparing the important task to each minor task in isolation.

FVP is also good at minimising time lost due to indecision. When presented with a menu of tasks to choose from, it can be quite hard to select a single task to work on first. When that choice process is reduced to a series of simple pairwise comparisons, the choosing process as a whole becomes much easier. And, once I've finished with FVP and selected a single winning task, there's an impetus towards starting that makes me much less prone to procrastination.

One last brief note on infrastructure: due to its relative obscurity, I haven’t found great online tools for FVP. Complice’s starred-task system can be passably adapted to the algorithm, but in general I’ve found physical paper lists to work best. When I was at work I would print off my Todoist task lists and use those; now I’m working from home I mostly write them out by hand. This is kind of time-consuming and redundant, so if you dislike paper notes and don’t have access to a printer it might be a significant mark against FVP.

I’d really love it if someone created a great online tool for FVP or integrated it more formally into an existing productivity application, but I don’t expect that to happen any time soon. In the meantime, if you have ideas for existing ways to execute FVP online, I’d love to hear about them!

26 comments

Comments sorted by top scores.

comment by kithpendragon · 2020-11-27T11:28:42.982Z · LW(p) · GW(p)

This is basically the algorithm I use when trying to get my 4yo to make a choice. I can tell you it works even with just 2 options! I choose a default (usually based on what I want), and then go through the other option(s) one at a time asking, "do you like this one better than the current default". If yes, that becomes the new default. I weed out the bad choices myself (based mostly on time and safety) and simply don't present them at all. At the end of the list, even if the kid is acting like a brat and refusing to participate at all, I still have a default option to execute on.

I've always figured it works because of that initial choice of default option. It's easier to compare how much we want to do one thing vs. another than it is to pick from a large list, and even more so if we clearly define and commit to an option that will trigger if we don't choose otherwise. Using (variously arbitrary) defaults makes it very obvious that refusing to choose is choosing to let somebody else make the decision for you (even if "somebody else" is just the random order of the list). I've also noticed this method also doesn't induce decision fatigue as fast as other methods.

comment by willbradshaw · 2020-11-27T18:18:30.265Z · LW(p) · GW(p)

Nice, this sounds like a good system.

comment by Matt Goldenberg (mr-hire) · 2020-11-27T15:46:52.543Z · LW(p) · GW(p)

So it seems like there's a bunch of great things about this technique, including avoiding overwhelm and thinking abougt prioritization. At least partially it seems like part of the benefit of the system forces you to look at and confront things that you've been trying to avoid.

In my own life and also in my work as a procrastination coach, I've found these sorts of methods that through brute force cause you to have to look at things you're avoiding often have a shelf-life. Eventually, it seems like people's avoidance mechanisms reassert themselves through meta-avoidance like avoiding using the technique, or avoiding adding certain items to your list.

I'm curious how long you've been using this algorithm, and if you've encountered any of this meta-avoidance.

comment by willbradshaw · 2020-11-27T18:16:54.774Z · LW(p) · GW(p)

At least partially it seems like part of the benefit of the system forces you to look at and confront things that you've been trying to avoid.

Definitely agree with this.

In my own life and also in my work as a procrastination coach, I've found these sorts of methods that through brute force cause you to have to look at things you're avoiding often have a shelf-life. Eventually, it seems like people's avoidance mechanisms reassert themselves through meta-avoidance like avoiding using the technique, or avoiding adding certain items to your list.

I'm curious how long you've been using this algorithm, and if you've encountered any of this meta-avoidance.

My usage of FVP has fluctuated a fair amount over time; I used it a lot in the last year of my PhD, then not much in the year after that, then have since started using it regularly again. I think this is at least partly due to my life in the intervening time being very unstable, which disrupted a lot of my systems.

I don't think I've started avoiding adding items to the list. I do think my usage of FVP may have become gradually less effective at having me do difficult tasks. As using the technique becomes more routine, I become less agent-y while doing it, which leads to that aspect of the technique becoming less effective. In particular, if the same item is on the list day after day, it becomes increasingly easy to skip over it until the rest of the list is empty (which never happens).

I don't think this decay effect is all that strong so far: I think I'm still substantially better at doing important-but-aversive tasks with FVP than I'd be without it. But I wouldn't be too surprised if the decay was stronger than I thought, or gets substantially stronger in the future. I do think I could probably "refresh" this aspect of the technique's effectiveness if I put some effort into it, e.g. by forcing myself to use an explicit verbal question to choose between tasks, or mixing up the phrasing of that question.

comment by Brendan Heisler (brendan-heisler) · 2020-11-28T17:46:54.034Z · LW(p) · GW(p)

Sometimes I have to let a to-do item sit for a while before I can be more real with myself about why it's important. FVP still seems like the best way of tackling such things because the structure lends itself to creating mental leverage in easy, but noticeable, ways.

Maybe a small change like writing a number next to each item list representing the number of days it's been on the list would help draw your focus to items that have been lingering a long time. Just start by writing 0 next to a new list item, and adding 1 to the number next to any list item that gets substantially repeated from the previous day. You don't necessarily have to feel bad about list items that have large numbers next to them, but a larger number can create extra weight for prioritizing it.

Another reason this might work is that, much like Space Repetition Systems (SRS) used in reviewing e.g. information on flashcards, there is some logic to dropping cards that you have difficulty incorporating into memory after a certain number of times failing to incorporate it. The logic is that that particular piece of information is either not as relevant to the rest of the set (hard to form associations with "nearby" information), not as relevant to your own interests, or simply too difficult for you at that moment in time. Programs for doing SRS flashcard reviews include code to stop showing those cards again, and you have to manually specify to put them back into the review stack. Basically, it's a sideloop to identify things that actually do require more conscious processing without clogging the rest of the process, which seems to be the main point of FVP.

Combining the two prior points, if you track the number of days on the list, you could have a hard cutoff, like 14, where you take that item off the list altogether. Not sure how to reincorporate it in a streamlined way, though. Having a separate list and maintaining two of them seems onerous.

comment by __nobody · 2020-11-30T02:49:08.456Z · LW(p) · GW(p)

Apropos SRS and needing a second list: I'm currently experimenting with using Anki as a to-do tool. (Every task becomes a card, I "learn" the deck, and for each task get the choice of Again/Hard/Good/Easy with listed intervals, e.g. <15min, 1d, 6d, 27d. If I want to see the task again quickly (Again/Hard), I have to spend at least 5 minutes on it before clicking the button. Otherwise, it's ok to bury it by clicking 'Easy' on it.)

This deals nicely with "nice-to-haves" that I don't want to kill yet. Whenever they come up, I just send them away to next month/quarter/year/... - that way, I don't ever have to make the hard decision to kill the idea, I could always change my mind about this later, because I know that I will be reminded eventually. These "non-tasks" are also eating a fraction of the mental capacity that they'd otherwise require, because (a) I don't get a growing list of "things that would be nice to do eventually" that I'd have to manually comb through (instead every couple of days there will be 1 or 2 of them mixed in with the review), and (b) I know that they'll pop back up eventually, so I don't have to worry about keeping track of them or finding them again if I ever change my mind. (To a lesser degree, it also forces me to start early on tasks due in several months, to keep the interval growth in check.)

The only problem I had so far was tasks that are inactionable right now (e.g. taking out the trash at 5am, because noisy) needed to be 'skipped' and reviewed later, leading to "ugh not in the mood right now" skips of actually actionable tasks, leading to less stuff getting done.

FVP looks like it might fix this. So for the month of December I'll be running the following modified algorithm:

  1. Go through the list of tasks in Anki, for each either do it right away or put it on the (paper) list, or delegate it to future-me (i.e. pick the long interval Good/Easy option).
  2. Do FVP on the paper list.
  3. 3-strikes rule for "list leftovers": If I say I do it but don't get around to it, the counter increases. Once it hits three, I must "delegate to future me". (Counter resets whenever I explicitly declare not to work on it, not sure yet if it should also reduce for streaks... For the experiment, I'll go with yes and 3-days streaks for removing one mark.)

Let's see how long I'll stick to this.

comment by willbradshaw · 2020-11-28T18:18:38.626Z · LW(p) · GW(p)

This sounds like it could work. I might well try this. Thanks!

comment by Alex Ray (alex-ray) · 2020-11-29T21:06:29.102Z · LW(p) · GW(p)

This is my favorite kind of lesswrong post -- a quick rationality technique that I can immediately go try and report back on.

I was able to prototype it quickly in my notes list by using a dedicated symbol as the marker.  It looks like any weird/unused symbol could be used as this.  Seems like a quick hack to work with any digital list (I used §).

Question about non-stationarity: How often is the "stable" prerequisite violated in practice?

E.g. if a bunch of items are physically exhausting, and a bunch are not, I might want to not do physically exhausting items in sequence.  I didn't run into this personally in my tiny trial, so at least the answer isn't "all the time".

comment by willbradshaw · 2020-11-30T08:17:55.211Z · LW(p) · GW(p)

Can you clarify your question? I started writing a response, but then realised I wasn't sure if I was interpreting it correctly.

comment by philh · 2020-12-01T12:10:44.256Z · LW(p) · GW(p)

I interpreted it as... suppose the items are, in order: play video games, rearrange furniture, work out. That's the reverse of the order I want to do them in right now, so I mark them all and go work out. Then after working out, I'm supposed to rearrange furniture. But if I started from scratch here, I'd want to play games first, to rest. How often does that sort of thing happen?

comment by Alex Ray (alex-ray) · 2020-12-02T18:12:14.083Z · LW(p) · GW(p)

Sure!

It seems like the prerequisite assumptions are likely to be violated sometimes (in general most assumptions aren't total rules).

My question is about the rate of violations to this prerequisite assumption.

A few ways to cut at it (feel free to answer just one or none of them):

  • When going through a list subsequent times, how often do you notice/feel internally that your views on a past item have shifted?
  • How often do you make a new list and start the process anew, even though you have an existing list that could be continued on?
  • How often do you go back and erase or modify marks on a list while using this process?

I think I find my internal experience (and relation to stuff on my to-do list) changes pretty significantly over the course of a day.

comment by adamShimi · 2020-11-28T22:42:32.018Z · LW(p) · GW(p)

Thanks for presenting this algorithm! I had not heard about it, and might try it at some point.

One thing I'm curious about is its interpretation as a sorting algorithm. Because basically what you are doing is sorting your list using pairwise comparisons. It cannot be better than the classical sorting algorithms, because comparison based sorting takes at least . But maybe the benefits is that it's more intuitive to do for a human being than quicksort or mergesort? Or that it require a weaker sense of transitivity than those? Also, I wonder if this isn't a known sorting algorithm.

comment by philh · 2020-12-01T13:48:13.913Z · LW(p) · GW(p)

My take is that quicksort, merge sort and all other common sorts involve physically rearranging memory in a way that would be a bad fit for a list on paper. This one doesn't change the original list, it just emits its elements one at a time in order.

This is worst-case - if they're currently in order (i.e. sorted from highest to lowest priority), you'd do comparisons. Best case comparisons, if they're currently in reverse order. (You could interpret it as high priority elements being high in the sort order, but then the algorithm emits elements one at a time in reverse order.) Memory use is pointers/indexes (the list of marked elements), bools (a list of which items have already been crossed off) and bookkeeping.

You could see it as a variant on selection sort - in particular it has the same property of "find the least element, then the next least, and so on" that lets you stop part way through if you only want to do three tasks. But because of the "emit items instead of changing the original list" behaviour, instead of just keeping track of the current minimum, we can keep track of a descending subsequence of the original list.

In pseudocode, I think we get something like...

let input: [Task] be the input list (n elements)
initialize:
  emitted: [Bool] = [False, False, ..., False] (n elements)
  descending-stack: [Int] = [-1]
  current-min: (Infinity | Task) = Infinity
  last-pop: Int = -1

repeat:
    for i from last-pop + 1 to n-1:
        if not emitted[i] and input[i] < current-min:
            push(descending-stack, i)
            current-min = input[i]

    last-pop = pop(descending-stack)
    if last-pop == -1:
        finished()

    emit(input[i])
    emitted[i] = True
comment by adamShimi · 2020-12-01T13:56:11.888Z · LW(p) · GW(p)

Thanks a lot for the thoughtful reply! Not having to move the items around could indeed help to lower the cognitive burden.

comment by billzito · 2020-11-29T02:25:51.957Z · LW(p) · GW(p)

For "what task should I do next," it's O(n), because you just go down the list once doing a pairwise comparison. "What task should I do next" seems more important for actually doing things than sorting the entire list at first to avoid deliberation time / indecision / harder 3-way value comparisons.

comment by willbradshaw · 2020-11-29T15:04:54.980Z · LW(p) · GW(p)

Right, for a single pass it's a find-the-maximum-element algorithm in O(n).

I think if you eventually do every task on the list it's equivalent to sorting the list? But this basically never happens to me. 

Presumably intermediate states (doing e.g. half the items) is of intermediate efficiency? But my grasp of the underlying theory here is pretty weak.

comment by Pongo · 2020-11-28T23:20:50.030Z · LW(p) · GW(p)

Seems like it's a lazy sort to me (with obvious wrinkles from the fact that the list can grow). It also seems to be a variant of drop sort (which is  via cheating) designed for repeated passes on the remaining list

comment by steve2152 · 2020-11-27T11:01:59.965Z · LW(p) · GW(p)

This seems useful and sensible, thanks!

asking whether the new task is something you want to do more than the old task

Why not just say "whether the new task is a better thing to do than the old task"? Like, there's the rule to start your day with whatever has the biggest "ugh field", i.e. whatever is most painful. I get that you're using "want to do more than" broadly, but still, it carries the wrong connotation for me. :-)

comment by willbradshaw · 2020-11-27T18:14:48.227Z · LW(p) · GW(p)

Mark Forster (who originated the technique) puts a lot of emphasis on the exact phrasing of the question you use to decide between tasks. I'm sceptical that it's all that important; I think it's fine to experiment with different phrasings and see what works for you. There might even be benefits to switching up the exact phrasing from time to time, e.g. to keep you focused and agent-y while doing it.

After using the technique extensively, it's become more of a nonverbal feeling for me than an explicit question. It's nontrivial for me to exactly describe the feeling: some combination of desire, obligation, and endorsed choice-worthiness. The nonverbal version is both faster and mentally easier, but it's plausible to me that explicitly switching back to a verbal question from time to time is worth it.

comment by Matt Goldenberg (mr-hire) · 2020-11-27T15:41:53.074Z · LW(p) · GW(p)

I suspect that there's something important about being able to actually make the reverse decision.  If you actually WANT to not do the "better" task because you're not in a good state for it, it's important to be able to make taht decision.

comment by MikkW (mikkel-wilson) · 2020-11-27T22:43:38.465Z · LW(p) · GW(p)

Thanks for posting this, it seems like a system that will help me stay on top of things that need doing, at least on some days. I've applied this today to my todos, and it has already helped me do some useful things today, in a way that felt less overbearing than other approaches to todos I've used in the past.

As someone who both has spent a nontrivial amount of time thinking about todo lists, and has experience with programming, I'm somewhat surprised that I've never done this exact approach before, since the procedure here is very similar to the code I would write when I need to find the element of a list that maximizes some property, which is a very common task.

(By the way, are you still working on your aging sequence? I enjoyed the first two posts you wrote there, but it's been half a year since I've seen anything in that sequence)

comment by Zian · 2020-12-07T05:43:06.909Z · LW(p) · GW(p)

How would you say this approach relates to https://www.lesswrong.com/posts/dJQ7BFz9ZPqstP3an/urgent-and-important-how-not-to-do-your-to-do-list? [LW · GW]

You wrote that it's important for your preferences to be fairly stable. I've been using a prioritizing grid (e.g. https://www.beverlyryle.com/prioritizing-grid) to go through my entire do list in 1 fell swoop. I wonder if that's more or less efficient than your approach.

comment by Yoav Ravid · 2020-12-05T12:11:18.707Z · LW(p) · GW(p)

Had some fun making a simple python implementation (text-based, no fancy GUI). I uploaded it to GitHub here

comment by Geoffrey Wood (geoffrey-wood) · 2020-11-30T01:13:56.247Z · LW(p) · GW(p)

While I absolutely agree that an unsorted to-do list is a minefield, I intuitively feel that FVP is a more-wrong approach to To-Do lists. I also feel that it might work for very small, short term lists but would struggle to scale.

Tasks are extremely varied things and so not always easily comparable, for example when comparing the task "Buy milk" and "Finish term Paper", the term paper is probably more important in the longer term, but in the short term you wont have any milk for your breakfast. Unless extremely time crunched, breakfast comes first.

*Edit - After some reflection I think the main disadvantage of FVP is when you have to put in the decision making effort. You have to make a decision just before you do the task. Better to rank an issue as you write them on the list, that way you can separate the effort of doing the task from the effort of writing it on your to do list, see below for my favoured solution.

I use and love this, Urgent & important: How (not) to do your to-do list - LessWrong [LW · GW].  

My algorithm is:

  • Write task description
  • Decide if I “Must”, “Should or “Could” do it
  • Decide if I should do it “Today” or “Later”
  • Assign how long it might take me (optional)
  • Use my spreadsheet to sort by rank (right click A column and sort A-Z)
  • Do tasks from top to bottom
  • When a Task is complete, replace “Must”, “Should or “Could” with "Done"

Here is my spreadsheet, I hope it serves you well.

To do list

I would love to receive feedback.

comment by D0TheMath · 2020-11-30T00:23:45.747Z · LW(p) · GW(p)

This algorithm seems like it can be generalized for any human decision algorithm. For instance, I'm usually pretty indecisive while trying to order food, but I'd bet that implementing this algorithm would speed up my decision making immensely, while guaranteeing I'd be selecting the best option available.

comment by willbradshaw · 2020-11-30T20:08:22.573Z · LW(p) · GW(p)

I haven't used it for that, but it sounds like a good application; and in this case, you only need to select one thing, so you can do it memorylessly (just keep your finger on the active dish).