On SPEAR3 it takes about seventeen seconds to measure injection efficiency once. A genetic or swarm optimizer wants thirty of those every generation. That is eight and a half minutes of beam, and plenty of it goes to settings that were never going to be good. MG-GPO puts a Gaussian process between the breeding and the machine, so most bad candidates are dropped unmeasured. Xiaobiao Huang came up with it and wrote the first Matlab version. Minghao Song and I developed it with him, and I led the runs on the ring (Minghao and I share first authorship of the MLST 2020 paper).
- 300 to 1,200candidates bred each generation on the ring, for thirty measurements
- −1.66 mA/minloss-rate objective MG-GPO reached, close to the ring's best in recent studies
- 0.9 kVkick it took to knock out half the stored beam after the second injection run
One generation
Each generation MG-GPO breeds hundreds of candidates from its population of thirty, with operators borrowed from particle swarm and NSGA-II. One Gaussian process per objective scores every candidate with the lower confidence bound.
is what the GP predicts for a candidate, how unsure it is there, and how much that doubt counts in the candidate's favour, with every objective written so that lower is better.
Non-dominated sorting keeps the thirty that go to the machine. shrinks by a fixed factor every generation, so it gambles on uncertain corners early and trusts the model later.
A usual Bayesian optimizer searches a bumpy acquisition function at every step. MG-GPO skips that. The GP only puts the bred candidates in order, and on the ring that usually took under eight seconds a generation.
Each GP has one length scale for all the knobs, so there are just three hyperparameters to fit. We couldn't find a decent GP package for Matlab, so GPy did the fitting in Python behind Teeport, the platform I was writing then, and the rest stayed in Matlab.
Test problems
Away from the machine, Xiaobiao's method paper (on arXiv, with Minghao and me as co-authors) compared it with NSGA-II and three swarm methods on 30-dimensional ZDT problems. On ZDT2 it reached the front in about 1,000 evaluations, where the runner-up needed 4,000. It wasn't that far ahead everywhere; ZDT6 took it 3,000.

ZDT has no noise, and a ring does. So the MLST paper also ran it against PSO on a noisy 4-D Rosenbrock function. MG-GPO was near zero by about 600 evaluations. PSO still hadn't converged at 1,020. Ten times the noise made no clear difference to either. On a simulated SPEAR3 vertical-emittance problem MG-GPO was faster again, though its ten runs spread a little wider than PSO's.
What the ring measures
For injection efficiency the evaluator writes the ten sextupole families, reads the stored current, injects for about ten seconds and reads the current again. Divide that gain per minute by the charge the booster delivered and you have the score, in arbitrary units. (With no booster beam it divides by a huge number, so the point scores terribly.)
The loss-rate evaluator mostly waits. If top-off injection is on it polls until it stops, gives it a few more seconds, then reads the current twice a set time apart. We wanted that loss rate higher, which sounds backwards. At high current most of the loss is Touschek scattering, which gets worse as the beam gets thinner vertically. SPEAR3 measures beam size at one spot, and the loss rate sees the whole ring.
Both evaluators registered with Teeport too, so they stayed in the control room and the optimizer could run anywhere. I also wrote the measurements in Python as spear3-opt-pkg, which switches injection off before moving any sextupole.
Thirteen skew quads
The vertical-emittance runs moved the thirteen powered skew quads at about 500 mA. MG-GPO was ahead almost from the start, through about 480 evaluations. PSO, under the same conditions, climbed more slowly and stopped at −1.48 mA/min.

Injection, twice
Dynamic aperture is how far from the stored beam a particle can start and still make it around the ring. The injected beam arrives off to one side, just past the septum wall, so the more aperture there is, the more of it gets caught. The sextupoles are what shape it.

In that simulation MG-GPO opened the aperture from 11.8 to 16.5 mm. PSO caught up in the end, since the score tops out just under full capture.
On the ring we tuned injection efficiency and let it stand in for the aperture. The eight knobs mix the sextupole families so the chromaticity stays put (to first order), and no family moves more than 20 A from the flat setting (all focusing sextupoles equal, all defocusing ones equal). Round one started from flat, which injects poorly, so we kept the kicker bump at standard strength. After five generations MG-GPO was near −2.9, and PSO from the same start had reached −2.2. (Efficiency goes in negated, so more negative is better.)

Then we made it harder. The kicker bump went down to 80% of standard, so the aperture mattered more, and a second run started around round one's best. We were short of machine time, so round two was MG-GPO alone. The smaller bump pushed the objective up to about −0.5, and the run pulled it back to about −1.4.
We also measured the aperture itself. Store a little beam, kick it harder and harder, and note the kick where half of it is gone. Flat sextupoles lost half at 0.76 kV, round one's best at 0.8 kV. Round two's did better again.

A few days later
The ring runs were a test of the method, and on the day the numbers were good. They didn't last. A few days later the solutions no longer held, and none of them went into routine operation at SPEAR3. Watching them fade is what started my next method, RCDS-S. We suspected the ring was drifting, so it had to cope with drift and noise, tuning in small steps checked against a line set in advance.
Numbers are from Zhang, Song and Huang, Mach. Learn.: Sci. Technol. 2, 015014 (online December 2020), Huang, Song and Zhang, arXiv:1907.00250, and our 2021 project report to SSRL. The evaluator steps are from our Matlab evaluator code.