docs: @Override
  	public void run() throws SolverException {
  		// Create an executor for concurrent evaluation of derivatives
  		if(numberOfThreads > 1) {
  			if(executor == null) {
  				executor = Executors.newFixedThreadPool(numberOfThreads);
  				executorShutdownWhenDone = true;
  			}
  		}
  
  		try {
  
  			// Allocate memory
  			int numberOfParameters	= initialParameters.length;
  			int numberOfValues		= targetValues.length;
  
  			parameterTest		= initialParameters.clone();
  			parameterIncrement	= new double[numberOfParameters];
  			parameterCurrent	= new double[numberOfParameters];
  
  			valueTest			= new double[numberOfValues];
  			valueCurrent		= new double[numberOfValues];
  			derivativeCurrent	= new double[parameterCurrent.length][valueCurrent.length];
  
  			hessianMatrix = new double[parameterCurrent.length][parameterCurrent.length];
  			beta = new double[parameterCurrent.length];
  
  			iteration = 0;
  
  			while(true) {
  				// Count iterations
  				iteration++;
  
  				// Calculate values for test parameters
  				setValues(parameterTest, valueTest);
  
  				// Calculate error
  				double errorMeanSquaredTest = getMeanSquaredError(valueTest);
  
  				/*
  				 * Note: The following test will be false if errorMeanSquaredTest is NaN.
  				 * That is: NaN is consider as a rejected point.
  				 */
  				if(errorMeanSquaredTest < errorMeanSquaredCurrent) {
  					errorRootMeanSquaredChange = Math.sqrt(errorMeanSquaredCurrent) - Math.sqrt(errorMeanSquaredTest);
  
  					// Accept point
  					System.arraycopy(parameterTest, 0, parameterCurrent, 0, parameterCurrent.length);
  					System.arraycopy(valueTest, 0, valueCurrent, 0, valueCurrent.length);
  					errorMeanSquaredCurrent		= errorMeanSquaredTest;
  
  					// Derivative has to be recalculated
  					isParameterCurrentDerivativeValid = false;
  
  					// Decrease lambda (move faster)
  					lambda			/= lambdaDivisor;
  				} else {
  					errorRootMeanSquaredChange = Math.sqrt(errorMeanSquaredTest) - Math.sqrt(errorMeanSquaredCurrent);
  
  					// Reject point, increase lambda (move slower)
  					lambda				*= lambdaMultiplicator;
  				}
  
  				// Update a new parameter trial, if we are not done
  				if (!done()) {
  					updateParameterTest();
  				} else {
  					break;
  				}
  
  				// Log iteration
  				if (logger.isLoggable(Level.FINE))
  				{
  					String logString = "Iteration: " + iteration + "\tLambda="
  							+ lambda + "\tError Current:" + errorMeanSquaredCurrent
  							+ "\tError Change:" + errorRootMeanSquaredChange + "\t";
  					for (int i = 0; i < parameterCurrent.length; i++) {
  						logString += "[" + i + "] = " + parameterCurrent[i] + "\t";
  					}
  					logger.fine(logString);
  				}
  			}
  		}
  		finally {
  			// Shutdown executor if present.
  			if(executor != null && executorShutdownWhenDone) {
  				executor.shutdown();
  				executor = null;
  			}
  		}
  	}