def test_lt(): x = FuncInput(np.array([0, 3]), np.array([1])) y = FuncInput(np.array([1, 4]), np.array([1])) assert x < y, 'less-than function is not correct' xreal = 3 yreal = 4 assert xreal < yreal, 'less-than function is not correct'
def test_ge(): x = FuncInput(np.array([0, 3]), np.array([1])) y = FuncInput(np.array([1, 3]), np.array([1])) assert y >= x, 'greater-or-equal-than function is not correct' xreal = 3 yreal = 3 assert yreal >= xreal, 'greater-or-equal-than function is not correct'
def test_le(): x = FuncInput(np.array([0, 3]), np.array([1])) y = FuncInput(np.array([1, 3]), np.array([1])) assert x <= y, 'less-or-equal-than function is not correct' xreal = 3 yreal = 3 assert xreal <= yreal, 'less-or-equal-tha function is not correct'
def test_mul(): x = FuncInput(np.array([1]), np.array([1, 0])) y = FuncInput(np.array([2]), np.array([0, 1])) f = x * y assert f.value == 2, "mul function is not correct" assert (f.gradients == np.array([2, 1])).all(), "mul function is not correct"
def test_sub(): x = FuncInput(np.array([1]), np.array([1, 0])) y = FuncInput(np.array([2]), np.array([0, 1])) f = x - y assert f.value == [-1], "sub function is not correct" assert (f.gradients == np.array([1, -1])).all(), "sub function is not correct"
def test_gt(): x = FuncInput(np.array([0, 3]), np.array([1])) y = FuncInput(np.array([1, 4]), np.array([1])) assert y > x, 'greater-than function is not correct' xreal = 3 yreal = 4 assert yreal > xreal, 'greater-than function is not correct'
def test_add(): x = FuncInput(np.array([1]), np.array([1, 0])) y = FuncInput(np.array([2]), np.array([0, 1])) f = x + y assert f.value == [3], "add function is not correct" assert (f.gradients == np.array([1, 1])).all(), "add function is not correct"
def test_floordiv(): x = FuncInput(np.array([2]), np.array([1, 0])) y = FuncInput(np.array([-5]), np.array([0, 1])) f = y // x # f2 = y // 2 assert f.value == [-3], "floordiv function is not correct" assert (f.gradients == np.array( [1, 0])).all(), "floordiv function is not correct"
def test_logaddexp(): x = FuncInput(np.array([0]), np.array([1, 0])) y = FuncInput(np.array([1]), np.array([0, 1])) f = op.logaddexp(x, y) assert (abs(f.value - 1.31326169) < 1e-6).all(), "logaddexp function is not correct" assert (abs(f.gradients - np.array([0.26894142, 0.73105858])) < 1e-6).all(), "logaddexp function is not correct"
def test_logaddexp2(): x = FuncInput(np.array([2]), np.array([1, 0])) y = FuncInput(np.array([1]), np.array([0, 1])) f = op.logaddexp2(x, y) assert (abs(f.value - 2.32192809) < 1e-6).all(), "logaddexp2 function is not correct" assert (abs(f.gradients - np.array([1.15415603, 0.57707802])) < 1e-6).all(), "logaddexp2 function is not correct"
def test_pow(): x = FuncInput(np.array([2]), np.array([1, 0])) y = FuncInput(np.array([3]), np.array([0, 1])) f = x**3 f_2 = x**y assert f.value == [8], "pow function is not correct" assert (f.gradients == np.array([12, 0])).all(), "pow function is not correct" assert f_2.value == [8], "pow function is not correct"
def test_truediv(): x = FuncInput(np.array([1]), np.array([1, 0])) y = FuncInput(np.array([2]), np.array([0, 1])) f1 = x / y f2 = x / 2 assert f1.value == [0.5], "truediv function is not correct" assert (f1.gradients == np.array( [0.5, -0.25])).all(), "truediv function is not correct" assert f2.value == [0.5], "truediv function is not correct" assert (f2.gradients == np.array( [0.5, 0])).all(), "truediv function is not correct"
def test_abs(): x = FuncInput(np.array([-2]), np.array([1, 0])) f = abs(x) y = FuncInput(np.array([2]), np.array([1, 0])) f2 = abs(y) assert f.value == [2], "abs function is not correct" assert (f.gradients == np.array([-1, 0])).all(), "abs function is not correct" assert f2.value == [2], "abs function is not correct" assert (f2.gradients == np.array([1, 0])).all(), "abs function is not correct"
def test_arccos(): x = FuncInput(np.array([0.5]), np.array([1, 0])) f = op.arccos(x) assert (abs(f.value - (np.pi / 3)) < 1e-6).all(), 'arccos function is not correct' assert (abs(f.gradients - np.array([-(1 / math.sqrt(1 - 0.5**2)), 0])) < 1e-6).all(), 'arccos function not correct' with pytest.raises(AssertionError): x = FuncInput(np.array([1]), np.array([1, 0])) f = op.arccos(x) xreal = 0.5 freal = op.arccos(xreal) assert (abs(freal - (np.pi / 3)) < 1e-6).all(), 'arcsin function is not correct'
def test_arccosh(): x = FuncInput(np.array([2]), np.array([1, 0])) f = op.arccosh(x) assert (abs(f.value - np.arccosh(2)) < 1e-6).all(), 'arccosh function is not correct' assert (abs(f.gradients - np.array([1 / math.sqrt(3), 0])) < 1e-6).all(), 'arcosh function is not correct' with pytest.raises(AssertionError): x = FuncInput(np.array([1]), np.array([1, 0])) f = op.arccosh(x) xreal = 2 freal = op.arccosh(xreal) assert (abs(freal - np.arccosh(2)) < 1e-6).all(), 'arccosh function is not correct'
def test_arctanh(): x = FuncInput(np.array([0.5]), np.array([1, 0])) f = op.arctanh(x) assert (abs(f.value - np.arctanh(0.5)) < 1e-6).all(), 'arctanh function is not correct' assert (abs(f.gradients - np.array([1 / (1 - 0.5**2), 0])) < 1e-6).all(), 'arctanh function is not correct' with pytest.raises(AssertionError): x = FuncInput(np.array([1]), np.array([1, 0])) f = op.arctanh(x) xreal = 0.5 freal = op.arctanh(xreal) assert (abs(freal - np.arctanh(0.5)) < 1e-6).all(), 'arctanh function is not correct'
def gamma(x): """ Returns the gamma function of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value and gradients based on gamma function from scipy Examples ======= >>> x = FuncInput(np.array([1,4]),np.array([1])) >>> f = op.gamma(x) >>> f FuncInput([1., 6.], [0.63353918, 3.96259814]) """ if isinstance(x, FuncInput): new_vals = special.gamma(x.val_) new_ders = [x.ders_[i] * 2/(np.pi**0.5) * np.exp(special.digamma(x.val_)) for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return special.gamma(x)
def erf(x): """ Returns the error function of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on error function from scipy and gradients based on 2 * exp(-x**2) / sqrt(pi) * x' Examples ======= >>> x = FuncInput(np.array([1,20]),np.array([1])) >>> f = op.erf(x) >>> f FuncInput([0.84270079, 1.], [0.4151075, 0.]) """ if isinstance(x, FuncInput): new_vals = special.erf(x.val_) new_ders = [x.ders_[i] * 2/(np.pi**0.5) * np.exp(- (x.val_)**2) for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return special.erf(x)
def arctanh(x): """ Returns the arctanh of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on arcsinh(x) = log((1+x)/(1-x))/2 and gradients based on 1 / (1-x**2) * x' Examples ======= >>> x = FuncInput(np.array([0.5]),np.array([1,0])) >>> f = op.tanh(x) >>> f FuncInput([0.549306], [1.33333, 0.]) """ if isinstance(x, FuncInput): assert np.abs(x.val_) < 1, 'Input is outside the domain of arctanh or its derivative' new_val = np.arctanh(x.val_) new_ders = [(1/(1-x.val_**2)) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): assert abs(x) < 1, 'Input is outside the domain of arctanh or its derivative' return np.arctanh(x)
def arccosh(x): """ Returns the arccosh of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on arcsinh(x) = log(x + sqrt(x**2-1)) and gradients based on 1 / sqrt(x**2-1) * x' Examples ======= >>> x = FuncInput(np.array([2]),np.array([1,0])) >>> f = op.tanh(x) >>> f FuncInput([1.31695790], [0.57735027, 0.]) """ if isinstance(x, FuncInput): assert x.val_ > 1, 'Input is outside the domain of arccosh or its derivative' new_val = np.arccosh(x.val_) new_ders = [(1/sqrt((x.val_**2) - 1)) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): assert x >= 0, 'Input is outside the domain of arccosh' return np.arccosh(x)
def arcsinh(x): """ Returns the arcsinh of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on arcsinh(x) = log(x + sqrt(x**2+1)) and gradients based on 1 / sqrt(x**2+1) * x' Examples ======= >>> x = FuncInput(np.array([2]),np.array([1,0])) >>> f = op.tanh(x) >>> f FuncInput([0.88137359], [0.70710678, 0.]) """ if isinstance(x, FuncInput): new_val = np.arcsinh(x.val_) new_ders = [(1/sqrt(x.val_**2 + 1)) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): return np.arcsinh(x)
def tanh(x): """ Returns the tanh of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on tanh(x) = sinh(x) / cosh(x) and gradients based on 1 / cosh(x) ** 2 * x' Examples ======= >>> x = FuncInput(np.array([2]),np.array([1,0])) >>> f = op.tanh(x) >>> f FuncInput([0.9640276], [0.0706508, 0.]) """ if isinstance(x, FuncInput): new_val = np.tanh(x.val_) new_ders = [((1/np.cosh(x.val_)) ** 2) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): return np.tanh(x)
def arctan(x): """ Returns the arctan of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on arctan(x) and gradients based on 1/(1+x^2) * x' Examples ======= >>> x = FuncInput(np.array([0.5]),np.array([1,0])) >>> f = op.arcsin(x) >>> f FuncInput([0.7853982], [0.5, 0.]) """ if isinstance(x, FuncInput): new_val = np.arctan(x.val_) new_ders = [(1/(1 + x.val_**2)) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): return np.arctan(x)
def arccos(x): """ Returns the arccos of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on arccos(x) and gradients based on -1/sqrt(1-x^2) * x' Examples ======= >>> x = FuncInput(np.array([0.5]),np.array([1,0])) >>> f = op.arcsin(x) >>> f FuncInput([1.04719755], [-0.8660254, 0.]) """ if isinstance(x, FuncInput): assert x.val_ > -1 and x.val_ < 1, 'Input is outside the domain of arccos or its derivative' new_val = np.arccos(x.val_) new_ders = [(-(1/sqrt(1 - x.val_**2))) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): assert x >= -1 and x <= 1, 'Input is outside the domain of arccos' return np.arccos(x)
def tan(x): """ Returns the tan of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on tan(x) and gradients based on 1/(cos(x))^2 * x' Examples ======= >>> x = FuncInput(np.array([np.pi/3]),np.array([1,0])) >>> f = op.tan(x) >>> f FuncInput([1.73205081], [4.,0.]) """ if isinstance(x, FuncInput): new_vals = np.tan(x.val_) new_ders = [x.ders_[i] * (1/np.cos(x.val_))**2 for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return np.tan(x)
def cos(x): """ Returns the cos of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on cos(x) and gradients based on -sin(x) * x' Examples ======= >>> x = FuncInput(np.array([np.pi/3]),np.array([1,0])) >>> f = op.cos(x) >>> f FuncInput([0.5], [-0.8660254,0.]) """ if isinstance(x, FuncInput): new_vals = np.cos(x.val_) new_ders = [x.ders_[i] * (-np.sin(x.val_)) for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return np.cos(x)
def exp(x): """ Returns the exponential of FuncInput object. Parameters ======= FuncInput object or real number Returns ======= FuncInput object with value based on exp(x) and gradients based on exp'(x) = exp(x) * x Examples ======= >>> x = FuncInput(np.array([0]),np.array([1,0])) >>> f = op.exp(x) >>> f FuncInput([1], [1, 0]) """ if isinstance(x, FuncInput): new_vals = np.exp(x.val_) new_ders = [x.ders_[i] * np.exp(x.val_) for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return np.exp(x)
def floor(x): """ Returns the floor value of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value and gradients from x! based on gamma function from scipy Examples ======= >>> x = FuncInput(np.array([0,3]),np.array([1])) >>> f = op.tanh(x) >>> f Value: [0. 3.] Gradient(s): 0 """ if isinstance(x, FuncInput): new_vals = np.floor(x.val_) warnings.warn('Using zero as derivatives for floor function (technically not defined at non-integers)...') new_ders = [x.ders_[i] * 0 for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return np.floor(x)
def gammainc(x, alpha): # lower incomplete gamma function """ Returns the lower incomplete gamma function of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value and gradients based on gammainc function from scipy Examples ======= >>> f = op.gammainc(3,2) >>> f 0.8008517265285442 """ if isinstance(x, FuncInput): new_vals = special.gammainc(alpha, x.val_) new_ders = [x.ders_[i] * (x**(alpha-1))*exp(-x) for i in range(len(x.ders_))] return FuncInput(new_vals, new_ders) elif isinstance(x, numbers.Real): return special.gammainc(alpha, x)
def cosh(x): """ Returns the cosh of FuncInput object. Parameters ======= x: FuncInput object or real number Returns ======= FuncInput object with value based on sinh(x) = (exp(x) + exp(-x)) * 1/2 and gradients based on sinh(x) * x' Examples ======= >>> x = FuncInput(np.array([1]),np.array([1,0])) >>> f = op.cosh(x) >>> f FuncInput([1.54308063], [1.17520119, 0.]) """ if isinstance(x, FuncInput): new_val = np.cosh(x.val_) new_ders = [(np.sinh(x.val_)) * x_der for x_der in x.ders_] return FuncInput(new_val, new_ders) elif isinstance(x, numbers.Real): return np.cosh(x)