![]()
Optimizer Examples
Maximize a Single-Parameter Function
Example 1 finds the maximum error when a Bode
approximation is used to represent a first-order filter. It does this by defining
two functions bode() and filter() and then finds the frequency at
which the difference in their magnitudes is a maximum. The maximum error is found to be 3dB
when freduced = f ⁄ f0 = 1.0.
The expression being maximized is very simple so it is specified directly as an argument to Optimize.
The search was started at freduced = 5 because the default starting values
±1.0 are not appropriate for this case.
By default, Optimize attempts to fit a quadratic hypersurface in the vicinity of the best point found. This process fails in this example because because, as the plot shows, the cost function in the vicinity of its minimum is a cusp.
Minimize a Two-Parameter Function
Example 2 searches for the minimum in the
Rosenbrock parabolic
valley ('banana') function. This has a global minimum of 0 at the point (1,1). Convergence to
the minimum is slow, so the limit on function evaluations neval was increased to
500. Setting stoppar to 10−6 causes the search to terminate when the parameters
have stabilised to roughly six significant figures. Fitting a quadratic surface in the region suggested by the search
succeeds, and this reassures us that a true minimum was found.
Refine a Filter Design
This example is based on the Phonocard Phono Equaliser design for a pre-amplifier with RIAA equalization. A simulation of this design (using AD797 and OP637 as the first- and second-stage op-amps respectively) shows deviation from the RIAA standard of approximately ±0.8 dB over the range 20 Hz — 20 kHz (see figure below). This deviation can be reduced by using the optimizer to find better values for some of the resistors. The task is divided into three files:
- The netlist riaa-circuit.cir
- The cost function procedure riaa-cost.src
This checks that the each of the parameter values, stored by the optimizer in vector p, lies in an acceptable range. If so, it alters the corresponding resistor values, and obtains the frequency response with an AC sweep analysis. The deviation from the ideal RIAA curve is calculated and stored in the vector 'error'. The cost to be minimized is set equal to the mean squared error. The plot created by the AC sweep is destroyed before returning, in order to conserve memory.
- The task definition riaa-optim.src
This invokes the optimizer, defines the RIAA standard curve, and displays the results as graphs.
Using the optimized values for the resisistors, the amplifier deviates from the RIAA curve by ±0.07 dB over the range 20 Hz — 20 kHz.
| Device | R1 | R2 | R3 | R4 | R5 |
|---|---|---|---|---|---|
| Original (Ω) | 24000 | 2610 | 2000 | 22600 | 953 |
| Optimized (Ω) | 24786 | 2685 | 2804 | 25152 | 1109 |

Difference between Phonocard Equaliser and RIAA reference curve.
Linearize a Differential Input Stage
The the maximum input range, distortion, and linearity of an amplifier can be improved by summing two offsetted differential input stages. In this example, we seek the offset that maximises the range of input over which the gain is constant to within 2dB. This a one-parameter problem. The areas of the devices are adjusted by varying the parameter p. The 'cost' is (minus) the range explicitly calculated from the transfer function. The task is divided into three files:
- The netlist diffpair-circuit.cir
- The cost function procedure diffpair-cost.src
This checks that the value of the parameter p, set by the optimizer, lies in an appropriate range. If so, it alters the transistor areas, keeping the total area constant, and performs a DC sweep. It calculates the 'gain' of the amplifier from the derivative with respect to the sweep. Starting at the zero-input gain, the procedure works along the sweep until the it finds the point where the variation in the gain is just within the specification set by the variable
$ripple, 2dB in this case. It sets the cost to the value of the sweep variable at this point, and negates; the optimizer minimizes cost, but we want the largest range. The plot created by the DC sweep is destroyed before returning, in order to conserve memory. - The task definition diffpair-optim.src
This invokes the optimizer, and plots a sweep corresponding to the best value found.
MacSpice finds the best value at p = 0.7523438, Δp = 0.00078125 which corresponds to a ratio of areas for the 'N' and '1X' transistors of (1+p)/(1−p) = 7.08, i.e. seven-to-one.
Another way to tackle this problem with the MacSpice optimizer is to treat it as a two-parameter optimization (diffpair-optim2.src). In addition to the areas, the range is treated as an adjustable parameter. In this scenario, the cost function is much easier to calculate (it's just minus the range parameter) but procedure to evaluate the cost (diffpair-cost2.src) must also calculate the variation in gain over the range and reject (by signalling a constraint violation) the parameters if the variation exceeds 2dB.