3 ms·
So you would model the equations on the fly for a certain optimization problem? If so, can you expand on the problems you were solving? I'm trying to solve a s
by lambda_obrien 6y ago
So you would model the equations on the fly for a certain optimization problem? If so, can you expand on the problems you were solving?
I'm trying to solve a similar sounding problem where I have to build the model equations from scratch quite often and right now it's using templates to recompile my binary with new equations whenever I need to do so, but that takes time and I have to manage a lot of code complexity. I'm doing it for performance reasons right now because other methods I tried we too slow, but it's getting unwieldily.
- jbay808 6y agoSympy is great for this, because you can manipulate the equations symbolically, cancel terms, and then convert the result to a numerical routine using lambdify. In my case, I'd build up a model of a motor control system using subsystems (motor model, inverter, current sensors, delay elements, noise sources, etc). Then design a feedback/feedforward control system (eg. PID) and connect that in as another block. Each block has simulation code associated with it, and a matching symbolic sympy transfer function from each input to each output was derived. When you connect them together with various feedback loops, it creates a directed graph that it then resolves using NetworkX to find the various loops, and using Mason's rule to solve the system transfer functions. For discrete time systems cycles were automatically resolved by inserting additional delay elements. Each system composed internally of such parts could also be used as a single part in a larger feedback system, so for example, you can build up a current control loop around your motor and inverter, and then plug that as a subsystem into a velocity control loop. You only have to write out the symbolic model of the base level components (inductors, resistors, etc). The equation for each transfer function along each signal path gets built up by Sympy, using the normal rules; for example a feedback loop with gain A becomes 1/(1+A). For a big system the equation gets quite complicated to write out in full. Once you've assembled your system that way, you'll have a lot of parameters to tune. You can run the the resulting system in simulation and play with it but for tuning many variables at once, you'll want a more robust solution. So from control theory we can derive certain objectives that we want to maximize, and constraints that we want to satisfy. The constraints might include a maximum value on the transfer function from a noise input to the motor current, or something like that, and of course Nyquist stability. The objective might include minimizing sensitivity to disturbances within a frequency band or minimizing time to converge to a target. In such cases, you could perhaps simulate the system and derive those numerically, but it would be slow to do that. Much faster to solve them symbolically -- the expression for a sensitivity is easy when you know the transfer functions; you'll just have to take some limits as certain terms go to zero or infinity and take derivatives of those and so on. Then you get a function of your tuning parameters to optimize under constraints. That can then get passed to an optimizer routine, to solve for your tuning parameters. Then you simulate the system to check that the performance is good.
- lambda_obrien 6y agoExcellent! I think that's exactly what I was looking for! Thank you so much for going into detail on that, it helped immensely. I have a similar problem (though can't talk too many details) with discrete "ticks" and with a constrained CPU (a peak constraint, I have plenty of aggregate CPU power over time). I think I could fit some simple version of the symbolic module optimizer algorithm like you describe into the unused CPU time to optimize the spiky algorithm before I receive events (the events are spread apart pretty good) to return more accurate and timelier results when they do come. I am using a Haskell-like language for this that compiles to a binary format with a similar graph reduction scheme for the compiler as you describe for the symbolic reducer, so it should be very simple for me to compose the modules as you describe. The problem I have now is that when I need to calculate something that's very-high-priority (some events have hard deadlines), I would like to have a more optimized algorithm, but I don't have time to optimize it on the fly from the information I know (my knowledge is continuous, only the events are discrete), so I have to use less-accurate results or sometimes I don't have an answer so I just return a "no answer" response and the process fails. I tried using some crappy default values, but it would still fail most of the time. I think about my problem like a process which has a target and my answer is the "direction to aim at" for the process and so if I return a bad result to this process it'll just miss the target, so I just say "sorry, can't aim right now, wait 1 more tick" and I then am able to start a calculation for the next round before the process even asks for it and it finishes easily this time, since my events have a low frequency. Using an optimal algorithm (which I can get from a symbolic reduction: that's how I did it--by hand--in the first place to get my current algos) will always return the answer in time, based on my models and experiments.