// Path: src/main/java/com/asher_stern/crf/crf/CrfModel.java
// public class CrfModel<K,G> implements Serializable // K = token, G = tag
// {
// 	private static final long serialVersionUID = -5703467522848303660L;
// 	
// 	public CrfModel(CrfTags<G> crfTags, CrfFeaturesAndFilters<K, G> features, ArrayList<BigDecimal> parameters)
// 	{
// 		super();
// 		this.crfTags = crfTags;
// 		this.features = features;
// 		this.parameters = parameters;
// 	}
// 	
// 	
// 	
// 	public CrfTags<G> getCrfTags()
// 	{
// 		return crfTags;
// 	}
// 	public CrfFeaturesAndFilters<K, G> getFeatures()
// 	{
// 		return features;
// 	}
// 	public ArrayList<BigDecimal> getParameters()
// 	{
// 		return parameters;
// 	}
// 
// 
// 
// 	private final CrfTags<G> crfTags;
// 	private final CrfFeaturesAndFilters<K, G> features;
// 	private final ArrayList<BigDecimal> parameters;
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/FilterFactory.java
// public interface FilterFactory<K, G> extends Serializable
// {
// 	/**
// 	 * Creates a set of filters for the given token,tag, and tag-of-previous-token.
// 	 * The convention is as follows:
// 	 * Let each feature f be a feature that <B>might</B> return non-zero for the given token,tag,previous-tag.
// 	 * That feature is encapsulated with a {@link Filter} in a {@link CrfFilteredFeature}. Let's call this filter "t".
// 	 * For that filter there exist one filter in the set returned by this function, name it "t'", such that "t'" equals to "t".
// 	 * 
// 	 * 
// 	 * @param sequence A sequence of tokens
// 	 * @param tokenIndex An index of a token in that sequence
// 	 * @param currentTag A tag for that token
// 	 * @param previousTag A tag for the token which immediately precedes that token.
// 	 * @return A set of filters as described above.
// 	 */
// 	public Set<Filter<K, G>> createFilters(K[] sequence, int tokenIndex, G currentTag, G previousTag);
// }
// 
// Path: src/main/java/com/asher_stern/crf/utilities/TaggedToken.java
// public class TaggedToken<K,G>
// {
// 	public TaggedToken(K token, G tag)
// 	{
// 		super();
// 		this.token = token;
// 		this.tag = tag;
// 	}
// 	
// 	
// 	
// 	public K getToken()
// 	{
// 		return token;
// 	}
// 	public G getTag()
// 	{
// 		return tag;
// 	}
// 
// 	
// 
// 
// 	@Override
// 	public String toString()
// 	{
// 		return "CrfTaggedToken [getToken()=" + getToken() + ", getTag()="
// 				+ getTag() + "]";
// 	}
// 	
// 	
// 
// 
// 
// 
// 	@Override
// 	public int hashCode()
// 	{
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((tag == null) ? 0 : tag.hashCode());
// 		result = prime * result + ((token == null) ? 0 : token.hashCode());
// 		return result;
// 	}
// 
// 
// 
// 	@Override
// 	public boolean equals(Object obj)
// 	{
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		TaggedToken<?,?> other = (TaggedToken<?,?>) obj;
// 		if (tag == null)
// 		{
// 			if (other.tag != null)
// 				return false;
// 		} else if (!tag.equals(other.tag))
// 			return false;
// 		if (token == null)
// 		{
// 			if (other.token != null)
// 				return false;
// 		} else if (!token.equals(other.token))
// 			return false;
// 		return true;
// 	}
// 
// 
// 
// 
// 
// 
// 	private final K token;
// 	private final G tag;
// }


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import com.asher_stern.crf.crf.CrfModel;
import com.asher_stern.crf.crf.filters.FilterFactory;
import com.asher_stern.crf.utilities.TaggedToken;
package com.asher_stern.crf.crf.run;




/**
 * An example for usage of CRF. Don't run this class, but use it as a template for writing your own main class.
 * 
 * @author Asher Stern
 * Date: Nov 23, 2014
 *
 */
public class ExampleMain
{

	@SuppressWarnings("unchecked")
	public static void main(String[] args)
	{
		// Load a corpus into the memory
		List<List<? extends TaggedToken<String, String> >> corpus = loadCorpusWhereTokensAndTagsAreStrings();
		
		// Create trainer factory
		CrfTrainerFactory<String, String> trainerFactory = new CrfTrainerFactory<String, String>();
		
		// Optionally call trainerFactory.setRegularizationSigmaSquareFactor() to override the default regularization factor.
		
		// Create trainer
		CrfTrainer<String,String> trainer = trainerFactory.createTrainer(
				corpus,
				(Iterable<? extends List<? extends TaggedToken<String, String> >> theCorpus, Set<String> tags) -> createFeatureGeneratorForGivenCorpus(theCorpus,tags),
				createFilterFactory());

		// Run training with the loaded corpus.
		trainer.train(corpus);
		
		// Get the model
// Path: src/main/java/com/asher_stern/crf/crf/CrfModel.java
// public class CrfModel<K,G> implements Serializable // K = token, G = tag
// {
// 	private static final long serialVersionUID = -5703467522848303660L;
// 	
// 	public CrfModel(CrfTags<G> crfTags, CrfFeaturesAndFilters<K, G> features, ArrayList<BigDecimal> parameters)
// 	{
// 		super();
// 		this.crfTags = crfTags;
// 		this.features = features;
// 		this.parameters = parameters;
// 	}
// 	
// 	
// 	
// 	public CrfTags<G> getCrfTags()
// 	{
// 		return crfTags;
// 	}
// 	public CrfFeaturesAndFilters<K, G> getFeatures()
// 	{
// 		return features;
// 	}
// 	public ArrayList<BigDecimal> getParameters()
// 	{
// 		return parameters;
// 	}
// 
// 
// 
// 	private final CrfTags<G> crfTags;
// 	private final CrfFeaturesAndFilters<K, G> features;
// 	private final ArrayList<BigDecimal> parameters;
// }
// 
// Path: src/main/java/com/asher_stern/crf/crf/filters/FilterFactory.java
// public interface FilterFactory<K, G> extends Serializable
// {
// 	/**
// 	 * Creates a set of filters for the given token,tag, and tag-of-previous-token.
// 	 * The convention is as follows:
// 	 * Let each feature f be a feature that <B>might</B> return non-zero for the given token,tag,previous-tag.
// 	 * That feature is encapsulated with a {@link Filter} in a {@link CrfFilteredFeature}. Let's call this filter "t".
// 	 * For that filter there exist one filter in the set returned by this function, name it "t'", such that "t'" equals to "t".
// 	 * 
// 	 * 
// 	 * @param sequence A sequence of tokens
// 	 * @param tokenIndex An index of a token in that sequence
// 	 * @param currentTag A tag for that token
// 	 * @param previousTag A tag for the token which immediately precedes that token.
// 	 * @return A set of filters as described above.
// 	 */
// 	public Set<Filter<K, G>> createFilters(K[] sequence, int tokenIndex, G currentTag, G previousTag);
// }
// 
// Path: src/main/java/com/asher_stern/crf/utilities/TaggedToken.java
// public class TaggedToken<K,G>
// {
// 	public TaggedToken(K token, G tag)
// 	{
// 		super();
// 		this.token = token;
// 		this.tag = tag;
// 	}
// 	
// 	
// 	
// 	public K getToken()
// 	{
// 		return token;
// 	}
// 	public G getTag()
// 	{
// 		return tag;
// 	}
// 
// 	
// 
// 
// 	@Override
// 	public String toString()
// 	{
// 		return "CrfTaggedToken [getToken()=" + getToken() + ", getTag()="
// 				+ getTag() + "]";
// 	}
// 	
// 	
// 
// 
// 
// 
// 	@Override
// 	public int hashCode()
// 	{
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((tag == null) ? 0 : tag.hashCode());
// 		result = prime * result + ((token == null) ? 0 : token.hashCode());
// 		return result;
// 	}
// 
// 
// 
// 	@Override
// 	public boolean equals(Object obj)
// 	{
// 		if (this == obj)
// 			return true;
// 		if (obj == null)
// 			return false;
// 		if (getClass() != obj.getClass())
// 			return false;
// 		TaggedToken<?,?> other = (TaggedToken<?,?>) obj;
// 		if (tag == null)
// 		{
// 			if (other.tag != null)
// 				return false;
// 		} else if (!tag.equals(other.tag))
// 			return false;
// 		if (token == null)
// 		{
// 			if (other.token != null)
// 				return false;
// 		} else if (!token.equals(other.token))
// 			return false;
// 		return true;
// 	}
// 
// 
// 
// 
// 
// 
// 	private final K token;
// 	private final G tag;
// }


// Path: src/main/java/com/asher_stern/crf/crf/run/ExampleMain.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import com.asher_stern.crf.crf.CrfModel;
import com.asher_stern.crf.crf.filters.FilterFactory;
import com.asher_stern.crf.utilities.TaggedToken;

package com.asher_stern.crf.crf.run;




/**
 * An example for usage of CRF. Don't run this class, but use it as a template for writing your own main class.
 * 
 * @author Asher Stern
 * Date: Nov 23, 2014
 *
 */
public class ExampleMain
{

	@SuppressWarnings("unchecked")
	public static void main(String[] args)
	{
		// Load a corpus into the memory
		List<List<? extends TaggedToken<String, String> >> corpus = loadCorpusWhereTokensAndTagsAreStrings();
		
		// Create trainer factory
		CrfTrainerFactory<String, String> trainerFactory = new CrfTrainerFactory<String, String>();
		
		// Optionally call trainerFactory.setRegularizationSigmaSquareFactor() to override the default regularization factor.
		
		// Create trainer
		CrfTrainer<String,String> trainer = trainerFactory.createTrainer(
				corpus,
				(Iterable<? extends List<? extends TaggedToken<String, String> >> theCorpus, Set<String> tags) -> createFeatureGeneratorForGivenCorpus(theCorpus,tags),
				createFilterFactory());

		// Run training with the loaded corpus.
		trainer.train(corpus);
		
		// Get the model
		CrfModel<String, String> crfModel = trainer.getLearnedModel();