### Question:
NormalizeRows extends SingleParentVariable<Matrix> { @Override public Matrix gradient(Variable<?> parent, ComputationContext ctx) { double[] parentData = ctx.data(parent).data(); double[] gradientData = ctx.gradient(this).data(); double[] result = new double[parentData.length]; int rows = this.rows; int cols = this.cols; for (int row = 0; row < rows; row++) { double l2Squared = 0; for (int col = 0; col < cols; col++) { int elementIndex = row * cols + col; l2Squared += parentData[elementIndex] * parentData[elementIndex]; } double l2 = Math.sqrt(l2Squared); double l2Cubed = l2 * l2Squared; for (int col = 0; col < cols; col++) { int elementIndex = row * cols + col; for (int gradCol = 0; gradCol < cols; gradCol++) { if (col == gradCol) { result[elementIndex] += gradientData[elementIndex] * (l2Squared - parentData[elementIndex] * parentData[elementIndex]) / l2Cubed; } else { result[elementIndex] -= gradientData[row * cols + gradCol] * (parentData[elementIndex] * parentData[row * cols + gradCol]) / l2Cubed; } } } } return new Matrix(result, this.rows, this.cols); } NormalizeRows(Variable<Matrix> matrix); @Override Matrix apply(ComputationContext ctx); @Override Matrix gradient(Variable<?> parent, ComputationContext ctx);  }### Answer:
@Test void testGradient() { double[] data = new double[] { 3, 4, 1, 0, 0, 1 }; Weights<Matrix> w = new Weights<>(new Matrix(data, 3, 2)); Variable<Matrix> normalizeRows = new NormalizeRows(w); finiteDifferenceShouldApproximateGradient(w, new ElementSum(List.of(normalizeRows))); }