@Test
  public void testInitChain() throws Exception {
    SimulatedAnnealing simulatedAnnealing = new SimulatedAnnealing();
    Knapsack knapsack = new Knapsack("9035 4 100 4 236 68 237 74 121 22 112");
    Configuration configuration = knapsack.getRandomConfiguration();
    double fitness = knapsack.getDefaultFitness().getValue(configuration);

    simulatedAnnealing.init(new BaseObjectiveProblem(knapsack), configuration);

    assert simulatedAnnealing.getBestFitness() == fitness
        : "Expected fitness to be " + fitness + ", got " + simulatedAnnealing.getBestFitness();
    assert simulatedAnnealing.getBestConfiguration() == configuration
        : "Expected solution to be "
            + configuration
            + ", got "
            + simulatedAnnealing.getBestConfiguration();

    // try to perform optimize step - SA should not raise an exception
    simulatedAnnealing.optimize();
  }
  public static void main(String[] args) {
    if (args.length < 2) {
      System.out.println("Provide a input size and repeat count");
      System.exit(0);
    }
    int N = Integer.parseInt(args[0]);
    if (N < 0) {
      System.out.println(" N cannot be negaitve.");
      System.exit(0);
    }
    Random random = new Random();
    // create the random points
    double[][] points = new double[N][2];
    for (int i = 0; i < points.length; i++) {
      points[i][0] = random.nextDouble();
      points[i][1] = random.nextDouble();
    }
    int iterations = Integer.parseInt(args[1]);
    // for rhc, sa, and ga we use a permutation based encoding
    TravelingSalesmanEvaluationFunction ef = new TravelingSalesmanRouteEvaluationFunction(points);
    Distribution odd = new DiscretePermutationDistribution(N);
    NeighborFunction nf = new SwapNeighbor();
    MutationFunction mf = new SwapMutation();
    CrossoverFunction cf = new TravelingSalesmanCrossOver(ef);
    HillClimbingProblem hcp = new GenericHillClimbingProblem(ef, odd, nf);
    GeneticAlgorithmProblem gap = new GenericGeneticAlgorithmProblem(ef, odd, mf, cf);

    System.out.println("Randomized Hill Climbing\n---------------------------------");
    for (int i = 0; i < iterations; i++) {
      RandomizedHillClimbing rhc = new RandomizedHillClimbing(hcp);
      long t = System.nanoTime();
      FixedIterationTrainer fit = new FixedIterationTrainer(rhc, 200000);
      fit.train();
      System.out.println(
          ef.value(rhc.getOptimal()) + ", " + (((double) (System.nanoTime() - t)) / 1e9d));
    }

    System.out.println("Simulated Annealing \n---------------------------------");
    for (int i = 0; i < iterations; i++) {
      SimulatedAnnealing sa = new SimulatedAnnealing(1E12, .95, hcp);
      long t = System.nanoTime();
      FixedIterationTrainer fit = new FixedIterationTrainer(sa, 200000);
      fit.train();
      System.out.println(
          ef.value(sa.getOptimal()) + ", " + (((double) (System.nanoTime() - t)) / 1e9d));
    }

    System.out.println("Genetic Algorithm\n---------------------------------");
    for (int i = 0; i < iterations; i++) {
      StandardGeneticAlgorithm ga = new StandardGeneticAlgorithm(200, 150, 10, gap);
      long t = System.nanoTime();
      FixedIterationTrainer fit = new FixedIterationTrainer(ga, 1000);
      fit.train();
      System.out.println(
          ef.value(ga.getOptimal()) + ", " + (((double) (System.nanoTime() - t)) / 1e9d));
    }

    System.out.println("MIMIC \n---------------------------------");

    // for mimic we use a sort encoding
    int[] ranges = new int[N];
    Arrays.fill(ranges, N);
    odd = new DiscreteUniformDistribution(ranges);
    Distribution df = new DiscreteDependencyTree(.1, ranges);

    for (int i = 0; i < iterations; i++) {
      ProbabilisticOptimizationProblem pop =
          new GenericProbabilisticOptimizationProblem(ef, odd, df);
      MIMIC mimic = new MIMIC(200, 60, pop);
      long t = System.nanoTime();
      FixedIterationTrainer fit = new FixedIterationTrainer(mimic, 1000);
      fit.train();
      System.out.println(
          ef.value(mimic.getOptimal()) + ", " + (((double) (System.nanoTime() - t)) / 1e9d));
    }
  }