BotSharp/BotSharp.MachineLearning/Entropy/IO/GisModelWriter.cs
2018-07-28 13:01:22 -05:00

314 lines
11 KiB
C#

//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 GISModeWriter.java source file found in the
//original java implementation of MaxEnt. That source file contains the following header:
// Copyright (C) 2001 Jason Baldridge and Gann Bierner
//
// 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 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.
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.MachineLearning.IO
{
/// <summary> Abstract parent class for GIS model writers that save data to a single
/// file. It provides the persist method which takes care of the structure of a stored
/// document, and requires an extending class to define precisely how the data should
/// be stored.
/// </summary>
/// <author>
/// Jason Baldridge
/// </author>
/// <author>
/// Richard J. Northedge
/// </author>
/// <version>
/// based on GISModelWriter.java, $Revision: 1.5 $, $Date: 2004/06/11 20:51:36 $
/// </version>
public abstract class GisModelWriter
{
private PatternedPredicate[] mPredicates;
/// <summary>
/// Implement as needed for the format the model is stored in.
/// </summary>
/// <param name="data">
/// string data to be written to storage.
/// </param>
protected abstract void WriteString(string data);
/// <summary>
/// Implement as needed for the format the model is stored in.
/// </summary>
/// <param name="data">
/// Integer data to be written to storage.
/// </param>
protected abstract void WriteInt32(int data);
/// <summary>
/// Implement as needed for the format the model is stored in.
/// </summary>
/// <param name="data">
/// Double precision floating point data to be written to storage.
/// </param>
protected abstract void WriteDouble(double data);
/// <summary>
/// Obtains a list of the predicates in the model to be written to storage.
/// </summary>
/// <returns>
/// Array of PatternedPredicate objects containing the predicate data for the model.
/// </returns>
protected PatternedPredicate[] GetPredicates()
{
return mPredicates;
}
/// <summary>
/// Sets the list of predicates to be written to storage.
/// </summary>
/// <param name="predicates">
/// Array of PatternedPredicate objects to be persisted.
/// </param>
protected void SetPredicates(PatternedPredicate[] predicates)
{
mPredicates = predicates;
}
/// <summary>
/// Writes the model to persistent storage, using the <code>writeX()</code> methods
/// provided by extending classes.
///
/// <p>This method delegates to worker methods for each part of this
/// sequence. If you are creating a writer that conforms largely to this
/// sequence but varies at one or more points, override the relevant worker
/// method(s) to achieve the required format.</p>
///
/// <p>If you are creating a writer for a format which does not follow this
/// sequence at all, override this method and ignore the
/// other WriteX methods provided in this abstract class.</p>
/// </summary>
/// <param name="model">
/// GIS model whose data is to be persisted.
/// </param>
protected void Persist(GisModel model)
{
Initialize(model);
WriteModelType("GIS");
WriteCorrectionConstant(model.CorrectionConstant);
WriteCorrectionParameter(model.CorrectionParameter);
WriteOutcomes(model.GetOutcomeNames());
WritePredicates(model);
}
/// <summary>
/// Organises the data available in the GIS model into a structure that is easier to
/// persist from.
/// </summary>
/// <param name="model">
/// The GIS model to be persisted.
///</param>
protected virtual void Initialize(GisModel model)
{
//read the predicates from the model
Dictionary<string, PatternedPredicate> predicates = model.GetPredicates();
//build arrays of predicates and predicate names from the dictionary
mPredicates = new PatternedPredicate[predicates.Count];
var predicateNames = new string[predicates.Count];
predicates.Values.CopyTo(mPredicates, 0);
predicates.Keys.CopyTo(predicateNames, 0);
//give each PatternedPredicate in the array the name taken from the dictionary keys
for (int currentPredicate = 0; currentPredicate < predicates.Count; currentPredicate++)
{
mPredicates[currentPredicate].Name = predicateNames[currentPredicate];
}
//sort the PatternedPredicate array based on the outcome pattern that each predicate uses
Array.Sort(mPredicates, new OutcomePatternIndexComparer());
}
/// <summary>
/// Writes the model type identifier at the beginning of the file.
/// </summary>
/// <param name="modelType">string identifying the model type.</param>
protected virtual void WriteModelType(string modelType)
{
WriteString(modelType);
}
/// <summary>
/// Writes the value of the correction constant
/// </summary>
/// <param name="correctionConstant">the model's correction constant value.</param>
protected virtual void WriteCorrectionConstant(int correctionConstant)
{
WriteInt32(correctionConstant);
}
/// <summary>
/// Writes the value of the correction constant parameter.
/// </summary>
/// <param name="correctionParameter">the model's correction constant parameter.</param>
protected virtual void WriteCorrectionParameter(double correctionParameter)
{
WriteDouble(correctionParameter);
}
/// <summary>
/// Writes the outcome labels to the file.
/// </summary>
/// <param name="outcomeLabels">string array of outcome labels.</param>
protected virtual void WriteOutcomes(string[] outcomeLabels)
{
//write the number of outcomes
WriteInt32(outcomeLabels.Length);
//write each label
foreach (string label in outcomeLabels)
{
WriteString(label);
}
}
/// <summary>
/// Writes the predicate information to the model file.
/// </summary>
/// <param name="model">The GIS model to write the data from.</param>
protected virtual void WritePredicates(GisModel model)
{
WriteOutcomePatterns(model.GetOutcomePatterns());
WritePredicateNames();
WriteParameters();
}
/// <summary>
/// Writes the outcome pattern data to the file.
/// </summary>
/// <param name="outcomePatterns">
/// Array of outcome patterns, each an integer array containing
/// the number of predicates using the pattern, and then the list of
/// outcome IDs in the pattern.
/// </param>
protected void WriteOutcomePatterns(int[][] outcomePatterns)
{
//write the number of outcome patterns
WriteInt32(outcomePatterns.Length);
//for each pattern
foreach (int[] pattern in outcomePatterns)
{
//build a string with the pattern values separated by spaces
var outcomePatternBuilder = new StringBuilder();
for (int currentOutcome = 0; currentOutcome < pattern.Length; currentOutcome++)
{
if (currentOutcome > 0)
{
outcomePatternBuilder.Append(" ");
}
outcomePatternBuilder.Append(pattern[currentOutcome]);
}
//write the string containing pattern values to the file
WriteString(outcomePatternBuilder.ToString());
}
}
/// <summary>
/// Write the names of the predicates to the model file.
/// </summary>
protected void WritePredicateNames()
{
//write the number of predicates
WriteInt32(mPredicates.Length);
//for each predicate, write its name to the file
foreach (PatternedPredicate predicate in mPredicates)
{
WriteString(predicate.Name);
}
}
/// <summary>
/// Writes out the parameter values for all the predicates to the model file.
/// </summary>
protected void WriteParameters()
{
foreach (PatternedPredicate predicate in mPredicates)
{
for (int currentParameter = 0; currentParameter < predicate.ParameterCount; currentParameter++)
{
WriteDouble(predicate.GetParameter(currentParameter));
}
}
}
/// <summary>
/// Class to enable sorting PatternedPredicates into order based on the
/// outcome pattern index.
/// </summary>
private class OutcomePatternIndexComparer : IComparer<PatternedPredicate>
{
/// <summary>
/// Default constructor.
/// </summary>
internal OutcomePatternIndexComparer(){}
/// <summary>
/// Implementation of the IComparer interface.
/// Compares two PatternedPredicate objects and returns a value indicating whether
/// one is less than, equal to or greater than the other.
/// </summary>
/// <param name="firstPredicate">
/// First object to compare.
/// </param>
/// <param name="secondPredicate">
/// Second object to compare.
/// </param>
/// <returns>
/// -1 if the first PatternedPredicate has a lower outcome pattern index;
/// 1 if the second PatternedPredicate has a lower outcome pattern index;
/// 0 if they both have the same outcome pattern index.
/// </returns>
public virtual int Compare(PatternedPredicate firstPredicate, PatternedPredicate secondPredicate)
{
if (firstPredicate.OutcomePattern < secondPredicate.OutcomePattern)
{
return -1;
}
else if (firstPredicate.OutcomePattern > secondPredicate.OutcomePattern)
{
return 1;
}
return 0;
}
}
}
}