// Path: sequence-miner/src/main/java/sequencemining/main/InferenceAlgorithms.java
// public interface InferenceAlgorithm {
// 	public Multiset<Sequence> infer(final Transaction transaction);
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/sequence/Sequence.java
// public class Sequence extends AbstractSequence implements Serializable {
// 	private static final long serialVersionUID = -2766830126344921771L;
// 
// 	/**
// 	 * Constructor
// 	 */
// 	public Sequence() {
// 		this.items = new ArrayList<>();
// 	}
// 
// 	/**
// 	 * Shallow Copy Constructor
// 	 *
// 	 * @param seq
// 	 *            sequence to shallow copy
// 	 */
// 	public Sequence(final Sequence seq) {
// 		this.items = seq.items;
// 	}
// 
// 	/**
// 	 * Constructor
// 	 *
// 	 * @param items
// 	 *            a list of items that should be added to the new sequence
// 	 */
// 	public Sequence(final List<Integer> items) {
// 		this.items = new ArrayList<>(items);
// 	}
// 
// 	/**
// 	 * Constructor
// 	 *
// 	 * @param items
// 	 *            an array of items that should be added to the new sequence
// 	 */
// 	public Sequence(final Integer... items) {
// 		this.items = new ArrayList<>(Arrays.asList(items));
// 	}
// 
// 	/**
// 	 * Join Constructor
// 	 *
// 	 * @param seqs
// 	 *            two sequences that should be joined
// 	 */
// 	public Sequence(final Sequence seq1, final Sequence seq2) {
// 		this.items = new ArrayList<>(seq1.items);
// 		this.items.addAll(seq2.items);
// 	}
// 
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/transaction/TransactionDatabase.java
// public abstract class TransactionDatabase {
// 
// 	/** Set to true if candidate generation iteration limit exceeded */
// 	private boolean iterationLimitExceeded = false;
// 
// 	/** Average cost across the transactions */
// 	private double averageCost = Double.POSITIVE_INFINITY;
// 
// 	/** Set the average cost */
// 	public void setAverageCost(final double averageCost) {
// 		this.averageCost = averageCost;
// 	}
// 
// 	/** Get the average cost */
// 	public double getAverageCost() {
// 		return averageCost;
// 	}
// 
// 	public void setIterationLimitExceeded() {
// 		iterationLimitExceeded = true;
// 	}
// 
// 	public boolean getIterationLimitExceeded() {
// 		return iterationLimitExceeded;
// 	}
// 
// 	/** Get a list of transactions */
// 	public abstract List<Transaction> getTransactionList();
// 
// 	// /** Get a JavaRDD of transactions */
// 	// public abstract JavaRDD<Transaction> getTransactionRDD();
// 	//
// 	// /** Update the transaction cache */
// 	// public abstract void updateTransactionCache(
// 	// final JavaRDD<Transaction> updatedTransactions);
// 
// 	/** Get the number of transactions in this database */
// 	public abstract int size();
// 
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/util/Tuple2.java
// public class Tuple2<T1, T2> {
// 	public final T1 _1;
// 	public final T2 _2;
// 
// 	public Tuple2(final T1 _1, final T2 _2) {
// 		this._1 = _1;
// 		this._2 = _2;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "(" + _1 + "," + _2 + ")";
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
// 		result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
// 		return result;
// 	}
// 
// 	@Override
// 	public boolean equals(final Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (!(obj instanceof Tuple2))
// 			return false;
// 		final Tuple2<?, ?> other = (Tuple2<?, ?>) obj;
// 		return (_1 == null ? other._1 == null : _1.equals(other._1))
// 				&& (_2 == null ? other._2 == null : _2.equals(other._2));
// 	}
// 
// }


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import org.apache.commons.io.FileUtils;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.common.collect.Table;
import sequencemining.main.InferenceAlgorithms.InferenceAlgorithm;
import sequencemining.sequence.Sequence;
import sequencemining.transaction.TransactionDatabase;
import sequencemining.util.Tuple2;
package sequencemining.main;






public abstract class SequenceMiningCore {

	/** Main fixed settings */
	private static final int OPTIMIZE_PARAMS_EVERY = 1;
	private static final double OPTIMIZE_TOL = 1e-5;

	protected static final Logger logger = Logger.getLogger(SequenceMiningCore.class.getName());
	public static final File LOG_DIR = new File("/tmp/");

	/** Variable settings */
	protected static Level LOG_LEVEL = Level.FINE;
	protected static long MAX_RUNTIME = 24 * 60 * 60 * 1_000; // 24hrs

	/**
	 * Learn itemsets model using structural EM
	 */
	protected static Table<Sequence, Integer, Double> structuralEM(final TransactionDatabase transactions,
// Path: sequence-miner/src/main/java/sequencemining/main/InferenceAlgorithms.java
// public interface InferenceAlgorithm {
// 	public Multiset<Sequence> infer(final Transaction transaction);
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/sequence/Sequence.java
// public class Sequence extends AbstractSequence implements Serializable {
// 	private static final long serialVersionUID = -2766830126344921771L;
// 
// 	/**
// 	 * Constructor
// 	 */
// 	public Sequence() {
// 		this.items = new ArrayList<>();
// 	}
// 
// 	/**
// 	 * Shallow Copy Constructor
// 	 *
// 	 * @param seq
// 	 *            sequence to shallow copy
// 	 */
// 	public Sequence(final Sequence seq) {
// 		this.items = seq.items;
// 	}
// 
// 	/**
// 	 * Constructor
// 	 *
// 	 * @param items
// 	 *            a list of items that should be added to the new sequence
// 	 */
// 	public Sequence(final List<Integer> items) {
// 		this.items = new ArrayList<>(items);
// 	}
// 
// 	/**
// 	 * Constructor
// 	 *
// 	 * @param items
// 	 *            an array of items that should be added to the new sequence
// 	 */
// 	public Sequence(final Integer... items) {
// 		this.items = new ArrayList<>(Arrays.asList(items));
// 	}
// 
// 	/**
// 	 * Join Constructor
// 	 *
// 	 * @param seqs
// 	 *            two sequences that should be joined
// 	 */
// 	public Sequence(final Sequence seq1, final Sequence seq2) {
// 		this.items = new ArrayList<>(seq1.items);
// 		this.items.addAll(seq2.items);
// 	}
// 
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/transaction/TransactionDatabase.java
// public abstract class TransactionDatabase {
// 
// 	/** Set to true if candidate generation iteration limit exceeded */
// 	private boolean iterationLimitExceeded = false;
// 
// 	/** Average cost across the transactions */
// 	private double averageCost = Double.POSITIVE_INFINITY;
// 
// 	/** Set the average cost */
// 	public void setAverageCost(final double averageCost) {
// 		this.averageCost = averageCost;
// 	}
// 
// 	/** Get the average cost */
// 	public double getAverageCost() {
// 		return averageCost;
// 	}
// 
// 	public void setIterationLimitExceeded() {
// 		iterationLimitExceeded = true;
// 	}
// 
// 	public boolean getIterationLimitExceeded() {
// 		return iterationLimitExceeded;
// 	}
// 
// 	/** Get a list of transactions */
// 	public abstract List<Transaction> getTransactionList();
// 
// 	// /** Get a JavaRDD of transactions */
// 	// public abstract JavaRDD<Transaction> getTransactionRDD();
// 	//
// 	// /** Update the transaction cache */
// 	// public abstract void updateTransactionCache(
// 	// final JavaRDD<Transaction> updatedTransactions);
// 
// 	/** Get the number of transactions in this database */
// 	public abstract int size();
// 
// }
// 
// Path: sequence-miner/src/main/java/sequencemining/util/Tuple2.java
// public class Tuple2<T1, T2> {
// 	public final T1 _1;
// 	public final T2 _2;
// 
// 	public Tuple2(final T1 _1, final T2 _2) {
// 		this._1 = _1;
// 		this._2 = _2;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return "(" + _1 + "," + _2 + ")";
// 	}
// 
// 	@Override
// 	public int hashCode() {
// 		final int prime = 31;
// 		int result = 1;
// 		result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
// 		result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
// 		return result;
// 	}
// 
// 	@Override
// 	public boolean equals(final Object obj) {
// 		if (this == obj)
// 			return true;
// 		if (!(obj instanceof Tuple2))
// 			return false;
// 		final Tuple2<?, ?> other = (Tuple2<?, ?>) obj;
// 		return (_1 == null ? other._1 == null : _1.equals(other._1))
// 				&& (_2 == null ? other._2 == null : _2.equals(other._2));
// 	}
// 
// }


// Path: sequence-miner/src/main/java/sequencemining/main/SequenceMiningCore.java
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import org.apache.commons.io.FileUtils;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.common.collect.Table;
import sequencemining.main.InferenceAlgorithms.InferenceAlgorithm;
import sequencemining.sequence.Sequence;
import sequencemining.transaction.TransactionDatabase;
import sequencemining.util.Tuple2;

package sequencemining.main;






public abstract class SequenceMiningCore {

	/** Main fixed settings */
	private static final int OPTIMIZE_PARAMS_EVERY = 1;
	private static final double OPTIMIZE_TOL = 1e-5;

	protected static final Logger logger = Logger.getLogger(SequenceMiningCore.class.getName());
	public static final File LOG_DIR = new File("/tmp/");

	/** Variable settings */
	protected static Level LOG_LEVEL = Level.FINE;
	protected static long MAX_RUNTIME = 24 * 60 * 60 * 1_000; // 24hrs

	/**
	 * Learn itemsets model using structural EM
	 */
	protected static Table<Sequence, Integer, Double> structuralEM(final TransactionDatabase transactions,
			final Table<Sequence, Integer, Double> sequences, final InferenceAlgorithm inferenceAlgorithm,