@@ -38,10 +38,46 @@ where
38
38
+ x2. powi ( 2 )
39
39
}
40
40
41
+ /// Derivative of Three-hump camel test function
42
+ pub fn threehumpcamel_derivative < T > ( param : & [ T ; 2 ] ) -> [ T ; 2 ]
43
+ where
44
+ T : Float + FromPrimitive ,
45
+ {
46
+ let [ x1, x2] = * param;
47
+
48
+ let n2 = T :: from_f64 ( 2.0 ) . unwrap ( ) ;
49
+ let n4 = T :: from_f64 ( 4.0 ) . unwrap ( ) ;
50
+ let n4_2 = T :: from_f64 ( 4.2 ) . unwrap ( ) ;
51
+
52
+ [ x1. powi ( 5 ) - n4_2 * x1. powi ( 3 ) + n4 * x1 + x2, n2 * x2 + x1]
53
+ }
54
+
55
+ /// Hessian of Three-hump camel test function
56
+ pub fn threehumpcamel_hessian < T > ( param : & [ T ; 2 ] ) -> [ [ T ; 2 ] ; 2 ]
57
+ where
58
+ T : Float + FromPrimitive ,
59
+ {
60
+ let [ x1, _] = * param;
61
+
62
+ let n1 = T :: from_f64 ( 1.0 ) . unwrap ( ) ;
63
+ let n2 = T :: from_f64 ( 2.0 ) . unwrap ( ) ;
64
+ let n4 = T :: from_f64 ( 4.0 ) . unwrap ( ) ;
65
+ let n5 = T :: from_f64 ( 5.0 ) . unwrap ( ) ;
66
+ let n12_6 = T :: from_f64 ( 12.6 ) . unwrap ( ) ;
67
+
68
+ let a = n5 * x1. powi ( 4 ) - n12_6 * x1. powi ( 2 ) + n4;
69
+ let b = n2;
70
+ let offdiag = n1;
71
+
72
+ [ [ a, offdiag] , [ offdiag, b] ]
73
+ }
74
+
41
75
#[ cfg( test) ]
42
76
mod tests {
43
77
use super :: * ;
44
78
use approx:: assert_relative_eq;
79
+ use finitediff:: FiniteDiff ;
80
+ use proptest:: prelude:: * ;
45
81
use std:: { f32, f64} ;
46
82
47
83
#[ test]
@@ -56,5 +92,53 @@ mod tests {
56
92
0.0 ,
57
93
epsilon = f64 :: EPSILON
58
94
) ;
95
+
96
+ let deriv = threehumpcamel_derivative ( & [ 0.0 , 0.0 ] ) ;
97
+ for i in 0 ..2 {
98
+ assert_relative_eq ! ( deriv[ i] , 0.0 , epsilon = f64 :: EPSILON ) ;
99
+ }
100
+ }
101
+
102
+ proptest ! {
103
+ #[ test]
104
+ fn test_threehumpcamel_derivative( a in -5.0 ..5.0 , b in -5.0 ..5.0 ) {
105
+ let param = [ a, b] ;
106
+ let derivative = threehumpcamel_derivative( & param) ;
107
+ let derivative_fd = Vec :: from( param) . central_diff( & |x| threehumpcamel( & [ x[ 0 ] , x[ 1 ] ] ) ) ;
108
+ for i in 0 ..derivative. len( ) {
109
+ assert_relative_eq!(
110
+ derivative[ i] ,
111
+ derivative_fd[ i] ,
112
+ epsilon = f64 :: EPSILON ,
113
+ max_relative = 1e-3
114
+ ) ;
115
+ }
116
+ }
117
+ }
118
+
119
+ proptest ! {
120
+ #[ test]
121
+ fn test_threehumpcamel_hessian_finitediff( a in -5.0 ..5.0 , b in -5.0 ..5.0 ) {
122
+ let param = [ a, b] ;
123
+ let hessian = threehumpcamel_hessian( & param) ;
124
+ let hessian_fd =
125
+ Vec :: from( param) . central_hessian( & |x| threehumpcamel_derivative( & [ x[ 0 ] , x[ 1 ] ] ) . to_vec( ) ) ;
126
+ let n = hessian. len( ) ;
127
+ println!( "1: {hessian:?} at {a}/{b}" ) ;
128
+ println!( "2: {hessian_fd:?} at {a}/{b}" ) ;
129
+ for i in 0 ..n {
130
+ assert_eq!( hessian[ i] . len( ) , n) ;
131
+ for j in 0 ..n {
132
+ if hessian_fd[ i] [ j] . is_finite( ) {
133
+ assert_relative_eq!(
134
+ hessian[ i] [ j] ,
135
+ hessian_fd[ i] [ j] ,
136
+ epsilon = f64 :: EPSILON ,
137
+ max_relative = 1e-5
138
+ ) ;
139
+ }
140
+ }
141
+ }
142
+ }
59
143
}
60
144
}
0 commit comments