How does this C ++ function use memoization?

#include <vector> std::vector<long int> as; long int a(size_t n){ if(n==1) return 1; if(n==2) return -2; if(as.size()<n+1) as.resize(n+1); if(as[n]<=0) { as[n]=-4*a(n-1)-4*a(n-2); } return mod(as[n], 65535); } 

The above code example using memoization to compute a recursive formula based on some input n . I know this uses memoization because I wrote a purely recursive function that uses the same formula, but this one is much, much faster for much larger n values. I had never used vectors before, but I did some research and I understand their concept. I understand that memoization must store each calculated value, so that instead of repeating the same calculations, it can simply get the ones that have already been calculated.

My question is: how is this memory, and how does it work? I do not see the code in the code in which it checks if a value exists for n. Also, I don't understand the purpose of if(as[n]<=0) . This formula can give positive and negative values, so I'm not sure what this check is looking for.


Thank you, I think I'm close to understanding how this works, in fact it is a little easier than I thought.

I don't think the values ​​in the sequence can be 0, so this should work for me, since I think n should start with 1.

However, if zero were a viable number in my sequence, in what other way could I solve it? For example, what if five never appear? Do I just need to fill my vector with five?

Edit: Wow, I get many other answers by checking the code and typing it. Thanks for helping everyone, I think I understand now.

+4
source share
5 answers

if (as[n] <= 0) is a check. If the permissible values ​​can be negative, as you say, then you need another watchdog. Can real values ​​be null? If not, then just do the if (as[n] == 0) test. This makes writing code easier, because by default int vectors are filled with zeros.

+6
source

The code seems to be incorrectly checked (like [n] <= 0) and recounts the negative values ​​of the function (which seem to be just about every other value). This makes the linear scale of working with n instead of 2 ^ n with a recursive solution, so it works much faster.

However, the best test would be to check if (like [n] == 0), which seems to work 3 times faster on my system. Even if the function can return 0, a value of 0 simply means that it will take a little more to calculate (although if 0 is a frequent return value, you can consider a separate vector that indicates whether the calculated value was or not instead of using a single vector to store the value functions and whether it was calculated)

+1
source

If the formula can give both positive and negative values, this function has a serious error. The if(as[n]<=0) check should be a check if it has already cached this calculation value. But if the formula can be negative, this function recalculates this cached value ...

That it was really possible was vector<pair<bool, unsigned> > , where bool says if the value was calculated or not.

0
source

The code, as indicated, only remembers about 40% of the time (exactly when the stored value is positive). As Chris Jet-Young noted, the correct implementation will check if(as[n]==0) instead. In addition, you can change the memoization code itself to read as[n]=mod(-4*a(n-1)-4*a(n-2),65535);

(Even checking ==0 will waste power when the memoized value is 0. Fortunately, this will never happen in your case!)

0
source

There is an error in this code. He will continue to recount the values ​​as [n] for as [n] <= 0. He will memorize the values ​​of a, which turn out to be positive. It works much faster than code without memoization, because there are enough positive values ​​like [] to make the recursion quickly complete. You can improve this by using a value greater than 65535 as a father. New vector values ​​are initialized to zero when the vector expands.

0
source

Source: https://habr.com/ru/post/1277280/


All Articles