Index: /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/Analysis/NeutralityAnalyzer.cs
===================================================================
--- /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/Analysis/NeutralityAnalyzer.cs	(revision 7782)
+++ /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/Analysis/NeutralityAnalyzer.cs	(revision 7783)
@@ -48,4 +48,7 @@
       get { return (LookupParameter<DoubleValue>)Parameters["CurrentNeutralDistance"]; }
     }
+    public LookupParameter<DoubleValue> CurrentFractionOfNeutralNeighborsParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["CurrentFractionOfNeutralNeighbors"]; }
+    }
     public LookupParameter<DataTable> NeutralWalkDistancesTableParameter {
       get { return (LookupParameter<DataTable>)Parameters["NeutralWalkDistancesTable"]; }
@@ -57,4 +60,10 @@
       get { return (LookupParameter<DoubleValue>)Parameters["AverageNeutralWalkDistance"]; }
     }
+    public LookupParameter<DoubleValue> AverageNeutralNeighborFractionParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["AverageNeutralNeighborFraction"]; }
+    }
+    public LookupParameter<DoubleValue> AverageInnerNeutralNeighborFractionParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["AverageInnerNeutralNeighborFraction"]; }
+    }
     public LookupParameter<DoubleValue> NeutralWalkLengthVarianceParameter {
       get { return (LookupParameter<DoubleValue>)Parameters["NeutralWalkLengthVariance"]; }
@@ -63,4 +72,10 @@
       get { return (LookupParameter<DoubleValue>)Parameters["NeutralWalkDistanceVariance"]; }
     }        
+    public LookupParameter<DoubleValue> NeutralNeighborFractionVarianceParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["NeutralNeighborFractionVariance"]; }
+    }
+    public LookupParameter<DoubleValue> InnerNeutralNeighborFractionVarianceParameter {
+      get { return (LookupParameter<DoubleValue>)Parameters["InnerNeutralNeighborFractionVariance"]; }
+    }
     public LookupParameter<VariableCollection> ResultsParameter {
       get { return (LookupParameter<VariableCollection>)Parameters["Results"]; }
@@ -75,17 +90,27 @@
       Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The current quality"));
       Parameters.Add(new LookupParameter<DoubleValue>("CurrentNeutralDistance", "The distance of the current solution to the starting point of the neutral (portion of the) walk."));
+      Parameters.Add(new LookupParameter<DoubleValue>("CurrentFractionOfNeutralNeighbors", "The current fraction of neighbors with the same fitness (within epsilon)"));
       Parameters.Add(new LookupParameter<DataTable>("NeutralWalkDistancesTable", "The historical values of the current neutral distance."));
       Parameters.Add(new LookupParameter<DoubleValue>("AverageNeutralWalkLength", "The average length of a neutral walk"));
       Parameters.Add(new LookupParameter<DoubleValue>("AverageNeutralWalkDistance", "The average distance of the neutral walk to the starting point."));
+      Parameters.Add(new LookupParameter<DoubleValue>("AverageNeutralNeighborFraction", "The average fraction of neutral neighbors overall."));
+      Parameters.Add(new LookupParameter<DoubleValue>("AverageInnerNeutralNeighborFraction", "The average fraction of neutral neighbors within a neutral area."));
       Parameters.Add(new LookupParameter<DoubleValue>("NeutralWalkLengthVariance", "The variance of the neutral walks lengths"));
       Parameters.Add(new LookupParameter<DoubleValue>("NeutralWalkDistanceVariance", "The varaince of the neutral walks distances"));
+      Parameters.Add(new LookupParameter<DoubleValue>("NeutralNeighborFractionVariance", "The average fraction of neutral neighbors overall."));
+      Parameters.Add(new LookupParameter<DoubleValue>("InnerNeutralNeighborFractionVariance", "The average fraction of neutral neighbors within a neutral area."));
 
       var resultsCollector = new ResultsCollector();
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(CurrentNeutralDistanceParameter.ActualName));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(CurrentFractionOfNeutralNeighborsParameter.ActualName));
       resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(NeutralWalkDistancesTableParameter.Name));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(AverageNeutralWalkLengthParameter.Name));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(AverageNeutralWalkDistanceParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(AverageNeutralNeighborFractionParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(AverageInnerNeutralNeighborFractionParameter.Name));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(NeutralWalkLengthVarianceParameter.Name));
       resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(NeutralWalkDistanceVarianceParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(NeutralNeighborFractionVarianceParameter.Name));
+      resultsCollector.CollectedValues.Add(new LookupParameter<DoubleValue>(InnerNeutralNeighborFractionVarianceParameter.Name));
 
       OperatorGraph.InitialOperator = resultsCollector;
@@ -99,23 +124,36 @@
     public override IOperation Apply() {
       DataTable distanceTable = GetOrCreateDistanceTable();
-      var values = distanceTable.Rows["Neutral Walk Distances"].Values;
-      values.Add(CurrentNeutralDistanceParameter.ActualValue == null ? 0 : CurrentNeutralDistanceParameter.ActualValue.Value);
-      List<double> lenghts = new List<double>();
-      List<double> distances = new List<double>();
+      var distanceValues = distanceTable.Rows["Neutral Walk Distances"].Values;
+      var fractionValues = distanceTable.Rows["Neutral Neighbor Fractions"].Values;
+      distanceValues.Add(CurrentNeutralDistanceParameter.ActualValue == null ? 0 : CurrentNeutralDistanceParameter.ActualValue.Value);
+      fractionValues.Add(CurrentFractionOfNeutralNeighborsParameter.ActualValue == null ? 0 : CurrentFractionOfNeutralNeighborsParameter.ActualValue.Value);
+      var lengths = new List<double>();
+      var distances = new List<double>();
+      var innerFractions = new List<double>();
       double lastValue = -1;
       int lastStart = 0;
-      for (int i = 0; i<values.Count; i++) {
-        if (values[i] < lastValue) {
-          lenghts.Add(i - lastStart - 1);
+      for (int i = 0; i<distanceValues.Count; i++) {
+        if (distanceValues[i] < lastValue) { // restart
+          lengths.Add(i - lastStart - 1);
           distances.Add(lastValue);
           lastStart = i;
+        } else { // inside neutral area
+          innerFractions.Add(fractionValues[i]);
         }
-        lastValue = values[i];
+        lastValue = distanceValues[i];
       }
-      if (distances.Count > 0 && lenghts.Count > 0) {
+      if (lastStart != distanceValues.Count-1) {
+        lengths.Add(distanceValues.Count - lastStart - 1);
+        distances.Add(lastValue);
+      }
+      if (distances.Count > 0 && lengths.Count > 0) {
         AverageNeutralWalkDistanceParameter.ActualValue = new DoubleValue(distances.Average());
         NeutralWalkDistanceVarianceParameter.ActualValue = new DoubleValue(distances.Variance());
-        AverageNeutralWalkLengthParameter.ActualValue = new DoubleValue(lenghts.Average());
-        NeutralWalkLengthVarianceParameter.ActualValue = new DoubleValue(lenghts.Variance());
+        AverageNeutralWalkLengthParameter.ActualValue = new DoubleValue(lengths.Average());
+        NeutralWalkLengthVarianceParameter.ActualValue = new DoubleValue(lengths.Variance());
+        AverageNeutralNeighborFractionParameter.ActualValue = new DoubleValue(fractionValues.Average());
+        NeutralNeighborFractionVarianceParameter.ActualValue = new DoubleValue(fractionValues.Variance());
+        AverageInnerNeutralNeighborFractionParameter.ActualValue = new DoubleValue(innerFractions.Average());
+        InnerNeutralNeighborFractionVarianceParameter.ActualValue = new DoubleValue(innerFractions.Variance());
       }
       return base.Apply();
@@ -127,6 +165,6 @@
         distancesTable = new DataTable("Neutral Walk Distances");
         NeutralWalkDistancesTableParameter.ActualValue = distancesTable;
-        var row = new DataRow("Neutral Walk Distances");
-        distancesTable.Rows.Add(row);
+        distancesTable.Rows.Add(new DataRow("Neutral Walk Distances"));
+        distancesTable.Rows.Add(new DataRow("Neutral Neighbor Fractions") {VisualProperties = {SecondYAxis = true}});
       }
       return distancesTable;
Index: /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/NeutralSelector.cs
===================================================================
--- /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/NeutralSelector.cs	(revision 7782)
+++ /branches/FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/NeutralSelector.cs	(revision 7783)
@@ -56,4 +56,7 @@
       get { return (ValueLookupParameter<DoubleValue>)Parameters["Epsilon"]; }
     }
+    public ILookupParameter<DoubleValue> CurrentFractionOfNeutralNeighborsParameter {
+      get { return (LookupParameter<DoubleValue>) Parameters["CurrentFractionOfNeutralNeighbors"]; }
+    } 
     public LookupParameter<DoubleValue> CurrentNeutralDistanceParameter {
       get { return (LookupParameter<DoubleValue>)Parameters["CurrentNeutralDistance"]; }
@@ -71,4 +74,22 @@
       get { return CopySelectedParameter.Value; }
       set { CopySelectedParameter.Value = value; }
+    }
+    protected double CurrentNeutralDistance {
+      set {
+        if (CurrentNeutralDistanceParameter.ActualValue == null)
+          CurrentNeutralDistanceParameter.ActualValue= new DoubleValue(value);
+        else 
+          CurrentNeutralDistanceParameter.ActualValue.Value = value;
+      }
+      
+    }
+    protected double CurrentFractionOfNeutralNeighbors {
+      get { return CurrentFractionOfNeutralNeighborsParameter.ActualValue.Value; }
+      set {
+        if (CurrentFractionOfNeutralNeighborsParameter.ActualValue == null)
+          CurrentFractionOfNeutralNeighborsParameter.ActualValue = new DoubleValue(value);
+        else
+          CurrentFractionOfNeutralNeighborsParameter.ActualValue.Value = value;
+      }
     }
     #endregion
@@ -91,4 +112,5 @@
       Parameters.Add(new ConstrainedValueParameter<IItemDistanceCalculator>("SolutionDistanceCalculator", "Operator to calculate distances between the base item and the current item."));
       Parameters.Add(new LookupParameter<DoubleValue>("CurrentNeutralDistance", "The distance of the current item to the starting point of the neutral (portion of the) walk."));
+      Parameters.Add(new LookupParameter<DoubleValue>("CurrentFractionOfNeutralNeighbors", "The fraction of examined neighbors that have the same fitness value (within epsilon)"));
       Parameters.Add(new LookupParameter<IRandom>("Random", "Random number generator for breaking ties in the ordering."));
       CopySelectedParameter.Hidden = true;
@@ -112,4 +134,9 @@
       return new NeutralSelector(this, cloner);
     }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      if (!Parameters.ContainsKey("CurrentFractionOfNeutralNeighbors"))
+        Parameters.Add(new LookupParameter<DoubleValue>("CurrentFractionOfNeutralNeighbors", "The fraction of examined neighbors that have the same fitness (within epsilon)"));
+    }
     #endregion
 
@@ -119,15 +146,20 @@
 
     public sealed override IOperation Apply() {
-      IItemDistanceCalculator calc = (IItemDistanceCalculator)SolutionDistanceCalculatorParameter.ActualValue;
-      double baseQuality = BaseQualityParameter.ActualValue.Value;
-      IItem startingPoint = StartingPointParameter.ActualValue;
-      IItem baseSolution = BaseSolutionParameter.ActualValue;
-      ItemArray<IItem> items = SolutionParameter.ActualValue;
-      double eps = EpsilonParameter.ActualValue.Value;
-      IRandom random = RandomParameter.ActualValue;
-      double baseDistance = 0;
-      if (startingPoint != null) {
-        baseDistance = calc.Distance(baseSolution, startingPoint);
-        baseSolution = startingPoint;
+      var calc = (IItemDistanceCalculator)SolutionDistanceCalculatorParameter.ActualValue;
+      var baseQuality = BaseQualityParameter.ActualValue.Value;
+      var startingPoint = StartingPointParameter.ActualValue;
+      var baseSolution = BaseSolutionParameter.ActualValue;
+      var items = SolutionParameter.ActualValue;
+      var eps = EpsilonParameter.ActualValue.Value;
+      var random = RandomParameter.ActualValue;
+      double currentNeutralDistance;
+
+      if (startingPoint == null) {
+        currentNeutralDistance = 0;
+        CurrentNeutralDistance = 0;
+        startingPoint = baseSolution;
+        StartingPointParameter.ActualValue = (IItem)baseSolution.Clone();
+      } else {
+        currentNeutralDistance = calc.Distance(startingPoint, baseSolution);
       }
 
@@ -137,20 +169,35 @@
           Idx=i,
           Diff=Squash(Math.Abs(baseQuality-p.Quality), eps),
-          Dist=calc.Distance(baseSolution, p.Item)
+          StartDist=calc.Distance(startingPoint, p.Item),
+          BaseDist=calc.Distance(baseSolution, p.Item)
         })        
+        .Where(n => n.BaseDist > 0)
         .ToList();
-      if (random != null)
-        neighbors.Shuffle(random);
-      var mostDistantNeutralNeighbor = neighbors.Where(n => n.Diff == 0).OrderByDescending(n => n.Dist).FirstOrDefault();
-      if (mostDistantNeutralNeighbor != null && mostDistantNeutralNeighbor.Dist > baseDistance) {
-        Select(mostDistantNeutralNeighbor.Idx);
-        if (startingPoint == null)
-          StartingPointParameter.ActualValue = (IItem)baseSolution.Clone();
-        CurrentNeutralDistanceParameter.ActualValue = new DoubleValue(mostDistantNeutralNeighbor.Dist);
-      } else {
-        var mostDistantNeighbor = neighbors.OrderByDescending(n => n.Dist).FirstOrDefault();
-        Select(mostDistantNeighbor.Idx);
-        StartingPointParameter.ActualValue = (IItem)items[mostDistantNeighbor.Idx].Clone();
-        CurrentNeutralDistanceParameter.ActualValue = new DoubleValue(0);
+      if (neighbors.Count > 0) {
+        if (random != null)
+          neighbors.Shuffle(random);
+        var mostDistantNeutralNeighbor =
+          neighbors.Where(n => n.Diff == 0).OrderByDescending(n => n.StartDist).FirstOrDefault();
+        if (mostDistantNeutralNeighbor != null && mostDistantNeutralNeighbor.StartDist > currentNeutralDistance) {
+          if (currentNeutralDistance == 0) {
+            StartingPointParameter.ActualValue = (IItem) baseSolution.Clone();
+            CurrentNeutralDistance = mostDistantNeutralNeighbor.BaseDist;
+          } else {
+            CurrentNeutralDistance = mostDistantNeutralNeighbor.StartDist;
+          }
+          Select(mostDistantNeutralNeighbor.Idx);
+        } else {
+          var mostDistantNonNeutralNeighbor = neighbors.Where(n => n.Diff > 0).OrderByDescending(n => n.StartDist).FirstOrDefault();
+          if (mostDistantNonNeutralNeighbor != null) {
+            Select(mostDistantNonNeutralNeighbor.Idx);
+          } else {
+            var mostDistantNeighbor = neighbors.OrderByDescending(n => n.StartDist).FirstOrDefault();
+            Select(mostDistantNeighbor.Idx);
+          }
+          if (currentNeutralDistance > 0)
+            StartingPointParameter.ActualValue = (IItem)baseSolution.Clone();
+          CurrentNeutralDistance = 0;
+        }
+        CurrentFractionOfNeutralNeighbors = 1.0*neighbors.Count(n => n.Diff == 0)/neighbors.Count;
       }
       return base.Apply();
