Index

 

Optim Source Code

 

The paper describes the results of applying a simulated annealing algorithm to explore aspects of the optimization of laryngoscope blade design. In order to do so, a mathematical model of laryngoscope blade shape and airway anatomy was constructed. This model was used to create evaluation functions based on and modified from evaluation criteria suggested by Marks and Hancock (Can J Anaesth 1993; 40: 262-270).

 

The computer source code written to implement the mathematical model is too lengthy to publish as part of the paper. However, the validity of the results obtained cannot be confirmed without the availability of the source code. This is true of any computer-aided calculations. For this reason, the relevant code is included and described here.

 

General

The computer language used is C++, and the program Optim.exe was compiled with the Microsoft Visual C++ 4.0 compiler. Numerical Recipes in C routines were used for the multidimensional optimization algorithms. The programming was essentially completed before the ANSI/ISO standardization of C++: STL container classes were not used, and in particular all numerical work was done using arrays rather than the new standard library Vectors or Valarrays.

 

This document reviews only the source code that directly implements the relevant numerical models and functions. Code supporting graphical display, user input, and interaction with the Windows operating system is not included or discussed further.

Program Structure

The high level structure of the code is object-oriented. The major abstractions are implemented by three C++ class hierarchies: the Shape classes model the shape of a laryngoscope blade, the Blade classes model a functional laryngoscope, and the MdOptimum classes provide an interface to the multidimensional optimization algorithms. The abstract class Mdfunc is used to create function classes that can be passed directly to Numerical Recipes functions that expect a pointer to a function as a calling parameter.

 

The numerical code is aggressively optimized for speed. Extensive use is made of low-level language features such as C-type arrays. A contractual programming approach is used at this level to avoid inefficiencies caused by bounds checking and other defensive programming techniques. Code at this level is hidden within class member functions, or at least declared as protected data or functions within classes.

Shape Hierarchy

Class Shape

Class Shape is an abstract base class that provides an interface for constructing and using the curves defining the shape of a laryngoscope blade, and that encapsulates the required data structures. In particular, the arrays dat[], ling[], xinc[], and yinc[] represent the raw data, lingual curve, and the x and y values of the incisor curve respectively. Values of parameters such as the minimum IT length at blade insertion and the minimum number of segments to be inserted are also declared, as is a “penalty” variable used to modify the calculated score value for pathological cases.

 

Class Shape declares pure virtual functions. In particular the function calc(float d[]) (that calculates the values at each point on the curves) must be defined in derived classes. Instances of Shape objects therefore cannot be declared, although the Shape interface can be accessed through a pointer to Shape. Class Blade is declared as a friend to class Shape, so objects of type Blade can access private and protected data through a pointer to Shape.

Class Shape_Arch

Class Shape_Arch is an abstract node class derived from class Shape. It provides the important function arch(float d[]) which calculates a unimodal curve given a vector d[] of n floating point values. Conceptually, for each of the n values, a triangle is constructed with a height of that value, on a base of length n+1.  The curve is then the sum of all the triangles. This method of calculating the curve is key to creating an efficient function that takes an n-dimensional input vector and creates a curve whose shape is determined in a similar way by each input value.

Class Shape_Proportional

Class Shape_Proportional is derived from class Shape_Arch. It models both the lingual blade curve such that there is a progressively decreasing IT distance as the blade insertion is increased, and the incisor curve such that the inter-dental distance is proportional to the IT distance at each insertion depth. To create the incisor curve, the oral and pharyngeal anatomy is modeled using three anatomical parameters. Much of the code implementing this class is devoted to ensuring that all possible input vectors, even those representing points far from the “reasonable” regions of the function space, result in blade shapes that can be evaluated in a useful way.

 

This is the only blade shape model used by the current version of the program Optim.exe, but other ways of modeling both the blade curves and the anatomy are possible. These other models can be implemented as classes derived from class Shape, and because of the C++ support for virtual functions and run time polymorphism, can be used and evaluated without modifying any of the other code. In fact, this process was repeatedly iterated during the development of this program and is a good example of the power of C++ in application development.

Blade Hierarchy

Class Blade

Class Blade models a laryngoscope blade. In particular, it models the lingual and incisor curves given an input vector of n floating point values. This class contains a data member of type pointer to Shape, implementing a “has-a” relationship: a Blade has a Shape. In fact, the class consists of little more than a wrapper around the pointed to Shape object.

Class Scope

Class Scope models a functional laryngoscope. In particular, it is a Blade that can be inserted to different IT distances, and the angles EIT and MIT (actually their tangents) calculated for each insertion distance. Class Scope is also derived (by multiple inheritance) from class Mdfunc, so it is a function object that will return a value (the evaluation score for the blade shape) given a multidimensional floating-point input vector.

 

The evaluation function calls two pure virtual functions (decodescore(float)  and scorecode(float, float)), so Scope is an abstract class and no objects of type Scope can be constructed. These two functions must be defined in classes derived from class Scope. The reason for using two functions rather than a single virtual score calculation function is to allow optimization of the calculations of intermediate values (for example, to avoid the need to convert tangents to their corresponding angles).

Class ScopeMHC

Class ScopeMHC  is a Scope whose function operator returns a value calculated using the MHC Score. The two virtual functions (decodescore and scorecode) are overloaded to perform the calculation.

 

Class ScopeREIT

Class ScopeREIT  is a Scope whose function operator returns a value calculated using the REIT Score. The two virtual functions (decodescore and scorecode) are overloaded to perform the calculation.

MdOptimum Hierarchy

Class MdOptimum

Class MdOptimum is an abstract base class that provides an interface to the multidimensional optimization algorithms. Derived classes MdOptimum_ft and MdOptimum_restart provide more specific interfaces.

Class Algamebsa

Class Algamebsa is an abstract class derived from class McOptimum_ft. It encapsulates the data structures and initialization code required to use the Numerical Recipes simulated annealing function amebsa. The pure virtual function cool() must be defined in derived classes in order to implement an annealing schedule.

Class Algamebsa­­_nocool

Class Algamebsa­­_nocool is derived from class Algamebsa, and implements a minimalist annealing schedule that simply calls the function amebsa() at a single “temperature” for a specified number of function iterations.

Class Alganneal

Class Alganneal is derived from class Algamebsa­­_nocool. It implements the annealing schedule used by the program Optm.exe to perform all the simulated annealing optimization runs. The “temperature” is decreased by a constant fraction after every set number of function iterations (see NRC page 452). The annealing parameters are input using the function setschedule(float ht, float lt, int st, int fi) and the annealing schedule is implemented by the virtual function cool().

Class Algamoeba

Class Algamoeba is derived from class MdOptimum_restart and implements an interface for the use of the Numerical Recipes optimization routine amoeba.

Class Algpowell

Class Algpowell is derived from class MdOptimum_restart and implements an interface for the use of the Numerical Recipes optimization routine powell.