All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.stanford.nlp.math.ArrayMath Maven / Gradle / Ivy

Go to download

Stanford Parser processes raw text in English, Chinese, German, Arabic, and French, and extracts constituency parse trees.

The newest version!
package edu.stanford.nlp.math;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Random;

import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.util.RuntimeInterruptedException;
import edu.stanford.nlp.util.StringUtils;

/**
 * Methods for operating on numerical arrays as vectors and matrices.
 *
 * @author Teg Grenager
 */
public class ArrayMath {

  private static final Random rand = new Random();


  private ArrayMath() { } // not instantiable


  // BASIC INFO -----------------------------------------------------------------

  public static int numRows(double[] v) {
    return v.length;
  }

  // GENERATION -----------------------------------------------------------------

  /**
   * Generate a range of integers from start (inclusive) to end (exclusive).
   * Similar to the Python range() builtin function.
   *
   * @param start Beginning number (inclusive)
   * @param end Ending number (exclusive)
   * @return integers from [start...end)
   */
  public static int[] range(int start, int end) {
    assert end > start;
    int len = end - start;
    int[] range = new int[len];
    for (int i = 0; i < range.length; ++i) {
      range[i] = i+start;
    }
    return range;
  }


  // CASTS ----------------------------------------------------------------------

  public static float[] doubleArrayToFloatArray(double[] a) {
    float[] result = new float[a.length];
    for (int i = 0; i < a.length; i++) {
      result[i] = (float) a[i];
    }
    return result;
  }

  public static double[] floatArrayToDoubleArray(float[] a) {
    double[] result = new double[a.length];
    for (int i = 0; i < a.length; i++) {
      result[i] = a[i];
    }
    return result;
  }

  public static double[][] floatArrayToDoubleArray(float[][] a) {
    double[][] result = new double[a.length][];
    for (int i = 0; i < a.length; i++) {
      result[i] = new double[a[i].length];
      for (int j = 0; j < a[i].length; j++) {
        result[i][j] = a[i][j];
      }
    }
    return result;
  }

  public static float[][] doubleArrayToFloatArray(double[][] a) {
    float[][] result = new float[a.length][];
    for (int i = 0; i < a.length; i++) {
      result[i] = new float[a[i].length];
      for (int j = 0; j < a[i].length; j++) {
        result[i][j] = (float) a[i][j];
      }
    }
    return result;
  }

  // OPERATIONS ON AN ARRAY - NONDESTRUCTIVE

  public static double[] exp(double[] a) {
    double[] result = new double[a.length];
    for (int i = 0; i < a.length; i++) {
      result[i] = Math.exp(a[i]);
    }
    return result;
  }

  public static double[] log(double[] a) {
    double[] result = new double[a.length];
    for (int i = 0; i < a.length; i++) {
      result[i] = Math.log(a[i]);
    }
    return result;
  }

  // OPERATIONS ON AN ARRAY - DESTRUCTIVE

  public static void expInPlace(double[] a) {
    for (int i = 0; i < a.length; i++) {
      a[i] = Math.exp(a[i]);
    }
  }

  public static void logInPlace(double[] a) {
    for (int i = 0; i < a.length; i++) {
      a[i] = Math.log(a[i]);
    }
  }

  public static double[] softmax(double[] scales) {
    double[] newScales = new double[scales.length];
    double sum = 0;
    for (int i = 0; i < scales.length; i++) {
      newScales[i] = Math.exp(scales[i]);
      sum += newScales[i];
    }
    for (int i = 0; i < scales.length; i++) {
      newScales[i] /= sum;
    }
    return newScales;
  }

  // OPERATIONS WITH SCALAR - DESTRUCTIVE

  /**
   * Increases the values in the first array a by b. Does it in place.
   *
   * @param a The array
   * @param b The amount by which to increase each item
   */
  public static void addInPlace(double[] a, double b) {
    for (int i = 0; i < a.length; i++) {
      a[i] = a[i] + b;
    }
  }

  /**
   * Increases the values in this array by b. Does it in place.
   *
   * @param a The array
   * @param b The amount by which to increase each item
   */
  public static void addInPlace(float[] a, double b) {
    for (int i = 0; i < a.length; i++) {
      a[i] = (float) (a[i] + b);
    }
  }

  /**
   * Add c times the array b to array a. Does it in place.
   */
  public static void addMultInPlace(double[] a, double[] b, double c) {
    for (int i=0; i list) {
    int[] result = new int[list.size()];
    int i = 0;
    for (int v : list) {
      result[i++] = v;
    }
    return result;
  }

  public static Double[] box(double[] assignment) {
    Double[] result = new Double[assignment.length];
    for (int i=0; i list) {
    double[] result = new double[list.size()];
    int i = 0;
    for (double v : list) {
      result[i++] = v;
    }
    return result;
  }

  public static int indexOf(int n, int[] a) {
    for (int i=0; i 0; i--) {
      int j = rand.nextInt(i+1); // a random index from 0 to i inclusive, may shuffle with itself
      int tmp = a[i];
      a[i] = a[j];
      a[j] = tmp;
    }
  }

  public static void reverse(int[] a) {
    for (int i=0; i= testStatistic) successes++;
    }
    return (double) (successes + 1) / (double) (iterations + 1);
  }

  public static double sigLevelByApproxRand(int[] A, int[] B) {
    return sigLevelByApproxRand(A, B, 1000);
  }

  public static double sigLevelByApproxRand(int[] A, int[] B, int iterations) {
    if (A.length == 0)
      throw new IllegalArgumentException("Input arrays must not be empty!");
    if (A.length != B.length)
      throw new IllegalArgumentException("Input arrays must have equal length!");
    if (iterations <= 0)
      throw new IllegalArgumentException("Number of iterations must be positive!");
    double[] X = new double[A.length];
    double[] Y = new double[B.length];
    for (int i = 0; i < A.length; i++) {
      X[i] = A[i];
      Y[i] = B[i];
    }
    return sigLevelByApproxRand(X, Y, iterations);
  }

  public static double sigLevelByApproxRand(boolean[] A, boolean[] B) {
    return sigLevelByApproxRand(A, B, 1000);
  }

  public static double sigLevelByApproxRand(boolean[] A, boolean[] B, int iterations) {
    if (A.length == 0)
      throw new IllegalArgumentException("Input arrays must not be empty!");
    if (A.length != B.length)
      throw new IllegalArgumentException("Input arrays must have equal length!");
    if (iterations <= 0)
      throw new IllegalArgumentException("Number of iterations must be positive!");
    double[] X = new double[A.length];
    double[] Y = new double[B.length];
    for (int i = 0; i < A.length; i++) {
      X[i] = (A[i] ? 1.0 : 0.0);
      Y[i] = (B[i] ? 1.0 : 0.0);
    }
    return sigLevelByApproxRand(X, Y, iterations);
  }


  // Returns the absolute difference between the means of arrays A and B.
  // If 'randomize' is true, swaps matched A & B entries with 50% probability
  // Assumes input arrays have equal, non-zero length.
  private static double absDiffOfMeans(double[] A, double[] B, boolean randomize) {
    Random random = new Random();
    double aTotal = 0.0;
    double bTotal = 0.0;
    for (int i = 0; i < A.length; i++) {
      if (randomize && random.nextBoolean()) {
        aTotal += B[i];
        bTotal += A[i];
      } else {
        aTotal += A[i];
        bTotal += B[i];
      }
    }
    double aMean = aTotal / A.length;
    double bMean = bTotal / B.length;
    return Math.abs(aMean - bMean);
  }

  // PRINTING FUNCTIONS

  public static String toBinaryString(byte[] b) {
    StringBuilder s = new StringBuilder();
    for (byte by : b) {
      for (int j = 7; j >= 0; j--) {
        if ((by & (1 << j)) > 0) {
          s.append('1');
        } else {
          s.append('0');
        }
      }
      s.append(' ');
    }
    return s.toString();
  }

  public static String toString(double[] a) {
    return toString(a, null);
  }

  public static String toString(double[] a, NumberFormat nf) {
    if (a == null) return null;
    if (a.length == 0) return "[]";
    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; i < a.length - 1; i++) {
      String s;
      if (nf == null) {
        s = String.valueOf(a[i]);
      } else {
        s = nf.format(a[i]);
      }
      b.append(s);
      b.append(", ");
    }
    String s;
    if (nf == null) {
      s = String.valueOf(a[a.length - 1]);
    } else {
      s = nf.format(a[a.length - 1]);
    }
    b.append(s);
    b.append(']');
    return b.toString();
  }

  public static String toString(float[] a) {
    return toString(a, null);
  }

  public static String toString(float[] a, NumberFormat nf) {
    if (a == null) return null;
    if (a.length == 0) return "[]";
    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; i < a.length - 1; i++) {
      String s;
      if (nf == null) {
        s = String.valueOf(a[i]);
      } else {
        s = nf.format(a[i]);
      }
      b.append(s);
      b.append(", ");
    }
    String s;
    if (nf == null) {
      s = String.valueOf(a[a.length - 1]);
    } else {
      s = nf.format(a[a.length - 1]);
    }
    b.append(s);
    b.append(']');
    return b.toString();
  }

  public static String toString(int[] a) {
    return toString(a, null);
  }

  public static String toString(int[] a, NumberFormat nf) {
    if (a == null) return null;
    if (a.length == 0) return "[]";
    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; i < a.length - 1; i++) {
      String s;
      if (nf == null) {
        s = String.valueOf(a[i]);
      } else {
        s = nf.format(a[i]);
      }
      b.append(s);
      b.append(", ");
    }
    String s;
    if (nf == null) {
      s = String.valueOf(a[a.length - 1]);
    } else {
      s = nf.format(a[a.length - 1]);
    }
    b.append(s);
    b.append(']');
    return b.toString();
  }

  public static String toString(byte[] a) {
    return toString(a, null);
  }

  public static String toString(byte[] a, NumberFormat nf) {
    if (a == null) return null;
    if (a.length == 0) return "[]";
    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; i < a.length - 1; i++) {
      String s;
      if (nf == null) {
        s = String.valueOf(a[i]);
      } else {
        s = nf.format(a[i]);
      }
      b.append(s);
      b.append(", ");
    }
    String s;
    if (nf == null) {
      s = String.valueOf(a[a.length - 1]);
    } else {
      s = nf.format(a[a.length - 1]);
    }
    b.append(s);
    b.append(']');
    return b.toString();
  }

  public static String toString(int[][] counts) {
    return toString(counts, null, null, 10, 10, NumberFormat.getInstance(), false);
  }

  public static String toString(int[][] counts, Object[] rowLabels, Object[] colLabels, int labelSize, int cellSize, NumberFormat nf, boolean printTotals) {
    // first compute row totals and column totals
    if (counts.length==0 || counts[0].length==0) return "";
    int[] rowTotals = new int[counts.length];
    int[] colTotals = new int[counts[0].length]; // assume it's square
    int total = 0;
    for (int i = 0; i < counts.length; i++) {
      for (int j = 0; j < counts[i].length; j++) {
        rowTotals[i] += counts[i][j];
        colTotals[j] += counts[i][j];
        total += counts[i][j];
      }
    }
    StringBuilder result = new StringBuilder();
    // column labels
    if (colLabels != null) {
      result.append(StringUtils.padLeft("", labelSize)); // spacing for the row labels!
      for (int j = 0; j < counts[0].length; j++) {
        String s = (colLabels[j]==null ? "null" : colLabels[j].toString());
        if (s.length() > cellSize - 1) {
          s = s.substring(0, cellSize - 1);
        }
        s = StringUtils.padLeft(s, cellSize);
        result.append(s);
      }
      if (printTotals) {
        result.append(StringUtils.padLeftOrTrim("Total", cellSize));
      }
      result.append('\n');
    }
    for (int i = 0; i < counts.length; i++) {
      // row label
      if (rowLabels != null) {
        String s = (rowLabels[i]==null ? "null" : rowLabels[i].toString());
        s = StringUtils.padOrTrim(s, labelSize); // left align this guy only
        result.append(s);
      }
      // value
      for (int j = 0; j < counts[i].length; j++) {
        result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
      }
      // the row total
      if (printTotals) {
        result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
      }
      result.append('\n');
    }
    // the col totals
    if (printTotals) {
      result.append(StringUtils.pad("Total", labelSize));
      for (int colTotal : colTotals) {
        result.append(StringUtils.padLeft(nf.format(colTotal), cellSize));
      }
      result.append(StringUtils.padLeft(nf.format(total), cellSize));
    }
    return result.toString();
  }


  public static String toString(double[][] counts) {
    return toString(counts, 10, null, null, NumberFormat.getInstance(), false);
  }

  public static String toString(double[][] counts, int cellSize, Object[] rowLabels, Object[] colLabels, NumberFormat nf, boolean printTotals) {
    if (counts==null) return null;
    // first compute row totals and column totals
    double[] rowTotals = new double[counts.length];
    double[] colTotals = new double[counts[0].length]; // assume it's square
    double total = 0.0;
    for (int i = 0; i < counts.length; i++) {
      for (int j = 0; j < counts[i].length; j++) {
        rowTotals[i] += counts[i][j];
        colTotals[j] += counts[i][j];
        total += counts[i][j];
      }
    }
    StringBuilder result = new StringBuilder();
    // column labels
    if (colLabels != null) {
      result.append(StringUtils.padLeft("", cellSize));
      for (int j = 0; j < counts[0].length; j++) {
        String s = colLabels[j].toString();
        if (s.length() > cellSize - 1) {
          s = s.substring(0, cellSize - 1);
        }
        s = StringUtils.padLeft(s, cellSize);
        result.append(s);
      }
      if (printTotals) {
        result.append(StringUtils.padLeftOrTrim("Total", cellSize));
      }
      result.append('\n');
    }
    for (int i = 0; i < counts.length; i++) {
      // row label
      if (rowLabels != null) {
        String s = rowLabels[i].toString();
        s = StringUtils.padOrTrim(s, cellSize); // left align this guy only
        result.append(s);
      }
      // value
      for (int j = 0; j < counts[i].length; j++) {
        result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
      }
      // the row total
      if (printTotals) {
        result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
      }
      result.append('\n');
    }
    // the col totals
    if (printTotals) {
      result.append(StringUtils.pad("Total", cellSize));
      for (double colTotal : colTotals) {
        result.append(StringUtils.padLeft(nf.format(colTotal), cellSize));
      }
      result.append(StringUtils.padLeft(nf.format(total), cellSize));
    }
    return result.toString();
  }

  public static String toString(float[][] counts) {
    return toString(counts, 10, null, null, NumberFormat.getIntegerInstance(), false);
  }

  public static String toString(float[][] counts, int cellSize, Object[] rowLabels, Object[] colLabels, NumberFormat nf, boolean printTotals) {
    // first compute row totals and column totals
    double[] rowTotals = new double[counts.length];
    double[] colTotals = new double[counts[0].length]; // assume it's square
    double total = 0.0;
    for (int i = 0; i < counts.length; i++) {
      for (int j = 0; j < counts[i].length; j++) {
        rowTotals[i] += counts[i][j];
        colTotals[j] += counts[i][j];
        total += counts[i][j];
      }
    }
    StringBuilder result = new StringBuilder();
    // column labels
    if (colLabels != null) {
      result.append(StringUtils.padLeft("", cellSize));
      for (int j = 0; j < counts[0].length; j++) {
        String s = colLabels[j].toString();
        s = StringUtils.padLeftOrTrim(s, cellSize);
        result.append(s);
      }
      if (printTotals) {
        result.append(StringUtils.padLeftOrTrim("Total", cellSize));
      }
      result.append('\n');
    }
    for (int i = 0; i < counts.length; i++) {
      // row label
      if (rowLabels != null) {
        String s = rowLabels[i].toString();
        s = StringUtils.pad(s, cellSize); // left align this guy only
        result.append(s);
      }
      // value
      for (int j = 0; j < counts[i].length; j++) {
        result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
      }
      // the row total
      if (printTotals) {
        result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
      }
      result.append('\n');
    }
    // the col totals
    if (printTotals) {
      result.append(StringUtils.pad("Total", cellSize));
      for (double colTotal : colTotals) {
        result.append(StringUtils.padLeft(nf.format(colTotal), cellSize));
      }
      result.append(StringUtils.padLeft(nf.format(total), cellSize));
    }
    return result.toString();
  }

  /**
   * For testing only.
   * @param args Ignored
   */
  public static void main(String[] args) {
    Random random = new Random();
    int length = 100;
    double[] A = new double[length];
    double[] B = new double[length];
    double aAvg = 70.0;
    double bAvg = 70.5;
    for (int i = 0; i < length; i++) {
      A[i] = aAvg + random.nextGaussian();
      B[i] = bAvg + random.nextGaussian();
    }
    System.out.println("A has length " + A.length + " and mean " + mean(A));
    System.out.println("B has length " + B.length + " and mean " + mean(B));
    for (int t = 0; t < 10; t++) {
      System.out.println("p-value: " + sigLevelByApproxRand(A, B));
    }
  }

  public static int[][] deepCopy(int[][] counts) {
    int[][] result = new int[counts.length][];
    for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy