A neural network made of formulas, compiled for the chip
NAI-fnet grows a model from your measurements one neuron at a time; every neuron is a short
formula over the inputs.
The result is plain C for a microcontroller: kilobytes of code, a fraction of a
microsecond per prediction, the same numbers as the model bit for bit.
/* exported as is; comments added */
static double fnet_core0(const double x[35]) {
double s = (double)0.37351673900124743;
/* ... */
s += (double)0.15797843735074976 * x[22]; /* sin q2 */
s += (double)0.055716649969486616 * x[34]; /* cos q7 */
s += (double)0.007614945134597908 * x[16]; /* ddq3 */
/* ... */
s += (double)-0.16006778427022469 * x[24]; /* sin q4 */
s += (double)-0.013372094519342301 * x[17]; /* ddq4 */
s += (double)-0.071476869033755872 * x[30]; /* cos q3 */
return s;
}
- 46×smaller code than LightGBMdefault settings; compiled C, 7 tables registered in advance
- 3.9×faster predictionsame tables, gcc -O2, double
- 1stof 12 models below the data's range12 table splits, same registered test
- 0 bitsbetween the C code and the modelchecked on every release
Registered test of 06.11.2026 on seven engineering tables NAI-fnet had never seen: four of five hypotheses held; the one that failed: beyond the data, a small MLP was more accurate overall. The three examples below are separate registered tests.
How it works
A neural network learns weights for a fixed set of neurons.
NAI-fnet chooses the neurons
themselves: each one is a short formula found in your data.
- 01 · recordA table of measurements
5 to 100 inputs, one output, from hundreds to tens of thousands of rows: a calibration run, a test bench, a simulation.
q_1 … ddq_7 → tau_4 - 02 · growNeurons that are formulas
Each neuron is a short formula over the inputs, readable term by term. The network grows one neuron at a time and stops when the next one no longer pays for itself.
+ 0.158·sin q₂ - 03 · checkKnows where to trust itself
Every model comes with a range monitor: it tells when the inputs leave the data the model was built on, so the device knows when to rely on the answer.
fnet_in_range() - 04 · compilePlain C for the chip
No runtime, no dynamic memory, no tables of weights: a function of a few hundred operations, with a range monitor and a bounded output.
nai_cli --net --export-c fnet.c
Three examples, three registered tests
Real data, published protocols where they exist, the hypotheses written down before the one run on
the test data. Each example below has a simulator of the device and its full results.
All eight registered tests, with their uncertainty intervals and the hypotheses that failed:
the preprint (Zenodo); the registrations and
their scripts: the
track record.
| what the chip computes | NAI-fnet | the strongest other model | code on the chip | hypotheses held | |
|---|---|---|---|---|---|
| Robot's elbow | the torque the joint needs (a virtual torque sensor) | 0.062 % nMSE | tuned LightGBM 0.060 %; the published model 0.090 % | 34 KB, 0.65 µs (boosting: 566 KB, 29 µs) | 5 of 5 |
| Traction motor | the rotor magnets' temperature (a virtual temperature sensor) | 1.76 K² MSE | MLP 32×32 3.12 K²; tuned LightGBM 6.62 K² | 87 KB, 1.1 µs (boosting: 5.1 MB, 143 µs) | 5 of 5 |
| Airliner | drag beyond the measured Mach numbers (an aerodynamic model) | 27.8 drag counts | MLP 32×32 41.9; tuned LightGBM 42.8 | 21 KB, 2.3 µs (boosting: 496 KB, 14 µs) | 4 of 5 |
A chip in a robot's elbow
An android's arm needs to know the torque its elbow motor must give at every moment: to move
smoothly, and to notice when it touches something. A torque sensor in every joint is expensive.
Here the elbow's microcontroller learns to compute it instead.
The arm replays joint angles recorded on a real robot arm; the torques, the training and the predictions
are real too.
Loading the simulator…
The android is an illustration; its arm follows the seven joint angles of a Franka Emika Panda
arm (Zenodo 12516500, University of Padua and MERL, CC BY-SA 4.0).
“Push the arm” adds a synthetic 0.6-second external torque to the
measured one; everything else is recorded data and the model's real output.
On a real robot arm
A 7-joint Franka Emika Panda, the published protocol of Giacomuzzo, Carli, Romeres and Dalla Libera
(IEEE Transactions on Robotics, 2024): train on two recorded trajectories, check on 16 others, 12 times over.
NAI-fnet learns what the robot's nominal rigid-body model misses: friction, cable forces, errors in the
nominal masses.
| model | nMSE | code on the chip | one prediction |
|---|---|---|---|
| NAI-fnet + nominal model | 0.062 % | 33.8 KB | 0.65 µs |
| LIP Gaussian process (the paper's model) | 0.090 % | keeps its training data | — |
| GIP Gaussian process with friction | 0.297 % | keeps its training data | — |
| tuned LightGBM + nominal model | 0.060 % | 566 KB | 29 µs |
| MLP 32×32 + nominal model | 0.120 % | 19.0 KB | 1.2 µs |
| nominal model alone | 0.641 % | — | — |
- 31 %lower error than the paper's modelelbow, 192 trajectory checks
- 5 of 7joints more accurate than the paper's modelless accurate on joints 3 and 7
- 17×smaller code than tuned LightGBMwithin 3.5 % of its error (0.060 %)
- 45×faster predictiongcc -O2, double
nMSE: mean squared error over the variance of the measured torque, averaged over 16 test
trajectories and 12 training pairs (192 checks).
The Gaussian-process numbers are computed from the estimates
the authors published with the data; their models do not use the nominal model, NAI-fnet, LightGBM and the MLP
learn its error.
NAI-fnet trained on half the rows the authors' models had (the archive holds one of their two
files per trajectory).
Registered before the run, 09.11.2026 (SHA-256 d016dd39…67b4): all five hypotheses held.
Data: G. Giacomuzzo, A. Dalla Libera (University of Padua), D. Romeres (MERL), the data of “A Black-Box Physics-Informed Estimator Based on Gaussian Process Regression for Robot Inverse Dynamics Identification” (Zenodo 12516500), CC BY-SA 4.0; the excerpt in fnet/sim.json is adapted (resampled, with the model's predictions added) and shared under the same licence.
The magnets' temperature, without a sensor
Overheated magnets lose their strength for good, so a drive holds back long before the limit, and a
sensor on the spinning rotor is not an option in a car. NAI-fnet estimates the magnets' temperature in the
inverter, from the currents, the speed, the coolant and the stator's thermistors.
A permanent-magnet motor on a test bench, cut open: its rotor turns with the recorded speed; the magnets' colour
is their temperature, measured by the bench's telemetry while recording, estimated by the chip when running.
Loading the simulator…
The motor is an illustration; the speed, torque, currents and temperatures come from the Electric Motor Temperature dataset (Paderborn University): a training drive to record, test drive 60 to run. The plot shows the measured rotor temperature, the chip's estimate, and the stator winding's thermistor.
Three drives it had never seen
A 22/52 kW permanent-magnet synchronous motor, 185 hours on a test bench.
Every model learned 66 drives
and estimated the magnets' temperature through the dataset authors' three test drives (8.9 hours, every half
second), from the inverter's signals, the stator's three thermistors and their moving averages.
| model | mean squared error | largest error after 10 min | code on the chip | one prediction |
|---|---|---|---|---|
| NAI-fnet | 1.76 K² | 6.3 K | 87 KB | 1.1 µs |
| MLP 32×32 | 3.12 K² | 6.1 K | 28 KB | 2.0 µs |
| ridge regression | 5.60 K² | 7.7 K | 0.7 KB | 0.07 µs |
| tuned LightGBM | 6.62 K² | 7.8 K | 5.1 MB | 143 µs |
- 1.8×more accurate than a small neural networkMLP 32×32: 3.12 K²
- 3.8×lower squared error than tuned boostingLightGBM: 6.62 K²; RMS error 1.9× lower
- 59×smaller code than tuned boosting87 KB against 5.1 MB
- 130×faster prediction1.1 µs against 143 µs
Registered before the run, 09.11.2026 (SHA-256 19e31042…10eb): all five hypotheses held.
The largest
errors of every model fall in a drive's first seconds, where the moving averages start; hence the column after 10
minutes, where NAI-fnet and the MLP are level.
Not comparable but for scale: the authors' Thermal Neural Network on
the same drives, without the stator's thermistors as inputs, reached 4.34 K².
Data: Electric Motor Temperature, W. Kirchgässner, O. Wallscheid, J. Böcker, Paderborn University (Kaggle, DOI 10.34740/KAGGLE/DSV/2161054), CC BY-SA 4.0; the excerpt in fnet/motor.json is adapted (every 20th sample, rounded, the model's estimates added) and shared under the same licence.
Drag beyond the measured Mach numbers
A flight computer's performance functions carry an aircraft's aerodynamics as large tables over angle
of attack, Mach and more; beyond their points they can only hold the edge. NAI-fnet replaces a table with a few
kilobytes of formulas, trained on the same wind-tunnel measurements, that carry on past the last measured Mach
number.
A model of a modern wide-body airliner in a transonic wind tunnel: its angle of attack, its tail setting and the
flow follow the test points; past Mach 0.85 a shock grows on the wing, the drag rises, and the chip says it is
beyond its data while it predicts.
Loading the simulator…
The aircraft is an illustration of the NASA Common Research Model as tested (wing, body and tail, no engines); every angle, Mach number and drag value comes from NASA's National Transonic Facility Test 197. The plot shows each test run as a sweep of the angle of attack.
Beyond the last measured Mach number
659 measured points at Mach 0.70 to 0.85 to learn; 155 points of other runs in that range, and 225 points at Mach 0.86 and 0.87 to check. Inputs: angle of attack, Mach, Reynolds number, dynamic pressure, tail setting.
| model | drag error inside | drag error beyond | lift error beyond | code for the drag |
|---|---|---|---|---|
| NAI-fnet | 14.2 counts | 27.8 counts | 0.028 | 21 KB, 2.3 µs |
| tuned LightGBM | 21.4 counts | 42.8 counts | 0.021 | 496 KB, 14 µs |
| MLP 32×32 | 33.3 counts | 41.9 counts | 0.035 | 11 KB, 0.7 µs |
| a simple look-up table of the same points | 92.7 counts | 205.8 counts | 0.077 | 659 values |
- 1.5×more accurate drag beyond the measured Machthan tuned boosting and a small MLP
- 1.5×more accurate drag inside the measured rangethan tuned boosting (21.4 counts)
- 24×smaller code than tuned boosting21 KB of C for the drag
- 0on fnet_in_range() beyond the datathe chip says so while it predicts
RMSE; a drag count is 0.0001 of the drag coefficient. Registered before the run, 10.11.2026 (SHA-256
18f06eac…bd4c): four of five hypotheses held.
The one that failed: beyond the measured Mach, boosting predicted the
lift better (0.021 against 0.028).
The table interpolates between the measured points of the same Reynolds number
and tail setting; a production table would sit on a regular grid built by aerodynamicists.
Data: NASA Common Research Model, National Transonic Facility Test 197 (commonresearchmodel.larc.nasa.gov), a US Government work; NASA is acknowledged as the source and does not endorse this page. The excerpt in fnet/aircraft.json is adapted (drag in counts, the models' predictions added).
Compared with what goes on a chip today
| NAI-fnet | polynomial or lookup table | tree ensemble (LightGBM, XGBoost) | small neural network | one symbolic formula | |
|---|---|---|---|---|---|
| accuracy inside the data | on tables, behind tuned boosting (by 22 % on average over four registered tests); on the motor and the airliner, ahead | suits 1–3 inputs | the highest | high | error about 23 % higher than NAI-fnet's (four suites, compared after the tests) |
| beyond the data | no singularities; median error below boosting's in three of four registered tests, about equal pooled | clamped or a straight line | flat: the edge value | no guarantee; the best beyond the data in two registered tests | no guarantee |
| code size | a few to tens of KB | KB, grows with inputs | hundreds of KB | 4–40 KB | under 1 KB |
| can be read and reviewed | yes: formulas and their weights | yes | no | no | yes |
| trust signal at run time | range monitor | — | — | — | — |
Boosting and MLP columns: measured by the same method on the registered tables and on 46 development tables (median 39× smaller and 4.9× faster than LightGBM with default settings). The symbolic-formula column: PySR, one formula, 120 seconds a table, run on the registered tables after the tests. Details on request.
Built to be certified
The code
- deterministic C99: no dynamic memory, no recursion, no library beyond
math.h - MISRA C:2012 checked; the one advisory deviation is documented
- the compiled code gives the model's numbers bit for bit, checked on every release
- float or double, chosen at compile time
The model
fnet_in_range(): is the input inside the data the model was built on- a bounded output and no singularities, by construction
- every neuron is a formula an engineer can read and check against physics
- a model report: scope, accuracy inside and at the edges, the formulas and their weights
A pilot on your data
Send a table, or describe the signal you need on the device.
You get the C code, the model
report and a verification of the code against the model, on data held out before the work begins.
- virtual sensors: torque, temperature, state of charge, flow
- sensor calibration with several interacting inputs
- surrogates of simulations and aerodynamic tables that must run in a control loop