Core mechanism
An active scalar stores its numerical value and a tape-node identity. Operators create new nodes, while the recorder retains enough dependency information to push output adjoints back into the input vector.
Java records each ADouble operation into NablaTensor's tape, then displays the tape's forward values and reverse adjoints.
Difference of squares, recorded as binary operations.
This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.
import com.nablatensor.engine.ADouble;
import com.nablatensor.engine.AadOpEnum;
import com.nablatensor.engine.AadRecorder;
import com.nablatensor.engine.AadTape;
public final class AdoubleRiskStudio {
private AdoubleRiskStudio() {}
public static void main(String[] args) {
AadTape tape = AadRecorder.record(rec -> {
ADouble x = rec.input("x", 5); ADouble y = rec.input("y", 3); rec.output(x.add(y)
.mul(x.sub(y)));
});
int n = tape.size();
double[] value = new double[n], adjoint = new double[n];
double[] input = tape.recordedInputs();
for (int i = 0; i < n; i++) {
int a = tape.argA(i), b = tape.argB(i);
AadOpEnum op = tape.op(i);
double va = a >= 0 ? value[a] : 0.0, vb = b >= 0 ? value[b] : 0.0;
double external = op == AadOpEnum.CONST ? tape.constant(i) : op == AadOpEnum.INPUT ? input[a] : 0.0;
value[i] = op.apply(va, vb, external);
}
adjoint[tape.outputNode()] = 1.0;
for (int i = n - 1; i >= 0; i--) {
final int a = tape.argA(i), b = tape.argB(i);
final double g = adjoint[i], va = a >= 0 ? value[a] : 0.0, vb = b >= 0 ? value[b] : 0.0, vi = value[i];
tape.op(i)
.propagate(va, vb, vi, g, new AadOpEnum.GradientSink() {
public void addA(double contribution) {
if (a >= 0) adjoint[a] += contribution;
}
public void addB(double contribution) {
if (b >= 0) adjoint[b] += contribution;
}
});
}
for (int i = 0; i < n; i++) {
String name = "";
if (tape.op(i) == AadOpEnum.INPUT) name = tape.inputName(tape.argA(i));
System.out.println("NODE|" + i + "|" + tape.op(i) + "|" + tape.argA(i) + "|" + tape.argB(i)
+ "|" + value[i] + "|" + adjoint[i] + "|" + tape.isActive(i) + "|" + name + "|" + tape.constant(i));
}
System.out.println("OUT|" + value[tape.outputNode()]);
}
}
ADouble is the bridge between ordinary valuation arithmetic and a graph that can later produce sensitivities.
An active scalar stores its numerical value and a tape-node identity. Operators create new nodes, while the recorder retains enough dependency information to push output adjoints back into the input vector.
Use active values where market inputs enter a payoff or model. Leave fixed configuration and non-risk-bearing control values as ordinary Java values so the graph contains only economically meaningful differentiation paths.
Making every value active enlarges the tape and can create meaningless gradients. Factor naming and input selection remain a modelling decision.