예제 #1
0
 @Override
 public void dispose() {
   synchronized (undisposed) {
     super.dispose();
     undisposed.remove(this);
   }
 }
예제 #2
0
  /**
   * test code
   *
   * @param args command line
   * @throws Exception all errors
   */
  public static void main(String[] args) throws Exception {
    GaussNewtonSolver.setExpensiveDebug(true);
    /* fit straight line to points (0,0) (1,8) (3,8) (4,20) */
    final double[] coord = new double[] {0., 1., 3., 4.};
    TestVect data = new TestVect(new double[] {0., 8., 8., 20.}, 0.0001, "data");

    // model will be intercept and gradient
    LinearTransform linearTransform =
        new LinearTransform() {
          public void forward(Vect data1, VectConst model) {
            VectUtil.zero(data1);
            double[] d = ((ArrayVect1) data1).getData();
            double[] m = ((ArrayVect1) model).getData();
            for (int i = 0; i < coord.length; ++i) {
              d[i] += m[0];
              d[i] += coord[i] * m[1];
            }
          }

          public void addTranspose(VectConst data1, Vect model) {
            double[] d = ((ArrayVect1) data1).getData();
            double[] m = ((ArrayVect1) model).getData();
            for (int i = 0; i < coord.length; ++i) {
              m[0] += d[i];
              m[1] += coord[i] * d[i];
            }
          }

          public void inverseHessian(Vect model) {}

          public void adjustRobustErrors(Vect dataError) {}
        };

    { // bad starting model, damp full model
      TestVect model = new TestVect(new double[] {-1., -1.}, 1., "model");
      boolean dampOnlyPerturbation = false;
      int conjugateGradIterations = 2;
      ArrayVect1 result =
          (ArrayVect1)
              GaussNewtonSolver.solve(
                  data,
                  model,
                  linearTransform,
                  dampOnlyPerturbation,
                  conjugateGradIterations,
                  null);
      LOG.fine("data = " + data);
      LOG.fine("model = " + model);
      LOG.fine("result = " + result);

      assert (new Almost(4)).equal(1., result.getData()[0]) : "result=" + result;
      assert (new Almost(5)).equal(4., result.getData()[1]) : "result=" + result;

      model.dispose();
      result.dispose();
    }
    double[] dampPerturb = null;
    { // good starting model, damp perturbations only
      TestVect model = new TestVect(new double[] {0.9, 3.9}, 1., "model");
      boolean dampOnlyPerturbation = true;
      int conjugateGradIterations = 2;
      ArrayVect1 result =
          (ArrayVect1)
              GaussNewtonSolver.solve(
                  data,
                  model,
                  linearTransform,
                  dampOnlyPerturbation,
                  conjugateGradIterations,
                  null);
      LOG.fine("data = " + data);
      LOG.fine("model = " + model);
      LOG.fine("result = " + result);

      dampPerturb = result.getData();
      assert (new Almost(4)).equal(1., result.getData()[0]) : "result=" + result;
      assert (new Almost(5)).equal(4., result.getData()[1]) : "result=" + result;
      model.dispose();
      result.dispose();
    }
    { // good starting model, damp whole model, and compare to previous
      TestVect model = new TestVect(new double[] {0.9, 3.9}, 1., "model");
      boolean dampOnlyPerturbation = false;
      int conjugateGradIterations = 2;
      ArrayVect1 result =
          (ArrayVect1)
              GaussNewtonSolver.solve(
                  data,
                  model,
                  linearTransform,
                  dampOnlyPerturbation,
                  conjugateGradIterations,
                  null);
      LOG.fine("data = " + data);
      LOG.fine("model = " + model);
      LOG.fine("result = " + result);

      double[] dampAll = result.getData();
      assert (new Almost(4)).equal(1., result.getData()[0]) : "result=" + result;
      assert (new Almost(5)).equal(4., result.getData()[1]) : "result=" + result;
      assert dampAll[0] > dampPerturb[0];
      assert dampAll[1] < dampPerturb[1];
      { //
        double dampAll2 = 0.;
        double dampPerturb2 = 0.;
        for (int i = 0; i < 2; ++i) {
          dampAll2 += dampAll[i] * dampAll[i];
          dampPerturb2 += dampPerturb[i] * dampPerturb[i];
        }
        LOG.fine("dampAll2=" + dampAll2 + " dampPerturb2=" + dampPerturb2);
        assert dampAll2 < dampPerturb2;
      }
      model.dispose();
      result.dispose();
    }
    assert TestVect.max < 10 : "max=" + TestVect.max;
    // use full interface
    for (int twice = 0; twice < 2; ++twice) {
      boolean project = (twice == 1);
      TestVect perturb = new TestVect(new double[2], 1., "perturb");
      { // Steepest descent: One conjugate gradient iteration and a line search
        TestVect model = new TestVect(new double[] {0.9, 3.9}, 1., "model");
        boolean dampOnlyPerturbation = false;
        int linearizationIterations = 3;
        int lineSearchIterations = 20;
        double lineSearchError = 0.000001;
        int conjugateGradIterations = 1;
        Transform transform = new LinearTransformWrapper(linearTransform);
        ArrayVect1 result =
            (ArrayVect1)
                GaussNewtonSolver.solve(
                    data,
                    model,
                    (project) ? perturb : null,
                    transform,
                    dampOnlyPerturbation,
                    conjugateGradIterations,
                    lineSearchIterations,
                    linearizationIterations,
                    lineSearchError,
                    null);
        LOG.fine("data = " + data);
        LOG.fine("model = " + model);
        LOG.fine("result = " + result);
        assert (new Almost(3)).equal(1., result.getData()[0]) : "result=" + result;
        assert (new Almost(4)).equal(4., result.getData()[1]) : "result=" + result;
        model.dispose();
        result.dispose();
      }
      { // Make sure unnecessary iterations are not a problem
        TestVect model = new TestVect(new double[] {0.9, 3.9}, 1., "model");
        boolean dampOnlyPerturbation = true;
        int linearizationIterations = 3;
        int lineSearchIterations = 30;
        double lineSearchError = 0.000001;
        int conjugateGradIterations = 2;
        Transform transform = new LinearTransformWrapper(linearTransform);
        ArrayVect1 result =
            (ArrayVect1)
                GaussNewtonSolver.solve(
                    data,
                    model,
                    project ? perturb : null,
                    transform,
                    dampOnlyPerturbation,
                    conjugateGradIterations,
                    lineSearchIterations,
                    linearizationIterations,
                    lineSearchError,
                    null); // new LogMonitor("Test inversion",LOG)
        LOG.fine("data = " + data);
        LOG.fine("model = " + model);
        LOG.fine("result = " + result);

        assert (new Almost(4)).equal(1., result.getData()[0]) : "result=" + result;
        assert (new Almost(5)).equal(4., result.getData()[1]) : "result=" + result;
        model.dispose();
        result.dispose();
      }
      perturb.dispose();
    }
    data.dispose();

    if (TestVect.undisposed.size() > 0) {
      throw new IllegalStateException(TestVect.getTraces());
    }
    assert TestVect.max <= 10 : "max=" + TestVect.max;

    assert projectWasTested;

    GaussNewtonSolver.setExpensiveDebug(false);
  }