itt-ustutt / num-dual

Generalized (hyper-) dual numbers in rust
Other
53 stars 6 forks source link

There's a bug in jacobian #69

Closed powei-lin closed 1 year ago

powei-lin commented 1 year ago

This should work, but it shows, TypeError: argument 'f' must return a list. For scalar functions use 'first_derivative' or 'gradient' instead.

def f(x, y):
    return np.array([x[0], y[0]*3])
x = np.array([1], dtype=np.float64)
pf = partial(f, x)
y = np.array([2], dtype=np.float64)
print(jacobian(pf, y))

Change to gradient. Got TypeError: argument 'f' must return a scalar. For vector functions use 'jacobian' instead.

def f(x, y):
    return np.array([x[0], y[0]*3])
x = np.array([1], dtype=np.float64)
pf = partial(f, x)
y = np.array([2], dtype=np.float64)
print(gradient(pf, y))

But after adding a zero y to the first return then it works.

def f(x, y):
    return np.array([x[0]+0*y[0], y[0]*3])
x = np.array([1], dtype=np.float64)
pf = partial(f, x)
y = np.array([2], dtype=np.float64)
print(jacobian(pf, y))
prehner commented 1 year ago

Thank you for the feedback! The problem here is that in your first example x[0] and y[0] have different data types (a float and a dual number). In that case the returned array can't be converted in the Python/Rust interface which produces that error message.

The most pragmatic fix is exactly what you are doing in the third example because it ensures that all data types are the same. The error message could me more precise, though!