Example #1
0
def test_eval():
    def f1(x):
        return x

    def f2(x, y):
        return x + y

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    pos1 = 3
    pos2 = [3, 4]

    assert (ad1._eval(pos1, wrt_variables=False).val == pos1)
    assert (ad1._eval(pos1, wrt_variables=False).der == 1)
    assert (ad1._eval(pos1, wrt_variables=False).der2 == 0)
    assert (ad1._eval(pos1, wrt_variables=True).val == pos1)
    assert (ad1._eval(pos1, wrt_variables=True).der == 1)
    assert (ad1._eval(pos1, wrt_variables=True).der2 == 0)

    assert (ad2._eval(pos2, wrt_variables=False).val == pos2[0] + pos2[1])
    assert (ad2._eval(pos2, wrt_variables=False).der == 2)
    assert (ad2._eval(pos2, wrt_variables=False).der2 == 0)
    assert (ad2._eval(pos2, wrt_variables=True).val == pos2[0] + pos2[1])
    assert (all(ad2._eval(pos2, wrt_variables=True).der == [1, 1]))
    assert (all(ad2._eval(pos2, wrt_variables=True).der2 == [0, 0]))
Example #2
0
def test_divide_add_simple():
    alpha = 2
    pos = 2

    def f1(x):
        return alpha / x + 3

    def f2(x):
        return 3 + alpha / x

    def f3(x):
        return x / alpha + 3

    def f4(x):
        return 3 + x / alpha

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)
    ad3 = pydif.autodiff(f3)
    ad4 = pydif.autodiff(f4)

    assert (ad1.get_val(pos) == 4)
    assert (ad2.get_val(pos) == 4)
    assert (ad3.get_val(pos) == 4)
    assert (ad4.get_val(pos) == 4)

    assert (ad1.get_der(pos) == -0.5)
    assert (ad2.get_der(pos) == -0.5)
    assert (ad3.get_der(pos) == 0.5)
    assert (ad4.get_der(pos) == 0.5)

    assert (ad1.get_der(pos, order=2) == 0.5)
    assert (ad2.get_der(pos, order=2) == 0.5)
    assert (ad3.get_der(pos, order=2) == 0)
    assert (ad4.get_der(pos, order=2) == 0)
Example #3
0
def test_composite():
    pos = (1, 2, 3)

    def f1(x, y, z):
        return (1 / (x * y * z)) + el.sin((1 / x) + (1 / y) + (1 / z))

    def f2(x, y, z):
        return (1 / (x * y * z))

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    expected_val = (1 / 6) + np.sin(11 / 6)

    assert (ad1.get_val(pos) == expected_val)

    der1 = -(1 / 6) - np.cos(11 / 6)  #d/dx
    der2 = -(1 / 12) - (np.cos(11 / 6) / 4)  #d/dy
    der3 = -(1 / 18) - (np.cos(11 / 6) / 9)  #d/dz

    assert (np.allclose(ad1.get_der(pos, wrt_variables=True),
                        [der1, der2, der3]))

    assert (ad2.get_val(pos) == 1 / (1 * 2 * 3))
    #http://www.wolframalpha.com/input/?i=d%2Fda+(1%2F(x(a)*y(a)*z(a))
    expected_der = -((2 * 3 + 1 * 3 + 1 * 2) / ((1**2) * (2**2) * (3**2)))
    assert (np.isclose(float(ad2.get_der(pos)), expected_der))

    der2_1 = 2 / (1 * 2 * 3)  #d/dx^2
    der2_2 = 2 / (1 * ((2)**3) * 3)  #d/dy^2
    der2_3 = 2 / (1 * 2 * ((3)**3))  #d/dz^2
    assert (np.allclose(ad2.get_der(pos, wrt_variables=True, order=2),
                        [der2_1, der2_2, der2_3]))
Example #4
0
def test_multiply_add_simple():
    alpha = 2
    pos = 2

    def f1(x):
        return alpha * x + 3

    def f2(x):
        return x * alpha + 3

    def f3(x):
        return 3 + x * alpha

    def f4(x):
        return 3 + alpha * x

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)
    ad3 = pydif.autodiff(f3)
    ad4 = pydif.autodiff(f4)

    assert (ad1.get_val(pos) == 7)
    assert (ad2.get_val(pos) == 7)
    assert (ad3.get_val(pos) == 7)
    assert (ad4.get_val(pos) == 7)

    assert (ad1.get_der(pos) == 2)
    assert (ad2.get_der(pos) == 2)
    assert (ad3.get_der(pos) == 2)
    assert (ad4.get_der(pos) == 2)

    assert (ad1.get_der(pos, order=2) == 0)
    assert (ad1.get_der(pos, order=2) == 0)
    assert (ad1.get_der(pos, order=2) == 0)
    assert (ad1.get_der(pos, order=2) == 0)
Example #5
0
def test_init():
    def f1(x):
        return x

    def f2(x, y):
        return x + y

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    assert (ad1.func == f1)
    assert (ad2.func == f2)
    assert (ad1.num_params == 1)
    assert (ad2.num_params == 2)
Example #6
0
    def BFGS(self,
             init_pos,
             max_iters=100,
             precision=10**-8,
             return_hist=False):
        #set original values
        coord = init_pos

        hist = [coord]  #preallocate array

        #set inital conditions
        s = 0
        iterations = 0
        step = 10000
        B = np.identity(self.num_params)
        dfdx = autodiff(self.func)

        #set conditions for while loop
        while ((iterations <= max_iters) and (step >= precision)):
            s = np.linalg.solve(
                B, -dfdx.get_der(coord, wrt_variables=True))  #step
            step = np.linalg.norm(s)  #step size
            y = dfdx.get_der(coord + s, wrt_variables=True) - dfdx.get_der(
                coord, wrt_variables=True)  #new y
            coord = coord + s  #new coord
            B = B + self.delta_B(y, s, B)  #get new B
            iterations += 1
            hist.append(coord)
        hist = np.array(hist)

        if return_hist:
            return coord, hist
        else:
            return coord
Example #7
0
def test_derorder():
    def f1(x):
        return x

    ad1 = pydif.autodiff(f1)

    assert (ad1.get_der(2, order=1) == 1)
    assert (ad1.get_der(2, order=2) == 0)
    with pytest.raises(NotImplementedError):
        ad1.get_der(2, order=3)
Example #8
0
def test_get_val():
    def f1(x):
        return x

    def f2(x, y):
        return x, y

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    pos1 = 3
    pos2 = [3, 4]
    dir1 = [1]
    dir2 = [0, 1]

    assert (ad1.get_val(pos1, direction=None) == pos1)
    assert (ad1.get_val(pos1, direction=dir1) == pos1)

    assert (ad2.get_val(pos2, direction=None) == pos2)
    assert (ad2.get_val(pos2, direction=dir2) == pos2[1])
Example #9
0
def test_check_dim():
    def f1(x):
        return x

    def f2(x, y):
        return x + y

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    with pytest.raises(ValueError):
        ad1._check_dim([0, 0])
    ad1._check_dim([0])
    ad1._check_dim(0)

    with pytest.raises(ValueError):
        ad2._check_dim([0])
    with pytest.raises(ValueError):
        ad2._check_dim(0)
    ad2._check_dim([0, 0])
Example #10
0
def test_get_der2():
    def f1(x):
        return x

    def f2(x, y):
        return x, y

    ad1 = pydif.autodiff(f1)
    ad2 = pydif.autodiff(f2)

    pos1 = 3
    pos2 = [3, 4]
    dir1 = [1]
    dir2 = [0, 1]

    assert (ad1.get_der(pos1, direction=None, order=2) == 0)
    assert (ad1.get_der(pos1, direction=dir1, order=2) == 0)

    assert (ad2.get_der(pos2, direction=None, order=2) == [0, 0])
    assert (ad2.get_der(pos2, direction=dir2, order=2) == 0)
Example #11
0
def test_enforce_unitvector():
    def f1(x):
        return x

    dir1 = np.array([1])
    dir2 = np.array([0.5])
    dir3 = np.array([0, 1])
    dir4 = np.array([1, -1])
    dir5 = np.array([0, 0])

    ad1 = pydif.autodiff(f1)

    assert (np.isclose(ad1._enforce_unitvector(dir1), np.array([1])))
    assert (np.isclose(ad1._enforce_unitvector(dir2), np.array([1])))
    assert (all(np.isclose(ad1._enforce_unitvector(dir3), np.array([0, 1]))))
    assert (all(
        np.isclose(ad1._enforce_unitvector(dir4),
                   np.array([np.sqrt(1 / 2), -np.sqrt(1 / 2)]))))

    with pytest.raises(ValueError):
        ad1._enforce_unitvector(dir5)
Example #12
0
    def gradient_descent(self,
                         init_pos,
                         step_size=0.1,
                         max_iters=100,
                         precision=0.001,
                         return_hist=False):
        num_params = len(signature(self.func).parameters)
        badDimentionsMsg = 'poorly formatted initial position. should be of length {}.'.format(
            num_params)
        if num_params != len(init_pos):
            raise ValueError(badDimentionsMsg)

        cur_pos = init_pos
        iters = 0
        dfdx = autodiff(self.func)
        val = dfdx.get_val(init_pos)

        if isinstance(val, Iterable):
            raise ValueError(
                "The optimize class only optimizes scalar valued functions")

        # pre allocate history array
        hist = [cur_pos]
        prev_step_size = 100 + precision
        while (prev_step_size > precision and iters < max_iters):
            jac = dfdx.get_der(cur_pos, wrt_variables=True)
            prev_pos = cur_pos
            cur_pos = cur_pos - step_size * jac
            prev_step_size = np.linalg.norm(abs(cur_pos - prev_pos))
            iters += 1
            hist.append(cur_pos)  #store history
        np.array(hist)

        if return_hist:
            return cur_pos, hist
        else:
            return cur_pos
Example #13
0
 def newton(self,
            init_pos,
            step_size=0.1,
            max_iters=100,
            precision=0.001,
            return_hist=False):
     num_params = len(signature(self.func).parameters)
     badDimentionsMsg = 'poorly formatted initial position. should be of length {}.'.format(
         num_params)
     if num_params != len(init_pos):
         raise ValueError(badDimentionsMsg)
     cur_pos = init_pos
     iters = 0
     dfdx = autodiff(self.func)
     val = dfdx.get_val(init_pos)
     # if isinstance(val, Iterable):
     #     raise ValueError("The optimize class only optimizes scalar valued functions")
     #preallocate arrays
     hist = [cur_pos]
     #set inital conditions
     iters = 0
     s_k = 0
     step = 10000
     #define conditions to break loop
     while ((iters <= max_iters) and (np.linalg.norm(step) >= precision)):
         step = np.linalg.solve(
             dfdx.get_der(cur_pos, wrt_variables=True, order=1),
             -self.func(*cur_pos))
         cur_pos = cur_pos + step
         iters += 1
         hist.append(cur_pos)
     hist = np.array(hist)
     if return_hist:
         return cur_pos, hist
     else:
         return cur_pos
Example #14
0
import numpy as np
import sys
import os
sys.path.append(os.path.join(os.getcwd(), 'code', 'pydif'))
from pydif.pydif import autodiff
from pydif.elementary import elementary as el


#adapted from lecture 9 slides from CS207
def f(x):
    return x - el.exp(-2.0 * el.sin(4.0 * x) * el.sin(4.0 * x))


dfdx = autodiff(f)

# Start Newton algorithm
xk = 1.0  # Initial guess
tol = 1.0e-08  # Some tolerance
max_it = 100  # Just stop if a root isn't found after 100 iterations

root = None  # Initialize root
for k in range(max_it):
    delta_xk = -f(xk) / dfdx.get_der(xk, wrt_variables=True)[
        0]  #there is only 1 partial derivative that we care about
    if (abs(delta_xk) <= tol):  # Stop iteration if solution found
        root = xk + delta_xk
        print("Found root at x = {0:17.16f} after {1} iteratons.".format(
            root, k + 1))
        break
    print("At iteration {0}, Delta x = {1:17.16f}".format(k + 1, delta_xk))
    xk += delta_xk  # Update xk