private Pair<Double, double[]> calculate(double[] x) {
			double objective = 0.0;
			double[] derivatives = DoubleArrays.constantArray(0.0, dimension());
			// compute the objective and its derivatives

			// initialize
			objective = 0.0;
			for (int i = 0; i < derivatives.length; i++) {
				derivatives[i] = 0.0;
			}

			// loop each datum
			for (int dataIndex = 0; dataIndex < data.length; dataIndex++) {
				EncodedDatum datum = data[dataIndex];

				// 1.1 objective add the score to L(w)
				objective += getScore(datum, x, indexLinearizer,
						datum.labelIndex);

				// 1.2 objective add log(sum(exp^score(xi, y')) for each y' in Y)
				double[] logProbabilities = initLogProbabilities();
				double logSumExpScore = getLogProbabilities(datum, x, encoding,
						indexLinearizer, logProbabilities);
				objective -= logSumExpScore;
				
				for (int featureIndexIndex = 0; featureIndexIndex < datum.getNumActiveFeatures(); featureIndexIndex++) {
					// 2.1 count f(xi) for its real label
					int featureIndex = datum.getFeatureIndex(featureIndexIndex);
					int weightIndex = indexLinearizer.getLinearIndex(featureIndex, datum.getLabelIndex());
					double count = datum.getFeatureCount(featureIndexIndex);
					derivatives[weightIndex] += count;
					
					// 2.2 go through all label to dispatch estimated feature count
					for (int labelIndex = 0; labelIndex < encoding.getNumLabels(); labelIndex++) {
						weightIndex = indexLinearizer.getLinearIndex(featureIndex, labelIndex);
						derivatives[weightIndex] -= SloppyMath.exp(logProbabilities[labelIndex]) * count;
					}
				}

			}
			// TODO: incorporate penalty terms into the objective and
			// derivatives
			// penalties

			double denominator = (2 * sigma * sigma);
			objective -= DoubleArrays.innerProduct(x, x) / denominator;
			for (int wIndex = 0; wIndex < derivatives.length; wIndex++) {
				derivatives[wIndex] -= x[wIndex] * 2.0 / denominator;
			}
			
			// negate
			objective = -objective;
			for (int i = 0; i < derivatives.length; i++) {
				derivatives[i] = -derivatives[i];
			}
			return new Pair<Double, double[]>(objective, derivatives);
		}