def test_jacobian():
    g = sad.AutoDiff('g', 3)
    h = sad.AutoDiff('h', -4)
    i = sad.AutoDiff('i', 7)

    # Create functions
    f1 = g + 4
    f2 = h**2 + 2 * h - 12

    variables = ['g', 'h', 'i']
    functions = [f1, f2]
    jacob = sad.jacobian(variables, functions)
    test = np.array([[1., 0., 0.], [0., -6., 0.]])
    for row in range(jacob.shape[0]):
        for col in range(jacob.shape[1]):
            assert jacob[row, col] == pytest.approx(test[row, col])

    functions = sad.AutoDiffVector([f1, f2])
    jacob = sad.jacobian(variables, functions)
    test = np.array([[1., 0., 0.], [0., -6., 0.]])
    for row in range(jacob.shape[0]):
        for col in range(jacob.shape[1]):
            assert jacob[row, col] == pytest.approx(test[row, col])

    with pytest.raises(ValueError):
        sad.jacobian('incorrect', 'input')
def test_vector_add():
    f1 = sad.AutoDiff('x', 1)
    f2 = sad.AutoDiff('y', 1)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = sad.AutoDiffVector([f1, f2]) + 2
    vec1_other = sad.AutoDiffVector([f1, f2]) + other
    vec2 = sad.vectorize(['x', 'y'], [1, 1]) + 2
    vec2_other = sad.vectorize(['x', 'y'], [1, 1]) + other
    f3 = f1 + 2
    f4 = f1 + other
    #
    der = f3.der['x']
    val = f3.val
    der_other = f4.der['x']
    val_other = f4.val
    do_vector_tests(vec1, vec1_other, vec2, vec2_other, der, der_other, val,
                    val_other)
def test_vector_rdiv():
    f1 = sad.AutoDiff('x', 2)
    f2 = sad.AutoDiff('y', 2)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = 3 / sad.AutoDiffVector([f1, f2])
    vec1_other = other / sad.AutoDiffVector([f1, f2])
    vec2 = 3 / sad.vectorize(['x', 'y'], [2, 2])
    vec2_other = other / sad.vectorize(['x', 'y'], [2, 2])
    f3 = 3 / f1
    f4 = other / f1
    #
    der = f3.der['x']
    val = f3.val
    der_other = f4.der['x']
    val_other = f4.val
    do_vector_tests(vec1, vec1_other, vec2, vec2_other, der, der_other, val,
                    val_other)
def test_vector_div():
    f1 = sad.AutoDiff('x', 2)
    f2 = sad.AutoDiff('y', 2)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = sad.AutoDiffVector([f1, f2]) / 3
    vec1_other = sad.AutoDiffVector([f1, f2]) / other
    vec2 = sad.vectorize(['x', 'y'], [2, 2]) / 3
    vec2_other = sad.vectorize(['x', 'y'], [2, 2]) / other
    f3 = f1 / 3
    f4 = f1 / other
    #
    der = f3.der['x']
    val = f3.val
    der_other = f4.der['x']
    val_other = f4.val
    do_vector_tests(vec1, vec1_other, vec2, vec2_other, der, der_other, val,
                    val_other)
def test_vector_rsub():
    f1 = sad.AutoDiff('x', 1)
    f2 = sad.AutoDiff('y', 1)
    other = sad.AutoDiff('z', 1)
    # do operations on objects
    vec1 = 1 - sad.AutoDiffVector([f1, f2])
    vec1_other = other - sad.AutoDiffVector([f1, f2])
    vec2 = 1 - sad.vectorize(['x', 'y'], [1, 1])
    vec2_other = other - sad.vectorize(['x', 'y'], [1, 1])
    f3 = 1 - f1
    f4 = other - f1
    #
    der = f3.der['x']
    val = f3.val
    der_other = f4.der['x']
    val_other = f4.val
    do_vector_tests(vec1, vec1_other, vec2, vec2_other, der, der_other, val,
                    val_other)
def test_vector_log10():
    f1 = sad.AutoDiff('x', 2)
    f2 = sad.AutoDiff('y', 2)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = sad.log(sad.AutoDiffVector([f1, f2]), base=10)
    vec2 = sad.log(sad.vectorize(['x', 'y'], [2, 2]), base=10)
    f3 = sad.log(f1, base=10)
    #
    der = f3.der['x']
    val = f3.val
    do_vector_tests_no_other(vec1, vec2, der, val)
def test_vector_rpow():
    f1 = sad.AutoDiff('x', 2)
    f2 = sad.AutoDiff('y', 2)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = 3.0**sad.AutoDiffVector([f1, f2])
    vec2 = 3.0**sad.vectorize(['x', 'y'], [2, 2])
    f3 = 3.0**f1
    #
    der = f3.der['x']
    val = f3.val
    do_vector_tests_no_other(vec1, vec2, der, val)
def test_vector_tanh():
    f1 = sad.AutoDiff('x', 0.5)
    f2 = sad.AutoDiff('y', 0.5)
    # do operations on objects
    vec1 = sad.tanh(sad.AutoDiffVector([f1, f2]))
    vec2 = sad.tanh(sad.vectorize(['x', 'y'], [0.5, 0.5]))
    f3 = sad.tanh(f1)
    #
    der = f3.der['x']
    val = f3.val
    do_vector_tests_no_other(vec1, vec2, der, val)
    with pytest.raises(AttributeError):
        x1 = sad.AutoDiff('x', 1)
        sad._tanhV(x1)
def test_vector_ln():
    f1 = sad.AutoDiff('x', 2)
    f2 = sad.AutoDiff('y', 2)
    other = sad.AutoDiff('z', 2)
    # do operations on objects
    vec1 = sad.log(sad.AutoDiffVector([f1, f2]))
    vec2 = sad.log(sad.vectorize(['x', 'y'], [2, 2]))
    f3 = sad.log(f1)
    #
    der = f3.der['x']
    val = f3.val
    do_vector_tests_no_other(vec1, vec2, der, val)
    with pytest.raises(AttributeError):
        x1 = sad.AutoDiff('x', 1)
        sad._logV(x1)
def test_vector_inputlist_duplicate_var():
    with pytest.raises(ValueError):
        x = sad.AutoDiff('x', 2)
        y = sad.AutoDiff('x', 2)
        x1 = sad.AutoDiffVector([x, y])
def test_vector_inputlist_not_autodiff():
    with pytest.raises(ValueError):
        x = sad.AutoDiff('x', 2)
        y = 'asd'
        x1 = sad.AutoDiffVector([x, y])
def test_vector_input_two_args():
    with pytest.raises(TypeError):
        x1 = sad.AutoDiffVector('x', 1)