Saturday, October 8, 2022

Dynamic Systems

A picture is worth a thousand words, as they like to say. But it is also frozen in time. It doesn’t change, or at least it shouldn’t. 


And it’s a great analogy to describe things being ‘static’. Basically, a photograph is a directed static capture of just one specific moment of our dynamic reality. For a lot of pictures, pretty much right afterward at least one little thing has changed, the picture is no longer reproducible. Reality has moved on, it will never be the same again.

Now it’s worth noting that a video is a long sequence of pictures played together so that we can see a larger set of changes. While it is still static externally, it isn’t a moment anymore, it is now a period of time.  So, when you view it, it appears to be dynamic, but you can keep replaying it over and over again, so it isn't really.

Things that are dynamic can constantly change. They can change across all possible dimensions. Obviously, if we were going to try to model that, it would be impossible. 

But we can make some of the dimensions dynamic, while leaving others to be static, such as what happens with a video. Then things are not ‘entirely’ dynamic, but there are still dynamic aspects that are captured, at least for some period of time.

All of that is fairly easy to understand, but it gets a little less so when applied to mapping aspects of reality onto software. Fundamentally, what we want to do is capture some information about the world around us with our computers. It’s just that it’s highly multi-dimensional, and many of those dimensions are intrinsically dynamic. 

We should stop and talk about the multi-dimensional aspect of digital information. We mostly perceive our world as four dimensions, so we could capture any point in time and space, and combine these together to get descriptions of any type of objects. We do have higher dimensional theories, but we tend to think of our world in terms of 4D.

In software though, we have a large number of ‘variables’; that is things that can and do vary. Each one only has a finite number of different possibilities and at any one time there are only ever a fixed number of them, but since we tend to use a crazy large number of variables, it is worth treating each and every one as though it was essentially its own dimension. We can boil that down to a subset of variables that are so ewhat independent of each other, but since that is still a fairly large number it doesn't really change our perspective. It is a huge number of dimensions.

A static program then is one where the number of dimensions and the spaces it occupies, cannot change. For example, you write a problem with exactly 3 integer variables and the result is thay are added together, then we know the entire input space (all triples permuted from integer min to max) and the output space (an integer from min to max) are both fixed. The entire possible behaviour is static. 

A dynamic program however can introduce new variables. 

The easiest way to do this is to keep a list of integers and not have a maximum list size. At some point the list will grow too large for the hardware, but we’ll ignore that for the moment. While each integer has a fixed space, the number of them is essentially ‘nearly’ infinite, which we will call very large. So, the overall space of the input if it were just a list to be added together is very large. If the output were another list, then it too would be very large. 

In that sense a single variable is one dimensional, but a list of them adds a new dimension. That’s not a surprise, but weirdly a matrix doesn’t add a second one, two lists or a spreadsheet do, and a dag seems to add more than one. That is, the expressive power of data structures is multi-dimensional, but rather than being fixed static dimensions like the variables, each dimension is a “very large” one. And it is that huge bump in expressive power that makes the whole system dynamic.

But that isn't the only way to make systems dynamic. Another way is to make the variables variable. That is, instead of only an integer, the value can be any valid primitive type in the language. But more fun is to let it also be any user constructed composite variables, e.g. structs or objects. It is fully polymorphic. Then the code doesn’t know or care about the type or structure of the data which means the code can be used for an essentially unlimited number of computations. So, rather than statically encode one block for each possible type of variable, you encode the block once for all types, primitive or composite or data structure. 

If that is the heart of the code, basically an engine, then you can apply that code to a huge set of problems, making the usage of the code itself dynamic.

So, we can make some of the data dimensions dynamic and we can make some of the code dynamic. And we can pass that attribute into any of the interfaces used to interact with the system. There can employ the same code and data techniques to make the interface dynamic.

Now that we can construct dynamic computations, we can map real world dynamic behaviours onto these, so that we model them correctly. As things swing around in the real world, we can capture that correctly in the model, and build systems around that. 

We can tell if something is mismatched in a system. 

If it was encoded statically, but it suffers from scope creep all of the time, that is a clear indication that there is at least one dynamic dimension missing. 

In fact, unless the coverage of the model never changes, either some dynamic attribute was missed or the interface is incomplete. But for that latter case, any "missing features” are easy to implement. However, if something was incorrectly made static however, the code and data changes are usually big, difficult, and/or expensive. 

So we can really test the suitability of any underlying model used in a software solution by examining the requested list of changes, classifying them as domain increases, incomplete interfaces, or invalid modelling. New domain territory needs to extend the code and data to a new part of the problem space, incomplete interfaces and invalid modelling were covered above.

There is also a sub-branch of mathematics called “dynamic programming” which is a bit confusing in that it predates computer programming, but its use of the term dynamic is similar to this discussion. You can encode some algebraic expressions that when applied will dynamically converge on an answer. I believe that you can encode both the code and the data for this statically, so we have yet another category, which is effectively a dynamic computation. It’s no doubt related to the mathematical concept of uncomputable, but that knowledge is too deep for this discussion, other than alluding to the notion that dynamic behaviour may be able to spring from seemingly static roots.

Some things in reality are static. They essentially will not change for the expected lifetime of the system (usually 30 years). Other things are intrinsically dynamic. They can’t be locked down. In order to build good systems that don’t have ugly side effects, we need to implement any dynamic behavior with dynamic data or code. Trying to cheat that with static implementations will generate unintentional and undesirable side-effects with both the construction and usage of the system.



No comments:

Post a Comment

Thanks for the Feedback!