Add extended_powell functions and their tests.
authorMichael Orlitzky <michael@orlitzky.com>
Wed, 13 Mar 2013 18:04:55 +0000 (14:04 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Wed, 13 Mar 2013 18:04:55 +0000 (14:04 -0400)
optimization/test_functions/extended_powell1.m [new file with mode: 0644]
optimization/test_functions/extended_powell_gradient1.m [new file with mode: 0644]
optimization/test_functions/extended_powell_hessian1.m [new file with mode: 0644]
tests/extended_powell1_tests.m [new file with mode: 0644]
tests/extended_powell_gradient1_tests.m [new file with mode: 0644]
tests/extended_powell_hessian1_tests.m [new file with mode: 0644]

diff --git a/optimization/test_functions/extended_powell1.m b/optimization/test_functions/extended_powell1.m
new file mode 100644 (file)
index 0000000..2b1da25
--- /dev/null
@@ -0,0 +1,33 @@
+function f = extended_powell1(x)
+  ##
+  ## The extended Powell function. See Dennis & Schnabel, Appendix B,
+  ## problem #2.
+  ##
+  ## This function has a minimum at x=(0,0,...,0) with f(x) == 0. The
+  ## suggested starting point is x0=(3, -1, 0, 1,..., 3, -1, 0, 1).
+  ## Since the number of arguments is variable, we take a vector
+  ## instead of its individual components.
+  ##
+  n = length(x);
+
+  if (odd(n))
+    ## 'm' below must be an integer.
+    f = NA;
+    return;
+  end
+
+  m = n / 4;
+  f = 0;
+
+  % The extended Powell is simply a sum of Powell
+  % applications.
+  for k = [ 1 : m ]
+    y1 = x(4*k - 3);
+    y2 = x(4*k - 2);
+    y3 = x(4*k - 1);
+    y4 = x(4*k);
+
+    f_k = powell(y1,y2,y3,y4);
+    f = f + f_k;
+  end
+end
diff --git a/optimization/test_functions/extended_powell_gradient1.m b/optimization/test_functions/extended_powell_gradient1.m
new file mode 100644 (file)
index 0000000..7cc7aab
--- /dev/null
@@ -0,0 +1,35 @@
+function g = extended_powell_gradient1(x)
+  ##
+  ## The gradient of the extended Powell function. See
+  ## extended_powell1.m for more information.
+  ##
+  ## Since the number of arguments is variable, we take a vector
+  ## instead of its individual components.
+  ##
+  n = length(x);
+
+  if (odd(n))
+    ## 'm' below must be an integer.
+    g = NA;
+    return;
+  end
+
+  m = n / 4;
+  g = zeros(n, 1);
+
+  % The extended Powell is simply a sum of Powell
+  % applications.
+  for k = [ 1 : m ]
+    y1 = x(4*k - 3);
+    y2 = x(4*k - 2);
+    y3 = x(4*k - 1);
+    y4 = x(4*k);
+
+    g_k = powell_gradient(y1, y2, y3, y4);
+
+    for i = [ 1 : 4 ]
+      g(4*(k-1) + i) = g(4*(k-1) + i) + g_k(i);
+    end
+
+  end
+end
diff --git a/optimization/test_functions/extended_powell_hessian1.m b/optimization/test_functions/extended_powell_hessian1.m
new file mode 100644 (file)
index 0000000..972e690
--- /dev/null
@@ -0,0 +1,38 @@
+function H = extended_powell_hessian1(x)
+  ##
+  ## The Hessian of the extended Powell function. See
+  ## extended_powell1.m for more information.
+  ##
+  ## Since the number of arguments is variable, we take a vector
+  ## instead of its individual components.
+  ##
+  n = length(x);
+
+  if (odd(n))
+    ## 'm' below must be an integer.
+    H = NA;
+    return;
+  end
+
+  m = n / 4;
+  H = zeros(n, n);
+
+  % The extended Powell is simply a sum of Powell
+  % applications.
+  for k = [ 1 : m ]
+    y1 = x(4*k - 3);
+    y2 = x(4*k - 2);
+    y3 = x(4*k - 1);
+    y4 = x(4*k);
+
+    H_k = powell_hessian(y1, y2, y3, y4);
+
+    for i = [ 1 : 4 ]
+      for j = [ 1 : 4 ]
+       H(4*(k-1) + i, 4*(k-1) + j) = ...
+         H(4*(k-1) + i, 4*(k-1) + j) + H_k(i,j);
+      end
+    end
+
+  end
+end
diff --git a/tests/extended_powell1_tests.m b/tests/extended_powell1_tests.m
new file mode 100644 (file)
index 0000000..990eae6
--- /dev/null
@@ -0,0 +1,14 @@
+## Test the optimal point.
+
+for m = [ 1 : 10 ]
+  x = repmat([0;0;0;0], m, 1);
+
+  msg = sprintf("extended_powell1([0;0;0;0...]) == 0 (m = %d)", m);
+  unit_test_equals(msg, 0, extended_powell1(x));
+end
+
+## It should fail with the wrong number of coordinates.
+f = extended_powell1([1]);
+unit_test_equals("extended_powell1 fails when length(x) is odd", ...
+                true, ...
+                isna(f));
diff --git a/tests/extended_powell_gradient1_tests.m b/tests/extended_powell_gradient1_tests.m
new file mode 100644 (file)
index 0000000..5be0a6d
--- /dev/null
@@ -0,0 +1,13 @@
+## The gradient should be zero at the optimal point.
+
+for m = [ 1 : 10 ]
+  x = repmat([0;0;0;0], m, 1);
+
+  msg = sprintf("extended_powell_gradient1([0;0;0;0;...]) == 0 (m = %d)", m);
+  unit_test_equals(msg, 0, extended_powell_gradient1(x));
+end
+
+## It should fail with the wrong number of coordinates.
+g = extended_powell_gradient1([1;2;3]);
+msg = "extended_powell_gradient1 fails when length(x) is odd";
+unit_test_equals(msg, true, isna(g));
diff --git a/tests/extended_powell_hessian1_tests.m b/tests/extended_powell_hessian1_tests.m
new file mode 100644 (file)
index 0000000..6b65533
--- /dev/null
@@ -0,0 +1,9 @@
+## When m=1 we should agree with powell_hessian1().
+
+x = [4;5;6;7];
+f1 = powell_hessian1(x);
+f2 = extended_powell_hessian1(x);
+
+unit_test_equals("(extended_)powell_hessian1 agree for m=1", ...
+                true, ...
+                f1 == f2);