calculate method

  1. @override
Point calculate(
  1. List<Beacon> beacons
)
override

Implementation

@override
Point calculate(List<Beacon> beacons) {
  _function.adjustParameters(beacons);
  Vector initialGuess = _function.computeInitialGuess(beacons);

  _jacobian = reshape(
      _jacobian,
      List.filled(
          _function.numFunctions(), List.filled(initialGuess.length, 0)));
  _initialCost = _calculateCost(initialGuess);
  double previousCost = _initialCost;
  double lambda = _initialLambda;

  /// Recompute the Jacobian in this iteration or not
  bool computeHessian = true;
  Vector optimized = Vector.fromList(initialGuess.toList());

  for (int i = 0; i < _maxIterations; i++) {
    if (computeHessian) {
      //  Compute some variables based on the gradient
      _computeGradientAndHessian(optimized);
      computeHessian = false;
      Matrix gTest =
          _gradient.mapElements((element) => element.abs() > _gtol ? 1 : 0);
      bool converged = gTest.sum() == 0;

      if (converged) {
        _finalCost = previousCost;
        return Point.vector(optimized);
      }
    }

    Matrix lambdaIdentity =
        Matrix.diagonal(Vector.filled(_hessian.columnsNum, lambda).toList());
    _hessian = _hessian + lambdaIdentity;

    /// in some cases h can be a singular matrix, meaning its determinant equals 0
    /// and the equation cannot be solved "conventionally"
    /// Premature but usable return of [parameters]
    try {
      _negativeStep = Matrix.fromList(
          matrixSolve(matrixToList(_hessian), matrixToList(_gradient)));
    } catch (error) {
      return Point.vector(optimized);
    }

    // compute the candidate parameters
    Vector candidate = optimized - _negativeStep;
    double cost = _calculateCost(candidate);

    //  if the candidate parameters produced better results, use them instead
    if (cost <= previousCost) {
      computeHessian = true;
      optimized = Vector.fromList(candidate.toList());

      // check for convergence
      // ftol <= (cost(k) - cost(k+1))/cost(k)
      bool converged = _ftol * previousCost >= previousCost - cost;
      previousCost = cost;
      lambda /= 10.0;

      if (converged) {
        _finalCost = previousCost;
        Point.vector(optimized);
      }
    } else {
      lambda *= 10.0;
    }
  }

  _finalCost = previousCost;
  return Point.vector(optimized);
}