/***************************************************************************************************
*             C# sample for the usage of Episodic TopoART (class Fast_Episodic_TopoART)            *
****************************************************************************************************
*                           Created by Marko Tscherepanow, 20 October 2012                         *
***************************************************************************************************/

// Compile and run from the console: dotnet run --project Episodic_TopoART_sample1.csproj

using System;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using LibTopoART;
using System.Globalization;

namespace LibTopoART_samples
{
	/// <summary>
	/// Episodic clustering sample using synthetic two-dimensional data. [C#]
	/// <para>
	/// Like in Section 4.1 of "Marko Tscherepanow, Sina Kühnel, and Sören Riechers (2012). Episodic 
	/// Clustering of Data Streams Using a Topology-Learning Neural Network. In Proceedings of the European 
	/// Conference on Artificial Intelligence (ECAI), Workshop on Active and Incremental Learning (AIL), 
	/// pp. 24-29. Montpellier, France.", an Episodic TopoART network is trained with the well-known Two 
	/// Spirals dataset. Due to the incorporation of temporal information during learning, Episodic TopoART 
	/// is capable of creating two clusters each representing one spiral in an unsupervised way. 
	/// These clusters are formed by the nodes of module b (ETA b).
	/// </para>
	/// <para>The resulting network can be visualised using the script <c>ShowEpisodicTopoARTResults</c> 
	/// provided for R and MATLAB in the subfolder <c>visualisation</c>.
	/// </para>
	/// </summary>
	class Episodic_TopoART_sample1
	{
		private static void Main()
		{
			// Dataset
			const string dataset		=	"../../../../../data/TwoSpirals_dataset.txt";
			// Destination directory for trained networks
			const string networkPath	=	"../../../../../results/networks/";

			const long sampleNumber		=	194;
			const long inputDimension	=	2;

			var inputs = new decimal[sampleNumber][];

			// Set working directory to assembly directory
			Directory.SetCurrentDirectory(Path.GetDirectoryName(new Uri(Assembly.GetEntryAssembly().Location).LocalPath));

			// Load dataset
			using(var datasetFile = new StreamReader(File.OpenRead(dataset))) {
				for(long i = 0; i < sampleNumber; ++i) {
					var numbers = Regex.Split(datasetFile.ReadLine(), @"\s+");
					inputs[i] = new decimal[inputDimension]; 
					inputs[i][0] = Decimal.Parse(numbers[1], NumberStyles.Float, CultureInfo.InvariantCulture);
					inputs[i][1] = Decimal.Parse(numbers[2], NumberStyles.Float, CultureInfo.InvariantCulture);
					inputs[i][0] = (inputs[i][0] + 7.0m) / 14m;
					inputs[i][1] = (inputs[i][1] + 7.0m) / 14m;
				}
			}

			// Initialise an Episodic TopoART network with appropriate parameter values (taken from the paper
			// given above)
			Fast_Episodic_TopoART feta = new Fast_Episodic_TopoART(inputDimension, 2, 0.69m, 200)
				{ Beta_sbm = 0.0m, Phi = 1, Tau = 200 };

			// Train network
			for(long i = 0; i < sampleNumber; ++i) 
				feta.Learn(inputs[i]);

			// Determine clusters
			feta.ComputeClusterIDs();

			// Save network in human-readable form
			feta.SaveText(networkPath + "Fast_Episodic_TopoART_TwoSpirals_dataset.txt");

			// Save network in binary form
			feta.Save(networkPath + "Fast_Episodic_TopoART_TwoSpirals_dataset.feta");
		}
	}
}