0

I have a code that I use to compute the iterations needed to converge a number's Collatz sequence to one:

nums = input('Enter a number: ');

iter = zeros(1, nums, 'uint16');

collatz = zeros(1, nums, 'uint64');
seqn = zeros(nums, 'uint64');

parfor ii = 1:nums    

    num = ii;
    collatz(ii) = num;
    % seqn(ii) = num;

    while num ~= 1

        % writes the maximum number reached
        if collatz(ii) < num
            collatz(ii) = num; 
        end

        if rem(num, 2) == 0
            num = num / 2;
        else
            num = 3 * num + 1;
        end

        % counts iterations needed to reduce each number to one
        iter(ii) = iter(ii) + 1;

        % records the sequence
        seqn(:, iter(ii)) = num;

    end
end

Shortly, it computes the Collatz sequence for each number up to num, records the maximum number in the sequence, and records the number of iterations ot took to reduce the number to one.

With the seqn matrix, I'm trying to record the Collatz sequnece of each number I run the loop for.

The problem here is that MATLAB won't run this PARFOR loop because of the changes done to seqn. I don't understand the reason! It seems to me that what I do to iter is essentially the same thing I do to seqn, in the sense that it executes inside the nested WHILE loop and does not depend on previous iterations.

What can I do to fix this?

Gallifreyan
  • 232
  • 4
  • 11
  • 1
    [This answer by a MATLAB employee](http://stackoverflow.com/a/37696213/5211833) might help you, it looks like it's the same as what you want. General `parfor` tips can be found in [this answer of mine](http://stackoverflow.com/questions/32146555/saving-time-and-memory-using-parfor-in-matlab/32146700#32146700). (I'll delete the other comments now, as I think half of them either wrong or covered by the answer here, and to clean up a bit) – Adriaan Apr 03 '17 at 06:46

1 Answers1

1

I've changed your while loop into for loop and set the final value of iter outside. additionally I'm only setting one element of seqn instead of entire column like you did. now matlab lets you run that but I'm not sure it's what you wanted, so take a look:

nums = input('Enter a number: ');

iter = zeros(1, nums, 'uint16');
maxitr = 1e6;
collatz = zeros(1, nums, 'uint64');
seqn = zeros(nums, 'uint64');

parfor ii = 1:nums

    num = ii;
    collatz(ii) = num;
    % seqn(ii) = num;

    for itr = 1:maxitr
        if num == 1
            break
        end
        % writes the maximum number reached
        if collatz(ii) < num
            collatz(ii) = num;
        end

        if rem(num, 2) == 0
            num = num / 2;
        else
            num = 3 * num + 1;
        end

        % records the sequence
        seqn(ii, itr) = num;
    end
    iter(ii) = itr - 1;
end
user2999345
  • 4,195
  • 1
  • 13
  • 20
  • Great idea with the `for` loop instead of `while`! I rejected it initially because I didn't know how many iterations I'd need to do, but all evidence (numbers up to 10^8) shows that 10^6 would be more than enough. I'll check this when I have access to my machine and come back :) – Gallifreyan Apr 02 '17 at 15:08
  • ... aaaand my laptop almost crashed :D RAM usage went up to my maximum (8 Gb) - this doesn't hapen with my implementation. Can't see the reason though. – Gallifreyan Apr 02 '17 at 15:40
  • Oh, it's probably the preallocation - `uint32` and `uint64` eat too much RAM. – Gallifreyan Apr 02 '17 at 15:44