diff --git a/src/zutil/math/MatrixMath.java b/src/zutil/math/Matrix.java similarity index 55% rename from src/zutil/math/MatrixMath.java rename to src/zutil/math/Matrix.java index 0c09a43..d7a3f8a 100755 --- a/src/zutil/math/MatrixMath.java +++ b/src/zutil/math/Matrix.java @@ -4,7 +4,7 @@ package zutil.math; * Some basic matrix match functions. * Matrix definition: double[y][x]. */ -public class MatrixMath { +public class Matrix { /*********************************************************************** * Scalar @@ -74,71 +74,120 @@ public class MatrixMath { * Elemental **********************************************************************/ - /** - * Element addition, each element in matrix1 will be - * added with the corresponding element in matrix2. - * - * @return a new matrix with the result - */ - public static double[][] add(double[][] matrix1, double[][] matrix2){ - elementalPreCheck(matrix1, matrix2); - double[][] result = new double[matrix1.length][matrix1[0].length]; + public static class Elemental { - for (int y=0; y < matrix1.length; ++y) { - for (int x=0; x < matrix1[y].length; ++x){ - result[y][x] = matrix1[y][x] + matrix2[y][x]; + /** + * Element addition, each element in matrix1 will be + * added with the corresponding element in matrix2. + * + * @return a new matrix with the result + */ + public static double[][] add(double[][] matrix1, double[][] matrix2) { + elementalPreCheck(matrix1, matrix2); + double[][] result = new double[matrix1.length][matrix1[0].length]; + + for (int y = 0; y < matrix1.length; ++y) { + for (int x = 0; x < matrix1[y].length; ++x) { + result[y][x] = matrix1[y][x] + matrix2[y][x]; + } } + return result; } - return result; - } - /** - * Element subtraction, each element in matrix1 will be - * subtracted with the corresponding element in matrix2. - * - * @return a new matrix with the result - */ - public static double[][] subtract(double[][] matrix1, double[][] matrix2){ - elementalPreCheck(matrix1, matrix2); - double[][] result = new double[matrix1.length][matrix1[0].length]; + /** + * Element subtraction, each element in matrix1 will be + * subtracted with the corresponding element in matrix2. + * + * @return a new matrix with the result + */ + public static double[][] subtract(double[][] matrix1, double[][] matrix2) { + elementalPreCheck(matrix1, matrix2); + double[][] result = new double[matrix1.length][matrix1[0].length]; - for (int y=0; y < matrix1.length; ++y) { - for (int x=0; x < matrix1[y].length; ++x){ - result[y][x] = matrix1[y][x] - matrix2[y][x]; + for (int y = 0; y < matrix1.length; ++y) { + for (int x = 0; x < matrix1[y].length; ++x) { + result[y][x] = matrix1[y][x] - matrix2[y][x]; + } } + return result; } - return result; - } - /** - * Element multiplication, each element in matrix1 will be - * multiplied with the corresponding element in matrix2. - * - * @return a new matrix with the result - */ - public static double[][] elemMultiply(double[][] matrix1, double[][] matrix2){ - elementalPreCheck(matrix1, matrix2); - double[][] result = new double[matrix1.length][matrix1[0].length]; + /** + * Element multiplication, each element in matrix1 will be + * multiplied with the corresponding element in matrix2. + * + * @return a new matrix with the result + */ + public static double[][] multiply(double[][] matrix1, double[][] matrix2) { + elementalPreCheck(matrix1, matrix2); + double[][] result = new double[matrix1.length][matrix1[0].length]; - for (int y=0; y < matrix1.length; ++y) { - for (int x=0; x < matrix1[y].length; ++x){ - result[y][x] = matrix1[y][x] * matrix2[y][x]; + for (int y = 0; y < matrix1.length; ++y) { + for (int x = 0; x < matrix1[y].length; ++x) { + result[y][x] = matrix1[y][x] * matrix2[y][x]; + } } + return result; } - return result; - } - private static void elementalPreCheck(double[][] matrix1, double[][] matrix2) { - if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length) - throw new IllegalArgumentException("Matrices need to be of same dimension: " + - "matrix1 " + matrix1.length + "x" + matrix1[0].length + ", " + - "matrix2 " + matrix2.length + "x" + matrix2[0].length + ", "); + /** + * Element exponential, each element in the vector will raised + * to the power of the exp paramter + * + * @return a new vector with the result + */ + public static double[] pow(double[] vector, double exp) { + double[] result = new double[vector.length]; + + for (int i = 0; i < vector.length; ++i) { + result[i] = Math.pow(vector[i], exp); + } + return result; + } + + /** + * Element multiplication, each element in matrix1 will be + * multiplied with the corresponding element in matrix2. + * + * @return a new matrix with the result + */ + public static double[][] pow(double[][] matrix, double exp) { + double[][] result = new double[matrix.length][matrix[0].length]; + + for (int i = 0; i < matrix.length; ++i) { + result[i] = pow(matrix[i], exp); + } + return result; + } + + private static void elementalPreCheck(double[][] matrix1, double[][] matrix2) { + if (matrix1.length != matrix2.length || matrix1[0].length != matrix2[0].length) + throw new IllegalArgumentException("Matrices need to be of same dimension: " + + "matrix1 " + matrix1.length + "x" + matrix1[0].length + ", " + + "matrix2 " + matrix2.length + "x" + matrix2[0].length + ", "); + } } /*********************************************************************** * Vector **********************************************************************/ + /** + * Vector subtraction, every element in the first vector will be subtracted + * with the corresponding element in the second vector. + * + * @return a new vector with subtracted elements + */ + public static double[] subtract(double[] vector1, double[] vector2){ + vectorPreCheck(vector1, vector2); + double[] result = new double[vector1.length]; + + for (int i=0; i < result.length; ++i) { + result[i] = vector1[i] - vector2[i]; + } + return result; + } + /** * Matrix Vector multiplication, each element column in the matrix will be * multiplied with the corresponding element row in the vector. @@ -175,6 +224,24 @@ public class MatrixMath { return result; } + /** + * Sums all values in a vector + * + * @return the summed value of all elements in the vector + */ + public static double sum(double[] vector) { + double sum = 0; + for (int i = 0; i < vector.length; i++) { + sum += vector[i]; + } + return sum; + } + + private static void vectorPreCheck(double[] vector1, double[] vector2) { + if (vector1.length != vector2.length) + throw new IllegalArgumentException("The two vectors need to have the same length: " + + "vector1 " + vector1.length + "x1, vector2 " + vector2.length + "x1"); + } private static void vectorPreCheck(double[][] matrix, double[] vector) { if (matrix[0].length != vector.length) throw new IllegalArgumentException("Matrix columns need to have same length as vector length: " + @@ -196,11 +263,10 @@ public class MatrixMath { matrixPreCheck(matrix1, matrix2); double[][] result = new double[matrix1.length][matrix2[0].length]; - for (int y=0; y < result.length; ++y) { - for (int x=0; x < result[y].length; ++x){ - - for (int i=0; i
+ * + * h(x) = theta0 * x0 + theta1 * x1 + ... + thetan * xn => transpose(theta) * x + * + */ + protected static double[] calculateHypotesis(double[][] x, double[] theta){ + return Matrix.multiply(x, theta); + } + + /** + * Linear Regresion cost method. + *

+ * + * J(O) = 1 / (2 * m) * Σ { ( h(xi) - yi )^2 } + *
+ * m = learning data size (rows) + * @return a number indicating the error rate + */ + protected static double calculateCost(double[][] x, double[] y, double[] theta){ + return 1 / (2 * x.length) * Matrix.sum( + Matrix.Elemental.pow( + Matrix.subtract(calculateHypotesis(x, theta), y), + 2)); + } +} diff --git a/test/zutil/benchmark/AnonymousFunctionBenchmark.java b/test/zutil/benchmark/AnonymousFunctionBenchmark.java new file mode 100755 index 0000000..40ba80d --- /dev/null +++ b/test/zutil/benchmark/AnonymousFunctionBenchmark.java @@ -0,0 +1,57 @@ +package zutil.benchmark; + +import com.carrotsearch.junitbenchmarks.BenchmarkRule; +import org.junit.Rule; +import org.junit.Test; + +public class AnonymousFunctionBenchmark { + public static final int TEST_EXECUTIONS = 500; + + @Rule + public BenchmarkRule benchmarkRun = new BenchmarkRule(); + + + private int[] array = new int[100_000]; + + + @Test + public void functionLoop() { + for(int k=0; k