In Gekko 2.0/2.2/2.4, and also in some other software packages, series expressions are run in an outer loop. Consider a series expression like y = x1 + x2 + x3. In AREMOS, such an expression is run n times in an outer loop, where n is the number of periods. Imagine that the series values over the period 2010-12 are given as the vectors x1 = (1, 2, 4), x2 = (3, 5, 7), and x3 = (6, 8, 9). Then in AREMOS and Gekko 2.x, the following is run:
y = x1 + x2 + x3 = 1 + 3 + 6 = 10 y = x1 + x2 + x3 = 2 + 5 + 8 = 15 y = x1 + x2 + x3 = 4 + 7 + 9 = 20
In contrast, Gekko 3.0 treats an expression like y = x1 + x2 + x3 more vector-like:
y = (1, 2, 4) + (3, 5, 7) + (6, 8, 9) = (1, 2, 4) + (9, 13, 16) = (10, 15, 20)
So Gekko 3.0 first adds x2 and x3 together, creating an temporary vector with values (9, 13, 16). When this temporary vector is added to x1, the final result (10, 15, 20) is obtained. If an expression like x1 + x2 + x3 is fed to a function that later on uses a lag on that expression, we have to be sure in advance that the temporary series x1 + x2 + x3 is calculated over a sufficiently long time period. This is the lag problem.
Another problem is the dynamic problem. Imagine an expression like x = x[-1] + 1. In AREMOS and Gekko 2.x, such an expression is performed in the following way over the period 2010-12:
x = x + 1 x = x + 1 x = x + 1
Imagine that x over the period 2009-12 is (3, 5, 8, 11). Since the equation accumulates, only the 2009 value (x = 3) is relevant, and the result is (4, 5, 6) over 2010-12, growing by 1 for each period.
But in Gekko 3.0, an expression like x = x[-1] + 1 is run differently. Over the period 2010-12, we have x = (5, 8, 11) and x[-1] = (3, 5, 8). It is seen that the lag simply shifts the values one position to the right in the vector. The expression is thus evaluated as follows:
x = x[-1] + 1 = (3, 5, 8) + (1, 1, 1) = (4, 6, 9)
The first values is actually the same as in AREMOS and Gekko 2.x, but the following values are different. Because the values are not calculated period for period, the expression does not accumulate dynamically, augmenting the value by 1 each period. This problem is alleviated in Gekko 3.0 with an optional <dyn> option. So in Gekko 3.0, you can use x <dyn> = x[-1] + 1, and in that case, the statement is run period for period in an outer loop. This option can also be set via a “BLOCK series dyn = yes; … ; END;”.
It would perhaps be tempting to set <dyn> mode on all assignments, completely emulating the way AREMOS and Gekko 2.x works. But using such an outer loop is a tremendous waste of effort, since Gekko can add two vectors/arrays like (3, 5, 7) + (6, 8, 9) into a new vector (9, 13, 16) very efficiently compared to an outer loop. Another complication is that a naive implementation of an outer loop should not encompass for example a scalar or matrix expression like %x = %x + 1 or #x[1, 1] = #x[1, 1] + 1, running this expression n times (that would be a grave error: a scalar or matrix expression should of course only be run 1 time).
The dynamic problem only arises when the left-hand side variable is a timeseries that is also present on the right-hand side (and is lagged there). For an assignment like x = x[-1] + 1, this is self-evident, and in order to implement dynamic behavior on all assignments, the following was tried. When variables were accessed on the right-hand side, these variables were rememeberd, if they were of series type. Next, if the left-hand side variable was identical to one of the right-hand variables from the remembered list, the assignment was aborted and done dynamically instead. This seemed reasonalby watertight, but still quite cumbersome, complicating the internal source code quite a lot. When this was almost implemented, the following problem arose: how about an expression like x = x[-1] + #m, where #m is a list of values? This would readily be recognized as an assignment that needed to be run dynamically. But then, for each single period executed in an outer loop, Gekko would need to somehow pick the right element of #m (the first one in the first period, the second one in the second period, etc.). This would add another layer of complexity, and would be brittle and error-prone, too.
So, in the end, it was decided that the users have to indicate “manually” if certain assignment expressions are to be run dynamically, period by period. Either via the <dyn> option, or with a “BLOCK series dyn = yes; … ; END;”. Using a block makes sure that the dynamic behavior is switched off again, not accidently infecting parts of the code where this behavior is not needed or intended.
All in all, Gekko has quite a lot of operators regarding dynamic assignments, for instance x ^= 1 or x %= 1, either adding 1 (absolute) or 1% (relative) each period, but sometimes the dynamics may be more complicated than that, especially if model equations are used in command files. In theses cases, the <dyn> option or the above-mentioned BLOCK can be used, and the prevalence of such cases is probably not high enough to warrant general AREMOS-like behavior, always calculating series assignments period for period.