Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaAlgorithm.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaAlgorithm.cs	(revision 8522)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaAlgorithm.cs	(revision 8523)
@@ -141,4 +141,11 @@
       var attributes = scaledData.GetLength(1);
 
+      var penalties = new Dictionary<double, Dictionary<double, double>>();
+      foreach (var c in data.ClassValues) {
+        penalties[c] = new Dictionary<double, double>();
+        foreach (var r in data.ClassValues)
+          penalties[c][r] = data.GetClassificationPenalty(c, r);
+      }
+
       alglib.mincgstate state;
       alglib.mincgreport rep;
@@ -147,5 +154,5 @@
       alglib.mincgsetxrep(state, true);
       int neighborSampleSize = neighborSamples;
-      Optimize(state, scaledData, classes, dimensions, neighborSampleSize, cancellation, reporter);
+      Optimize(state, scaledData, classes, penalties, dimensions, neighborSampleSize, cancellation, reporter);
       alglib.mincgresults(state, out matrix, out rep);
 
@@ -159,9 +166,9 @@
     }
 
-    private static void Optimize(alglib.mincgstate state, double[,] data, double[] classes, int dimensions, int neighborSampleSize, CancellationToken cancellation, Reporter reporter) {
+    private static void Optimize(alglib.mincgstate state, double[,] data, double[] classes, Dictionary<double, Dictionary<double, double>> penalties, int dimensions, int neighborSampleSize, CancellationToken cancellation, Reporter reporter) {
       while (alglib.mincgiteration(state)) {
         if (cancellation.IsCancellationRequested) break;
         if (state.needfg) {
-          Gradient(state.x, ref state.innerobj.f, state.innerobj.g, data, classes, dimensions, neighborSampleSize);
+          Gradient(state.x, ref state.innerobj.f, state.innerobj.g, data, classes, penalties, dimensions, neighborSampleSize);
           continue;
         }
@@ -175,5 +182,5 @@
     }
 
-    private static void Gradient(double[] A, ref double func, double[] grad, double[,] data, double[] classes, int dimensions, int neighborSampleSize) {
+    private static void Gradient(double[] A, ref double func, double[] grad, double[,] data, double[] classes, Dictionary<double, Dictionary<double, double>> penalties, int dimensions, int neighborSampleSize) {
       var instances = data.GetLength(0);
       var attributes = data.GetLength(1);
@@ -208,24 +215,21 @@
       double val;
       var pi = new double[instances];
+      func = 0;
       while (alglib.sparseenumerate(probabilities, ref t0, ref t1, out r, out c, out val)) {
-        if (classes[r].IsAlmost(classes[c])) {
-          pi[r] += val;
-        }
-      }
-
+        double vp = val * penalties[classes[r]][classes[c]];
+        pi[r] += vp;
+        func += vp;
+      }
+
+      t0 = 0; t1 = 0;
       var innerSum = new double[attributes, attributes];
       while (alglib.sparseenumerate(probabilities, ref t0, ref t1, out r, out c, out val)) {
         var vector = new Matrix(GetRow(data, r)).Subtract(new Matrix(GetRow(data, c)));
         vector.OuterProduct(vector).Multiply(val * pi[r]).AddTo(innerSum);
-
-        if (classes[r].IsAlmost(classes[c])) {
-          vector.OuterProduct(vector).Multiply(-val).AddTo(innerSum);
-        }
-      }
-
-      func = -pi.Sum();
+        vector.OuterProduct(vector).Multiply(-val * penalties[classes[r]][classes[c]]).AddTo(innerSum);
+      }
 
       r = 0;
-      var newGrad = AMatrix.Multiply(-2.0).Transpose().Multiply(new Matrix(innerSum)).Transpose();
+      var newGrad = AMatrix.Multiply(2.0).Transpose().Multiply(new Matrix(innerSum)).Transpose();
       foreach (var g in newGrad) {
         grad[r++] = g;
@@ -238,12 +242,12 @@
       if (!Results.ContainsKey("Optimization")) {
         qualities = new DataTable("Optimization");
-        qualities.Rows.Add(new DataRow("Quality", string.Empty));
+        qualities.Rows.Add(new DataRow("Penalty", string.Empty));
         Results.Add(new Result("Optimization", qualities));
       } else qualities = (DataTable)Results["Optimization"].Value;
-      qualities.Rows["Quality"].Values.Add(-func / instances);
-
-      if (!Results.ContainsKey("Quality")) {
-        Results.Add(new Result("Quality", new DoubleValue(-func / instances)));
-      } else ((DoubleValue)Results["Quality"].Value).Value = -func / instances;
+      qualities.Rows["Penalty"].Values.Add(func / instances);
+
+      if (!Results.ContainsKey("Penalty")) {
+        Results.Add(new Result("Penalty", new DoubleValue(func / instances)));
+      } else ((DoubleValue)Results["Penalty"].Value).Value = func / instances;
     }
 
