package com.yahoo.tensor;

import com.yahoo.tensor.functions.Reduce;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Microbenchmark of tensor operations.
 * 
 * @author bratseth
 */
public class TensorFunctionBenchmark {

    private final Random random = new Random();
    
    public void benchmark(int iterations) {
        List<Tensor> modelVectors = generateVectors(100, 300);
        Tensor queryVector = generateVectors(1, 300).get(0);
        dotProduct(queryVector, modelVectors, 10); // warmup
        long startTime = System.currentTimeMillis();
        dotProduct(queryVector, modelVectors, iterations);
        long totalTime = System.currentTimeMillis() - startTime;
        System.out.println("Time per join: " + (totalTime / iterations) +  " ms");
    }

    private double dotProduct(Tensor tensor, List<Tensor> tensors, int iterations) {
        double result = 0;
        for (int i = 0 ; i < iterations; i++)
            result = dotProduct(tensor, tensors);
        return result;
    }

    private double dotProduct(Tensor tensor, List<Tensor> tensors) {
        double largest = Double.MIN_VALUE;
        for (Tensor tensorElement : tensors) {
            double dotProduct = tensor.join(tensorElement, (a, b) -> a * b).reduce(Reduce.Aggregator.sum).asDouble();
            if (dotProduct > largest)
                largest = dotProduct;
        }
        System.out.println(largest);
        return largest;
    }
    
    private List<Tensor> generateVectors(int vectorCount, int vectorSize) {
        List<Tensor> tensors = new ArrayList<>();
        TensorType type = new TensorType.Builder().mapped("x").build();
        for (int i = 0; i < vectorCount; i++) {
            MapTensorBuilder builder = new MapTensorBuilder(type);
            for (int j = 0; j < vectorSize; j++) {
                builder.cell().label("x", String.valueOf(j)).value(random.nextDouble());
            }
            tensors.add(builder.build());
        }
        return tensors;
    }
    
    public static void main(String[] args) {
        // Was: 150 ms
        // After adding type: 300 ms
        new TensorFunctionBenchmark().benchmark(100);
    }

}

@@ -84,65 +84,9 @@
 til.
-ArrayList;%0Aimport java.util.List;%0Aimport java.util.Random
+*
 ;%0A%0A/
@@ -214,16 +214,23 @@
 e final 
+static 
 Random r
@@ -267,20 +267,22 @@
  public 
-void
+double
  benchma
@@ -298,27 +298,17 @@
 erations
-) %7B%0A       
+,
  List%3CTe
@@ -329,37 +329,11 @@
 tors
- = generateVectors(100, 300);
+) %7B
 %0A   
@@ -640,48 +640,15 @@
     
-System.out.println(%22Time per join: %22 + (
+return 
 tota
@@ -669,19 +669,8 @@
 ions
-) +  %22 ms%22)
 ;%0A  
@@ -1074,37 +1074,73 @@
 s) %7B
-%0A            double dotProduc
+ // tensors.size() = 1 for larger tensor%0A            Tensor resul
 t = 
@@ -1215,21 +1215,117 @@
 .sum
-).asDouble();
+, %22x%22);%0A            double dotProduct = result.reduce(Reduce.Aggregator.max).asDouble(); // for larger tensor
 %0A   
@@ -1358,16 +1358,18 @@
 largest)
+ %7B
 %0A       
@@ -1399,16 +1399,30 @@
 roduct;%0A
+            %7D%0A
         
@@ -1486,28 +1486,24 @@
 gest;%0A    %7D%0A
-    
 %0A    private
@@ -1503,16 +1503,23 @@
 private 
+static 
 List%3CTen
@@ -2047,20 +2047,725 @@
 ;%0A    %7D%0A
+%0A
     
+private static List%3CTensor%3E generateVectorsInOneTensor(int vectorCount, int vectorSize) %7B%0A        List%3CTensor%3E tensors = new ArrayList%3C%3E();%0A        TensorType type = new TensorType.Builder().mapped(%22i%22).mapped(%22x%22).build();%0A        MapTensorBuilder builder = new MapTensorBuilder(type);%0A        for (int i = 0; i %3C vectorCount; i++) %7B%0A            for (int j = 0; j %3C vectorSize; j++) %7B%0A                builder.cell()%0A                        .label(%22i%22, String.valueOf(i))%0A                        .label(%22x%22, String.valueOf(j))%0A                        .value(random.nextDouble());%0A            %7D%0A        %7D%0A        tensors.add(builder.build());%0A        return tensors; // only one tensor in the list.%0A    %7D%0A
 %0A    pub
@@ -2869,16 +2869,37 @@
 %0A       
+ double timeperJoin =
  new Ten
@@ -2934,16 +2934,433 @@
 mark(100
+, generateVectors(100, 300));%0A%0A        // This benchmark should be as fast as fast as the previous. Currently it is not by a factor of 5.%0A        double timePerJoinOneTensor = new TensorFunctionBenchmark().benchmark(20, generateVectorsInOneTensor(100, 300));%0A%0A        System.out.println(%22Time per join: %22 + timeperJoin +  %22 ms%22);%0A        System.out.println(%22Time per join one tensor: %22 + timePerJoinOneTensor +  %22 ms%22
 );%0A    %7D

Add tensor benchmark