// Copyright (C) 2005 Richard J. Northedge
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//This file is based on the AbstractDataIndexer.java source file found in the
//original java implementation of MaxEnt.
using System;
using System.Collections.Generic;
namespace BotSharp.MachineLearning
{
///
/// Abstract base for DataIndexer implementations.
///
///
/// Tom Morton
///
///
/// Richard J. Northedge
///
public abstract class AbstractDataIndexer : ITrainingDataIndexer
{
private int[][] mContexts;
private int[] mOutcomeList;
private int[] mNumTimesEventsSeen;
private string[] mPredicateLabels;
private string[] mOutcomeLabels;
///
/// Gets an array of context data calculated from the training data.
///
///
/// Array of integer arrays, each containing the context data for an event.
///
public virtual int[][] GetContexts()
{
return mContexts;
}
///
/// Sets the array of context data calculated from the training data.
///
///
/// Array of integer arrays, each containing the context data for an event.
///
protected internal void SetContexts(int[][] newContexts)
{
mContexts = newContexts;
}
///
/// Gets an array indicating how many times each event is seen.
///
///
/// Integer array with event frequencies.
///
public virtual int[] GetNumTimesEventsSeen()
{
return mNumTimesEventsSeen;
}
///
/// Sets an array indicating how many times each event is seen.
///
///
/// Integer array with event frequencies.
///
protected internal void SetNumTimesEventsSeen(int[] newNumTimesEventsSeen)
{
mNumTimesEventsSeen = newNumTimesEventsSeen;
}
///
/// Gets an outcome list.
///
///
/// Integer array of outcomes.
///
public virtual int[] GetOutcomeList()
{
return mOutcomeList;
}
///
/// Sets an outcome list.
///
///
/// Integer array of outcomes.
///
protected internal void SetOutcomeList(int[] newOutcomeList)
{
mOutcomeList = newOutcomeList;
}
///
/// Gets an array of predicate labels.
///
///
/// Array of predicate labels.
///
public virtual string[] GetPredicateLabels()
{
return mPredicateLabels;
}
///
/// Sets an array of predicate labels.
///
///
/// Array of predicate labels.
///
protected internal void SetPredicateLabels(string[] newPredicateLabels)
{
mPredicateLabels = newPredicateLabels;
}
///
/// Gets an array of outcome labels.
///
///
/// Array of outcome labels.
///
public virtual string[] GetOutcomeLabels()
{
return mOutcomeLabels;
}
///
/// Sets an array of outcome labels.
///
///
/// Array of outcome labels.
///
protected internal void SetOutcomeLabels(string[] newOutcomeLabels)
{
mOutcomeLabels = newOutcomeLabels;
}
///
/// Sorts and uniques the array of comparable events. This method
/// will alter the eventsToCompare array -- it does an in place
/// sort, followed by an in place edit to remove duplicates.
///
///
/// a List of ComparableEvent values
///
protected internal virtual void SortAndMerge(List eventsToCompare)
{
eventsToCompare.Sort();
int eventCount = eventsToCompare.Count;
int uniqueEventCount = 1; // assertion: eventsToCompare.length >= 1
if (eventCount <= 1)
{
return; // nothing to do; edge case (see assertion)
}
ComparableEvent comparableEvent = eventsToCompare[0];
for (int currentEvent = 1; currentEvent < eventCount; currentEvent++)
{
ComparableEvent eventToCompare = eventsToCompare[currentEvent];
if (comparableEvent.Equals(eventToCompare))
{
comparableEvent.SeenCount++; // increment the seen count
eventsToCompare[currentEvent] = null; // kill the duplicate
}
else
{
comparableEvent = eventToCompare; // a new champion emerges...
uniqueEventCount++; // increment the # of unique events
}
}
//NotifyProgress("done. Reduced " + eventCount + " events to " + uniqueEventCount + ".");
mContexts = new int[uniqueEventCount][];
mOutcomeList = new int[uniqueEventCount];
mNumTimesEventsSeen = new int[uniqueEventCount];
for (int currentEvent = 0, currentStoredEvent = 0; currentEvent < eventCount; currentEvent++)
{
ComparableEvent eventToStore = eventsToCompare[currentEvent];
if (null == eventToStore)
{
continue; // this was a dupe, skip over it.
}
mNumTimesEventsSeen[currentStoredEvent] = eventToStore.SeenCount;
mOutcomeList[currentStoredEvent] = eventToStore.Outcome;
mContexts[currentStoredEvent] = eventToStore.GetPredicateIndexes();
++currentStoredEvent;
}
}
///
/// Utility method for creating a string[] array from a dictionary whose
/// keys are labels (strings) to be stored in the array and whose
/// values are the indices (integers) at which the corresponding
/// labels should be inserted.
///
///
/// a Dictionary value
///
///
/// a string[] value
///
protected internal static string[] ToIndexedStringArray(Dictionary labelToIndexMap)
{
string[] indexedArray = new string[labelToIndexMap.Count];
int[] indices = new int[labelToIndexMap.Count];
labelToIndexMap.Keys.CopyTo(indexedArray, 0);
labelToIndexMap.Values.CopyTo(indices, 0);
Array.Sort(indices, indexedArray);
return indexedArray;
}
}
}