def test_jacobian_exception():
    x = AD.AD(3.0)
    y = AD.AD(2.0, [0.0, 1.0])
    with pytest.raises(Exception, match="Incorrect dimension"):
        assert AD.AD.get_jacobian([x, y])
    with pytest.raises(TypeError, match="Invalid input type: not a function"):
        assert AD.AD.get_jacobian([x, 3.0])
    with pytest.raises(Exception, match="Empty list of functions"):
        assert AD.AD.get_jacobian([])
def test_jacobian():
    x = AD.AD(3.0, [1.0, 0.0, 0.0])
    y = AD.AD(2.0, [0.0, 1.0, 0.0])
    z = AD.AD(1.0, [0.0, 0.0, 1.0])
    vals, ders = AD.AD.get_jacobian([x * y, x + y, z, unary.sin(x)])
    test_jac = np.array([[2.0, 3.0, 0.0], [1.0, 1.0, 0.0], [0.0, 0.0, 1.0],
                         [np.cos(3.0), 0.0, 0.0]])
    assert (vals[0] == 6.0)
    assert (vals[2] == 1.0)
    assert (np.array_equal(ders, test_jac))
def test_add_radd_mult_rmult():
    x = AD.AD(2.0)
    alpha = 2.0
    beta = 3.0

    functions = []
    functions.append(('alpha * x + beta', alpha * x + beta))
    functions.append(('x * alpha + beta', x * alpha + beta))
    functions.append(('beta + alpha * x', beta + alpha * x))
    functions.append(('beta + x * alpha', beta + x * alpha))

    for (name, val) in functions:
        assert (val.val == 7)
        assert (val.der == 2)
Exemple #4
0
def tanh(x):
    """ Calculate hyperbolic tangent of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: hyperbolic tangent of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> print(tanh(x))
    AD(0.9640275800758169, [0.07065082 0.        ])
    """
    try:
        return ad.AD(np.tanh(x.val), x.der/np.cosh(x.val)**2)
    except AttributeError:
        return np.tanh(x)
Exemple #5
0
def arctan(x):
    """ Calculate inverse tangent of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: inverse tangent of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2)
    >>> print(arctan(x))
    AD(1.1071487177940906, [0.2])
    """
    try:
        return ad.AD(np.arctan(x.val), x.der/(1+x.val**2))
    except AttributeError:
        return np.arctan(x)
Exemple #6
0
def logistic(x):
    """ Return the logistic of an AD object, integer, or float

    INPUTS
    =======
    x: the AD object, int, or float

    RETURNS
    ========
    result: 1/(1+e^(-x))

    EXAMPLES
    =========
    >>> x = ad.AD(4.0)
    >>> print(logistic(x))
    AD(0.9820137900379085, [0.0183095])
    """
    try:
        return ad.AD(1/(1+np.exp(-x.val)), np.exp(-x.val)*x.der/(1+np.exp(-x.val))**2)
    except AttributeError:
        return 1/(1+np.exp(-x))
Exemple #7
0
def log(x, base):
    """ Calculate the logarithm of an AD object, integer, or float of given base
    
    INPUTS
    =======
    x: the AD object, int, or float
    base: logarithm base
    
    RETURNS
    ========
    result: given base logarithm of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(4.0)
    >>> print(log(x,2))
    AD(2.0, [0.36067376])
    """
    try:
        return ad.AD(math.log(x.val, base), x.der/(x.val*np.log(base)))
    except AttributeError:
        return math.log(x,base)
Exemple #8
0
def ln(x):
    """ Calculate the natural base logarithm of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: natural logarithm of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(ln(x*y))
    AD(1.791759469228055, [0.5        0.33333333])
    """
    try:
        return ad.AD(np.log(x.val), x.der/x.val)
    except AttributeError:
        return np.log(x)
Exemple #9
0
def cosh(x):
    """ Calculate hyperbolic cosine of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: hyperbolic cosine of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(cosh(x*y))
    AD(201.7156361224559, [605.13947211 403.42631474])
    """
    try:
        return ad.AD(np.cosh(x.val), x.der*np.sinh(x.val))
    except AttributeError:
        return np.cosh(x)
Exemple #10
0
def sinh(x):
    """ Calculate hyperbolic sine of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: hyperbolic sine of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(sinh(x+y))
    AD(74.20321057778875, [74.20994852 74.20994852])
    """
    try:
        return ad.AD(np.sinh(x.val), x.der*np.cosh(x.val))
    except AttributeError:
        return np.sinh(x)
Exemple #11
0
def sin(x):
    """ Calculate sine of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: sine of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(sin(x*y))
    AD(-0.27941549819892586, [2.88051086 1.92034057])
    """
    try:
        return ad.AD(np.sin(x.val), x.der*np.cos(x.val))
    except AttributeError:
        return np.sin(x)
Exemple #12
0
def cos(x):
    """ Calculate cosine of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: cosine of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(cos(x*y))
    AD(0.9601702866503661, [0.83824649 0.558831  ])
    """
    try:
        return ad.AD(np.cos(x.val), -x.der*np.sin(x.val))
    except AttributeError:
        return np.cos(x)
Exemple #13
0
def arccos(x):
    """ Calculate inverse cosine of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or float
    
    RETURNS
    ========
    result: inverse cosine of x
    
    EXAMPLES
    =========
    >>> x = ad.AD(0.5)
    >>> print(arccos(x))
    AD(1.0471975511965976, [-1.15470054])
    """
    try:
        if x.val<=-1 or x.val>=1:
            raise Exception("X out of domain")
        return ad.AD(np.arccos(x.val), -x.der/np.sqrt(1-x.val**2))
    except AttributeError:
        return np.arccos(x)
Exemple #14
0
def exp(x):
    """ Calculate the exponential of the input AD object, integer, or float
    
    INPUTS
    =======
    x: input value, an AD object, int, or flot
    
    RETURNS
    ========
    result: exponential of x

    EXAMPLES
    =========
    >>> x = ad.AD(2.0, [1.0,0.0])
    >>> y = ad.AD(3.0, [0.0,1.0])
    >>> print(exp(x))
    AD(7.38905609893065, [7.3890561 0.       ])
    >>> print(exp(x*y))
    AD(403.4287934927351, [1210.28638048  806.85758699])
    """
    try:
        return ad.AD(np.exp(x.val), np.exp(x.val)*x.der)
    except AttributeError:
        return np.exp(x)
def test_add_reg_AD():
    x = 2 + AD.AD(1.0)
    y = AD.AD(3.0, 1.0)
    assert (x == y)
def test_add_AD_reg():
    x = AD.AD(2.0) + 3
    y = AD.AD(5.0, 1.0)
    assert (x == y)
def test_add_AD_AD():
    x = AD.AD(2.0) + AD.AD(3.0)
    y = AD.AD(5.0, 2.0)
    assert (x == y)
def test_identity():
    x = AD.AD(3.0)
    eq = (2 * x) / (2 * x)
    y = AD.AD(1.0, 0.0)
    assert (eq == y)
def test_mult_reg_AD():
    x = 2 * AD.AD(1.0)
    y = AD.AD(2.0, 2.0)
    assert (x == y)
def test_invalid_init():
    x = AD.AD(3.0)
    with pytest.raises(TypeError, match="Invalid input type"):
        assert AD.AD(x)
def test_sub_AD_reg():
    x = AD.AD(2.0) - 1.0
    y = AD.AD(1.0, 1.0)
    assert (x == y)
def test_mult_AD_AD():
    x = AD.AD(2.0) * AD.AD(1.0)
    y = AD.AD(2.0, 3.0)
    assert (x == y)
def test_sub_AD_AD():
    x = AD.AD(2.0) - AD.AD(1.0)
    y = AD.AD(1.0, 0.0)
    assert (x == y)
def test_eq():
    x = AD.AD(3.0)
    y = 3.0
    assert (x == y)
def test_sub_reg_AD():
    x = 2 - AD.AD(1.0)
    y = AD.AD(1.0, -1.0)
    assert (x == y)
def test_ne():
    x = AD.AD(3.0, [1.0, 0.0])
    y = AD.AD(3.0)
    assert (x != y)
def test_mult_AD_reg():
    x = AD.AD(2.0) * 2.0
    y = AD.AD(4.0, 2.0)
    assert (x == y)
def test_neg():
    x = AD.AD(3.0, [1.0, 0.0])
    y = AD.AD(2.0, [0.0, 1.0])
    f = -x * y
    assert (f.val == -6.0)
    assert (np.array_equal(f.der, np.array([-2.0, -3.0])))
def test_truediv_AD_AD():
    x = AD.AD(6.0) / AD.AD(3.0)
    y = AD.AD(2.0, -1 / 3)
    assert (x == y)
def test_linear_combos():
    x = AD.AD(3.0)
    eq = x**2 + x
    y = AD.AD(12.0, 7.0)
    assert (eq == y)