<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="pattern.xsl"?>
<pattern id="">
  <name>Goal Seeker</name>
  <relatedPatterns> 
    <relatedPattern ref="">
    </relatedPattern> 
    <relatedPattern ref="" /> 
  </relatedPatterns>
  <diagram>
  <web>
  <img src="DiagramGoSe.gif" width="400"  />
  </web>
  <latex>
    <img src="DiagramGoSe.pdf" width="400"  />			
	</latex>
  </diagram>
  <what>
    <paragraph>Change an input until a chosen output meets a
    threshold.
    </paragraph>		
  </what>
  <when>
    <paragraph>
      Parametric models are acyclic---they evaluate nodes upstream to
      downstream. In other words, you need to know parameter values to
      produce a result. Sometimes, though knowledge works the other
      way. You know a goal for a particular variable and want to
      discover a set of input values that will achieve it. Use this
      pattern when you want to adjust inputs until you reach a goal.

    </paragraph>
  </when>
  <why>
    <paragraph>
      Without values for its independent variables, a parametric model
      is <em>undetermined,</em> that is, it does not contain
      sufficient information to give values to its dependent
      variables. Typically, a model can exist in an indenumerable
      infinity of states, depending on the choice of its input
      values. Sometimes, you know a property of such a state. You may
      even be able to adjust input values until the property is
      achieved. But accuracy and reproducibility are important. A
      <patternName>Goal Seeker</patternName> can compute the needed
      input values.
    </paragraph>
  </why>
  <how>
    <paragraph>A model has inputs and some outputs. A
    <patternName>Goal Seeker</patternName> requires a choice of both:
    an output that will be evaluated and an input that will be
    adjusted. The output is called the <em>result</em> and input the
    <em>driver</em>. The threshold that the result should meet is
    called the <em>target.</em> The process of calculating the result
    from the inputs is the <em>update method.</em>
    </paragraph>
    <paragraph>
      The <patternName>Goal Seeker</patternName> script runs the update
      method then checks the result. If it meets the target, the job
      is done and it returns. If not, it goes back, slightly changes
      the driver, runs the update method and checks the result
      again. This loop continues to run until the desired result is
      achieved.
    </paragraph>
    <paragraph>
      A simple way of being systematic is to use a binary search, in
      which an estimate of the distance to the target determines
      changes to the driver. While searching, the incremental step
      change of the driver may cause the result to pass the target. If
      this happens, the script reverses and reduces the step
      size. Then it continues changing the driver until it passes the
      target again. It repeats the search process until the result
      meets the target (with adequate precision).
      <animation src="diagram/AnimationGoSeAnimationDiagram00.swf"/>
    </paragraph>
    <paragraph>
      The simple <patternName>Goal Seekers</patternName> presented in this pattern
      require that the model (or at least the result) changes
      smoothly with changes in the driver. If the result varied in
      sharp jumps, the strategy of slowly changing the driver to
      approach a result would not work. Such situations present
      complex problems of <em>discrete search</em> or <em>constraint
      satisfaction</em> that are beyond the scope of simple elements
      of parametric design.
    </paragraph>
    <web>
     <paragraph>
      Following is a much-simplified example of
      <patternName>Goal Seeker</patternName> code.  Actual running code
      can be dowloaded <a href="GoSeTrivial.gct" > here.</a>
     </paragraph>
    </web>
  </how>

<web>
<pre>
transaction script "trivial goal 
 {
 // This is a trivial example, in that the target and result are direct 
 // measures of the same parameter on a line. Thus, we could simply set the 
 // result to the target. However, this simplicity lets us explain the code 
 // structure more clearly.
 // 
 // The features we name "driver" and "trackLine" already exist in the 
 // model. We just access them here. The "trackLine" is the curve on which 
 // the parametric point "driver" lies.
 
 Point driver = FindFeature("pointOnLine");
 ICurve trackLine = driver.Curve;
 
 // We aim to find the result such that the driver parameter (T) is equal
 // to the target. Choose an arbitrary target value. Any value would work.
 
 double target = 0.6;
 
 // In this example, we assume that the driver's parameter is less than the target.
 // Generalizing this requires an additional test that would obscure the 
 // essential action of the Goal Seeker.
 
 driver.ByParameterAlongCurve(trackLine, 0.3);
 
 
 // Set the result to whatever the driver's parameter happens to be now.
 
 double result = driver.T;
 
 // "CurrentT" stores the current T value so that we can reverse the search
 // should it overshoot the target.
 
 double currentT;  
 
 // "Increment" is an (almost) arbitrary choice of the initial increment
 // for the search. It is almost arbitrary, because it must be chosen so that
 // a single increment does not completely skip a region of interest.  
 // In this case, the increment must be such it moves the result towards
 // the target.
 
 double increment = 0.2;
 
 // "incrementAdded" counts the number of times that the increment has been
 // added to currentT.
 
 int incrementAdded = 0;
 
 // " incrementSubdivided " counts the number of times that the increment has
 // been halved in the search.
 
 int incrementSubdivided =0;
 
 // "closeEnough" is the threshold for the search. Once the result is
 // closeEnough to the target, we stop.
 
 double closeEnough = 0.000001;
 
 // "giveUpWhen" is the threshold for iterations in the loop. You should
 // set the increment so that the number of steps needed to overshoot the
 // target is much smaller than giveUpWhen. 
 // This is defensive coding.
 // If you leave out this parameter, expect to reboot the system frequently
 // as the script can go into an infinite loop.
 
 int giveUpWhen = 100;
 
 // Ensure that the increment moves you towards the target. In a non-trivial
 // example, this part of the code can be quite tricky. In this example, no code
 // is needed, as the result is initially less than the target.
 
 if (result >= target)
 {
 
 }
 
 // There are two loops.
 // The inner loop adds the increment to the currentT until the result
 // overshoots the target.
 // The outer loop implements a binary search. It divides increment by 2
 // (any number greater than one will work) and restarts the inner loop
 // from currenT, which is the last position before overshooting.
 
 // The initial increment will be divided at the start of the outer loop.
 
 increment = increment * 2;
 
 while (incrementSubdivided &lt; giveUpWhen &amp;&amp; increment &gt; closeEnough)
 {
 // 
 incrementSubdivided = incrementSubdivided + 1;
 increment = increment / 2;
 
 // Reset incrementAdded so that the inner loop starts counting at zero.
 
 incrementAdded = 0;
 
 while ( result &lt; target &amp;&amp; incrementAdded &lt; giveUpWhen)
 {
 incrementAdded = incrementAdded +1;
 currentT = driver.T;
 driver.ByParameterAlongCurve(trackLine, currentT+increment);
 
 // UpdateGraph causes the constraint system to recompute new values for
 // all features, thus computing one cycle of the search.   
 
 UpdateGraph();
 result = driver.T;
 }
 
 // The search has now overshot the target. Start again just before the
 // overshot with a smaller increment.
 
 driver.ByParameterAlongCurve(trackLine, currentT);
 
 // This call to UpdateGraph is needed as we have just returned to a
 // previous state.
 
 UpdateGraph();
 result = driver.T;
 }
 }
</pre>		
</web>  
  <samples>
    
    <sample id="LocalMaximum">
      <name>Local Maximum</name>
      <when>
	<paragraph> 
	  Locate the point on a curve at which the curve is at a maximum. 
	</paragraph>
      </when>
      <how>			
      <paragraph> 
	Elementary calculus (or just looking at a curve) tells us
	that, at any maximum (or minimum) point, the tangent to a
	curve<latex>\index{curve}</latex> is horizontal. Thus the angle between the tangent<latex>\index{tangent}</latex> and a
	horizontal line is zero. Searching for a fixed value
	simplifies the <patternName>Goal Seeker</patternName> script
	in comparison to looking for an unknown maximum. The tangent
	changes predictably as a point moves across a maximum. Its
	slope is greater than zero on one side of the maximum and less
	than zero on the other side. This gives a very simple rule for
	changing the driver: always move towards zero.
      </paragraph>
      <paragraph> 
	The essential idea is simple. Start at a known point on the
	curve. Always step upwards. At each step measure the slope. If
	it is zero stop. If is changes direction, turn around, takes
	smaller steps and keep going. Not surprisingly, this is called
	a hill-climbing strategy. It has some problems. If there is a
	local hilltop in the direction you start walking, you will
	reach it and be trapped, even if you can see a taller hill
	nearby. If the hilltop is really small, that is, small in
	relation to the steps you are taking, you might miss it
	altogether.
      </paragraph>
      <paragraph> 
	Key to writing a working <patternName>Goal
	Seeker</patternName> is understanding how the build desired
	measure into the system. Understand how the result will change
	with changes to the driver. In this case, the tangent measure
	makes the choice easy. In other cases code may be needed to
	check the effect of change of the driver on the result and to
	choose the appropriate direction of change.
      </paragraph>
      <paragraph> 
	The code for this <patternName>Goal Seeker</patternName> is
	relatively simple. Unfortunately, other <patternName>Goal
	Seekers</patternName> require significantly more complex code.
	There are two nested <arg>while</arg> loops. The outer loop<latex>\index{program!control statement}</latex>
	implements the binary search, the inner one the "walk" towards
	the target. The inner loop has a test <arg>driver &gt;
	driver.RangeMinimum &amp;&amp; driver &lt;
	driver.RangeMaximum)</arg> that ensures that point remains on
	the parametric curve. If the local maximum is at one of the curve
	ends, the <patternName>Goal Seeker</patternName> will
	approach, but never overshoot the end and will finally arrive
	at it.
      </paragraph>
      <latex>\newpage
        <paragraph> 
	  Code for the <sampleName>Local Maximum</sampleName> sample.
        </paragraph>
      </latex>
      </how>
<pre>
function generalNumericTest (object booleanTest, 
                             double a, double b)
 { //provides conditional test of two numeric variables 
   //based on an input string. 
  switch (booleanTest){
  case ">=": return a >= b;
  case "&lt;=": return a &lt;= b;
  case ">" : return a > b;
  case "&lt;" : return a &lt; b;
  case "==": return a == b;
  default: return true;
  }
 }

double currentDriver = driver.Value; 
   //driver is a named variable in the model.
double target = 0.0;
double closeEnough = 0.000000001;
int giveUpWhen = 200;
int incrementAdded = 0;
int incrementSubdivided = 0;
double increment = 0.2;
object startingSide = "gt";
int incrementSign = 1;
    
if (result>target){
  startingSide = ">";
  incrementSign = 1;
 }
 else{   
  startingSide = "&lt;=";
  incrementSign = -1;
 }
while (increment > closeEnough &amp;&amp; 
       incrementSubdivided &lt; giveUpWhen)
 {
  ++incrementSubdivided;
  increment = increment/2.0;
  while (generalNumericTest(startingSide,result,target) &amp;&amp; 
         incrementAdded &lt; giveUpWhen &amp;&amp;
         driver > driver.RangeMinimum &amp;&amp; 
	 driver &lt; driver.RangeMaximum)
   {
    ++incrementAdded;
    currentDriver = driver.Value;        
    driver = currentDriver+(incrementSign*increment);
    UpdateGraph();
   }
  driver = currentDriver;
  UpdateGraph();
 }
</pre>
      <a href="Samples/GoSeLocalMaximum/GoSeLocalMaximum.gct" >Click
      to download GoSeLocalMaximum.gct</a>
      <animation src="Samples/GoSeLocalMaximum/AnimationLocalMaximum00.swf"/>			
    </sample>
    
    <sample id="CurveAndPointDistance">
      <name>Curve And Point Distance</name>
      <when>			
	<paragraph> 
	  Adjust a curve until it is exactly a given distance to a point at its closest approach.
	</paragraph>
      </when>
      <how>
      <paragraph> 
	In this sample the goal is a minimal distance. Every point on
	a curve<latex>\index{curve}</latex> is some distance from a given point<latex>\index{point}</latex>. One (or more) of
	the curve points lie at the least distance. Such points are
	<em>projections</em> of the a point onto a curve.
      </paragraph>
      <paragraph> 
	Clearly, any of the control points on a curve can be
	changed. For each of these points, any direction of change
	could be used. Using a <patternName>Goal Seeker</patternName>
	requires choice of both point and direction of movement.
	Other choices of point and direction can yield vastly
	different curves, but they will be at the goal distance (if
	the <patternName>Goal Seeker</patternName> works).
      </paragraph>
      <paragraph> 
	Once a control point and direction of movement are chosen, a
	<patternName>Goal Seeker</patternName> works as we have
	already described: walk towards the target until you
	overshoot; back up and take smaller steps; and keep doing this
	until you are as close as you can discern.
      </paragraph>
      <latex>\setlength{\storedWidth}{\currentWidth}
             \setlength{\currentWidth}{\currentWidth*\real{0.9}}
             \hfill</latex>
	<diagram>
	  <img src="Samples/GoSeCurveAndPointDistance/CrvPoiDistanceDiagram.pdf" width="400"  />
	</diagram>
      <latex>\hfill
             \setlength{\currentWidth}{\storedWidth}</latex>
      </how>
      <a href="Samples/GoSeCurveAndPointDistance/GoSeCurveAndPointDistance.gct"
	  >Click to download GoSeCurveAndPointDistance.gct</a>
      <animation src="Samples/GoSeCurveAndPointDistance/AnimationCurveAndPointDistance00.swf"/>			
    </sample>
    
    <sample id="Area">
      <name>Area</name>
      <when>			
	<paragraph> 
	  Adjust a control point of a curve until the curve encloses a given area.
      </paragraph>
      </when>
      <how>
	<paragraph> 
	  The goal here is the area of a closed curve<latex>\index{curve}</latex>. As in the
	  previous sample, any of the control points of the curve can
	  be moved and in any direction. The modeler must choose the
	  control point. This particular sample moves the chosen
	  control point away from the centroid of all other control
	  points. This is a useful approximation, but, with some work,
	  any other direction could be chosen.
	</paragraph>
	<paragraph> 
	  The <patternName>Goal Seeker</patternName> is almost
	  identical to previous <patternName>Goal
	  Seekers</patternName>. The details of the curve, the chosen
	  point and its direction are all factored into the single
	  variable called <math latex="\afVar{driver}">driver</math>.
	</paragraph>
      </how>
      <a href="Samples/GoSeArea/GoSeArea.gct" >Click to download
      GoSeArea.gct</a>
      <animation src="Samples/GoSeArea/AnimationArea00.swf"/>			
    </sample>

    <latex>\renewcommand{\sampleNewPage}[0]{false}</latex>    
    <sample id="TwoCircles">
      <name>Two Circles</name>
      <when>			
	<paragraph> 
	  Given a circle constrained to move along a line, find the
	  position of its centre such that it is tangent to another
	  circle.
      </paragraph>
      </when>
      <how>
	<paragraph> 
	  Computing tangency<latex>\index{tangent}</latex> is easy if the circles<latex>\index{circls}</latex> are
	  unconstrained. The centres of the two circles form a
	  line. Move one circle along the line such that its centre is
	  plus or minus its radius from the intersection of the line<latex>\index{line}</latex>
	  and the other circle. This situation is different --- the
	  centre of once circle is constrained to lie on another,
	  arbitrary line. The movement of the circle centre is
	  governed by a parametric point-on-curve parameter <math
	  latex="t">t</math>. The <patternName>Goal
	  Seeker</patternName> adjusts this parameter until the
	  tangency conditions are met. The <patternName>Goal
	  Seeker</patternName> must operate twice: once for each
	  tangency condition.
	  \index{pattern|)}
	</paragraph>
      </how>
      <a href="Samples/GoSeTwoCircles/GoSeTwoCircles.gct" >Click to
      download GoSeTwoCircles.gct</a> <animation
      src="Samples/GoSeTwoCircles/AnimationTwoCircles00.swf"/>
    </sample> 
  </samples> 

</pattern>

