/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ package com.analog.lyric.dimple.test.FactorFunctions; import java.util.Arrays; import java.util.Random; import org.junit.Test; import com.analog.lyric.dimple.factorfunctions.MatrixVectorProduct; import com.analog.lyric.dimple.model.domains.Domain; import com.analog.lyric.dimple.model.domains.RealDomain; import com.analog.lyric.dimple.model.domains.RealJointDomain; import com.analog.lyric.dimple.model.values.Value; public class TestMatrixVectorProduct extends FactorFunctionTester { private final Random _rand = new Random(123123); @Test public void test() { for (int inLength = 2; inLength < 4; ++inLength) { for (int outLength = 2; outLength < 4; ++outLength) { testDeterministic(inLength, outLength); } } } private void testDeterministic(int inLength, int outLength) { final int nCases = 5; final MatrixVectorProduct function = new MatrixVectorProduct(inLength, outLength); final RealDomain rd = RealDomain.unbounded(); final RealJointDomain rd2 = RealJointDomain.create(2); final int[] outputIndices = new int[outLength]; for (int i = 0; i < outLength; ++i) { outputIndices[i] = i; } final double[][][] matrices = new double[nCases][][]; final double[][] inVectors = new double[nCases][]; final double[][] outVectors = new double[nCases][]; for (int i = 0; i < nCases; ++i) { double[][] matrix = matrices[i] = new double[outLength][]; for (int row = 0; row < outLength; ++row) { double[] rowValues = matrix[row] = new double[inLength]; for (int col = 0; col < inLength; ++col) { rowValues[col] = 1 + (_rand.nextDouble() * 10); } } double[] inVector = inVectors[i] = new double[inLength]; for (int col = 0; col < inLength; ++col) { inVector[col] = 1 + (_rand.nextDouble() * 10); } double[] outVector = outVectors[i] = new double[outLength]; for (int row = 0; row < outLength; ++row) { for (int col = 0; col < inLength; ++col) { outVector[row] += matrix[row][col] * inVector[col]; } } } // // Constant matrix and input vector // Domain[] domains = new Domain[2 + outLength]; Arrays.fill(domains, rd); domains[outLength] = null; // matrix domains[outLength + 1] = rd2; Value[][] testCases = new Value[nCases][]; for (int i = 0; i < nCases; ++i) { double[] inVector = inVectors[i]; double[][] matrix = matrices[i]; double[] outVector = outVectors[i]; Value[] testCase = testCases[i] = new Value[2 + outLength]; for (int j = 0; j < outLength; ++j) { testCase[j] = Value.create(outVector[j]); } testCase[outLength] = Value.create(matrix); testCase[outLength + 1] = Value.create(inVector.clone()); } testEvalDeterministic(function, domains, outputIndices, testCases); // // Constant matrix, flattened variable vector // domains = new Domain[1 + outLength + inLength]; Arrays.fill(domains, rd); domains[outLength] = null; // matrix for (int i = 0; i < nCases; ++i) { double[] inVector = inVectors[i]; double[][] matrix = matrices[i]; double[] outVector = outVectors[i]; Value[] testCase = testCases[i] = new Value[domains.length]; for (int j = 0; j < outLength; ++j) { testCase[j] = Value.create(outVector[j]); } testCase[outLength] = Value.create(matrix); for (int j = 0; j < inLength; ++j) { testCase[outLength + 1 + j] = Value.create(inVector[j]); } } testEvalDeterministic(function, domains, outputIndices, testCases); // // Constant input vector, flattened variable matrix // domains = new Domain[1 + outLength + inLength * outLength]; Arrays.fill(domains, rd); domains[domains.length - 1] = rd2; for (int i = 0; i < nCases; ++i) { double[] inVector = inVectors[i]; double[][] matrix = matrices[i]; double[] outVector = outVectors[i]; Value[] testCase = testCases[i] = new Value[domains.length]; for (int j = 0; j < outLength; ++j) { testCase[j] = Value.create(outVector[j]); } int j = outLength; for (int col = 0; col < inLength; ++col) { for (int row = 0; row < outLength; ++row) { testCase[j++] = Value.create(matrix[row][col]); } } testCase[domains.length - 1] = Value.create(inVector); } testEvalDeterministic(function, domains, outputIndices, testCases); // // Flattened variable matrix and input vector // domains = new Domain[outLength + inLength + inLength * outLength]; Arrays.fill(domains, rd); int inVectorOffset = domains.length - inLength; for (int i = 0; i < nCases; ++i) { double[] inVector = inVectors[i]; double[][] matrix = matrices[i]; double[] outVector = outVectors[i]; Value[] testCase = testCases[i] = new Value[domains.length]; for (int j = 0; j < outLength; ++j) { testCase[j] = Value.create(outVector[j]); } int j = outLength; for (int col = 0; col < inLength; ++col) { for (int row = 0; row < outLength; ++row) { testCase[j++] = Value.create(matrix[row][col]); } } for (j = 0; j < inLength; ++j) { testCase[inVectorOffset + j] = Value.create(inVector[j]); } } testEvalDeterministic(function, domains, outputIndices, testCases); // TODO: test evalEnergy for non-deterministic cases w/ smoothing } }