From: POWERS_W%FLC@VAXF.COLORADO.EDU (William T. Powers)
Newsgroups: bit.listserv.csg-l
Subject: Primer part III
Date: 15 Nov 92 17:46:26 GMT
Comments: Gated by NETNEWS@AUVM.AMERICAN.EDU
X-Envelope-to: CSG-L@vmd.cso.uiuc.edu
X-VMS-To: @CSG
MIME-version: 1.0
Content-transfer-encoding: 7BIT

Continuing with the draft version of the modeling primer:

              Experimenting with the control paradigm
                  A primer for computer modelers

                 PART III: The effects of delays.

It is often said among the ill-informed that control systems will not
work well in organisms because of reaction-time and other delays. In
this section we will set up a control system with delays in it, first in
the output function and then in the input function, to see what is
required for such a system to maintain tight and stable control.

                             Output delay

The program is an extension of the one in Part II:

/* primer3.c */

#include "stdio.h"
#include "conio.h"

void main()
 {
float sp = 0.0,  /* initialize signals and quantities */
      sr = 20.0,
      se = 0.0,
      qo = 0.0,
      qi = 0.0,
      qd = 0.0;
float kd = 1.0, /* set constants */
      ki = 1.0,
      ko = 100.0,
      kf = 1.0,
      ks = 70.0,
      dt = 0.1;
float qo3 = 0.0, /* initialize variables for output delay */
      qo2 = 0.0,
      qo1 = 0.0;
int i;
 clrscr();  /* alternative: for(i=0;i<25;++i) putch(0x0d); */
 for(i=1;i<=80;++i)
  {
   if(i > 40) qd = 9.0; else qd = 0.0;
   qi = kf*qo + kd*qd;
   sp = ki*qi;
   se = sr - sp;
   qo = qo1;
   qo1 = qo2;
   qo2 = qo3;
   qo3 = qo3 + (ko*se - qo3)*dt/ks;
    gotoxy(i,24 - sr/2.0 - 0.5); putch('r');
    gotoxy(i,24 - qd/2.0 - 0.5); putch('d');
    gotoxy(i,24 - qo/2.0 - 0.5); putch('o');
    gotoxy(i,24 - sp/2.0 - 0.5); putch('p');  }
 (void) getch();
}

The delay is put into the output function by the following lines:

   qo = qo1;
   qo1 = qo2;
   qo2 = qo3;
   qo3 = qo3 + (ko*se - qo3)*dt/ks;

The three dummy variables qo1 through qo3 provide a delay of 3
iterations. On the current iteration, the value of qo3 is computed just
as it was in Part II. But this value is passed, on the next iteration,
to qo2, then to qo1, and only on the third iteration to qo, the actual
output quantity. So the output is always based on the error signal that
existed three iterations, or 3*dt seconds, ago.

This is called a "transport lag." The variations in qo follow the
variations in qo3, but three iterations later. The effect is much like
shouting commands from one end-zone of a football field to a marching
band in the other end zone. The marchers follow all the commands in
properly-spaced sequence, but with a delay about about 0.3 seconds.

It may not be obvious, but in the program of Part II there was already a
transport lag of dt, one iteration. The effect of a disturbance of the
input quantity during one iteration did not make its way around the loop
to affect the input quantity until one iteration later. We saw that it
was possible, with a delay of 0.1 second, to adjust the system for tight
control despite this lag.

Now the situation is slightly different. Effects still propagate around
the loop in one iteration, but the transport lag inserts a delay of 3
iterations in the output function alone. In ALL the functions, including
the output function, there is a new value of input and output calculated
on every iteration; the output quantity and input quantity can change
during the transport lag period. Previously nothing at all could happen
during the lag of one iteration. Now, with a lag of three iterations,
the errior signal can change on every iteration even though the effect
on the output quantity is delayed by 3 iterations.

Compile and run the program. The appearance is much the same as in Part
II, but now a "reaction time" is visible. After the initial rise in
reference signal, the output quantity, represented as an 'o', does not
start to rise until the fourth iteration, and the perceptual signal
starts to rise one iteration later. The perceptual signal, a 'p',  then
rises smoothly until it matches the reference signal. When the
disturbance jumps to 9.0 units, the perceptual signal is affected
immediately. But the output signal, which opposes the disturbance,
begins to change on the fourth iteration after the start of the
disturbance. Then the perceptual signal begins to return toward the
reference signal (some apparent lags are simply due to the coarseness of
the resolution of the plot).

We have paid one penalty for this transport lag. The slowing factor,
which had an optimum value of 10.1 in Part II, now must have a value ofat least
 70 to avoid overshoots. This added slowing is required in order
to compensate for the transport lag and keep the control system stable.
If you reduce ks to speed up the transitions, the perceptual signal will
begin to overshoot and undershoot. Try reducing the slowing factor ks in
steps of 10. The instability will get worse and worse until a runaway
oscillation starts and control is totally lost.

                           Input delay

Now we restore the output lag to zero (or one iteration) and use the
same mechanism to put a lag into the input function.

/* primer4.c */

#include "stdio.h"
#include "conio.h"

void main()
 {
float sp = 0.0,  /* initialize signals and quantities */
      sr = 20.0,
      se = 0.0,
      qo = 0.0,
      qi = 0.0,
      qd = 0.0;
float kd = 1.0, /* set constants */
      ki = 1.0,
      ko = 100.0,
      kf = 1.0,
      ks = 70.0,
      dt = 0.1;
float sp3 = 0.0, /* initialize variables for perceptual delay */
      sp2 = 0.0,
      sp1 = 0.0;
int i;
 clrscr();  /* alternative: for(i=0;i<25;++i) putch(0x0d); */
 for(i=1;i<=80;++i)
  {
   if(i > 40) qd = 9.0; else qd = 0.0;
   qi = kf*qo + kd*qd;
   sp = sp1;
   sp1 = sp2;
   sp2 = sp3;
   sp3 = ki*qi;
   se = sr - sp;
   qo = qo + (ko*se - qo)*dt/ks;
    gotoxy(i,24 - sr/2.0 - 0.5); putch('r');
    gotoxy(i,24 - qd/2.0 - 0.5); putch('d');
    gotoxy(i,24 - qo/2.0 - 0.5); putch('o');
    gotoxy(i,24 - sp/2.0 - 0.5); putch('p');
  }
 (void) getch();
}

Compile and run this program.
At the start of the run, when the reference signal is set to 20.0, the
output immediately begins to rise. Examining the block diagram of the
system (Part I), you can see that a change in the reference signal shows
up immediately as a change in the error signal, which drives the output.
This change in the output, however, is not reflected in the perceptual
signal until the fifth iteration (it is probably affected on the fourth
iteration, but not enough to show on the plot). When the disturbance
switches to 9.0, the perceptual signal does not show the effect for
three iterations even though the input quantity is immediately affected;
then, when this effect does appear in the perceptual signal, the output
begins to change at the same time.

So there is some difference when the delay is shifted to the input side.
But control remains just as good as before, and with the same slowing
factor of 70.

                          Sampled Control

Control systems can be designed so that they sample the state of the
input at intervals instead of continuously. In the final program in this
section, we use a timer variable t to count iterations. On every fourth
iteration, the perceptual signal is set to the appropriate level on the
basis of the input quantity. Between samples, the perceptual signal
simply holds the last sampled value. All the other variables in the loop
change on every iteration as usual. Here is the program:

/* primer5.c */

#include "stdio.h"
#include "conio.h"

void main()
 {
float sp = 0.0,  /* initialize signals and quantities */
      sr = 20.0,
      se = 0.0,
      qo = 0.0,
      qi = 0.0,
      qd = 0.0;
float kd = 1.0, /* set constants */
      ki = 1.0,
      ko = 100.0,
      kf = 1.0,
      ks = 70.0,
      dt = 0.1;
int i,t = 0;
 clrscr();  /* alternative: for(i=0;i<25;++i) putch(0x0d); */
 for(i=1;i<=80;++i)
  {
   if(i > 40) qd = 9.0; else qd = 0.0;
   if(t == 0)
    {
     qi = kf*qo + kd*qd;
     t = 4;    }
   t = t - 1;
   sp = ki*qi;
   se = sr - sp;
   qo = qo + (ko*se - qo)*dt/ks;
    gotoxy(i,24); putch('-');
    gotoxy(i,24 - sr/2.0 - 0.5); putch('r');
    gotoxy(i,24 - qd/2.0 - 0.5); putch('d');
    gotoxy(i,24 - qo/2.0 - 0.5); putch('o');
    gotoxy(i,24 - sp/2.0 - 0.5); putch('p');
  }
 (void) getch();
}

Once again, smooth control is achieved with a slowing factor of 70.
Notice that while the output quantity changes smoothly, the perceptual
signal changes in steps, one step on every fourth iteration. Obviously
no disturbance can be resisted if it occurs during the hold period; the
opposing output can only begin to change when the next sample occurs.
The average delay would be half the sampling period. As with all control
systems, disturbances can come and go too rapidly to oppose. But natural
control systems are adapted to the environment that exists; most natural
disturbances, therefore, can be opposed before their effects become
important.