// 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; } } }