XMLC/src/util/HuffmanTree.java
public class HuffmanTree extends PrecomputedTree {
	private static Logger logger = LoggerFactory.getLogger(HuffmanTree.class);
	
	private static final long serialVersionUID = 6677270104977721765L;
	public static final String name = "HuffmanTree";
	protected int nLeaves;
	protected transient PriorityQueue<FreqTuple> freqheap;
	protected transient DataManager data;

	protected class FreqTuple implements Comparable<FreqTuple> {
		public float f;
		public TreeNode node;

		public FreqTuple(float f, TreeNode node) {
			this.f = f;
			this.node = node;
		}

		@Override
		public int compareTo(FreqTuple arg0) {
			if (f < arg0.f)
				return -1;
			if (f > arg0.f)
				return 1;
			return 0;
		}
	}

	public HuffmanTree(DataManager data, String treeFileName) {
		super(2, data.getNumberOfLabels());
		nLeaves = data.getNumberOfLabels();
		this.data = data;
		allocateFrequencies();
		buildHuffmanTree();
		writeTree(treeFileName);
	}

	public HuffmanTree(String treeFile) {
		super(treeFile);
	}

	protected void allocateFrequencies() {
		freqheap = new PriorityQueue<FreqTuple>(nLeaves);

		int[] counts = new int[nLeaves];
		int nInstances = 0;
		data.reset();
		logger.info( "Building Huffman tree...");
		while (data.hasNext() == true ) {
			Instance instance = data.getNextInstance();
			for (int i = 0; i < instance.y.length; i++) {
				counts[instance.y[i]]++;
			}
			nInstances++;
		}
		data.reset();
		
		logger.info( "Huffman tree is built based on " + nInstances + " instance." );
		
		TreeNode node;
		for (int j = 0; j < nLeaves; j++) {
			node = new TreeNode(j + 1);
			node.label = j;
			freqheap.add(new FreqTuple(((float) counts[j]) / nInstances, node));
			// Index is j+1 in order to store root of the tree at 0
			labelToIndex.put(j, j + 1);
			indexToNode.put(j + 1, node);
		}
	}

	public void buildHuffmanTree() {
		int currentIndex = nLeaves + 1; // Root is at 0
		TreeNode parent, c1, c2;
		for (int node = 0; node < this.numberOfInternalNodes; node++) {
			FreqTuple e1 = freqheap.poll();
			FreqTuple e2 = freqheap.poll();

			parent = new TreeNode(currentIndex);
			indexToNode.put(currentIndex, parent);
			c1 = e1.node;
			c2 = e2.node;
			c1.parent = parent;
			c2.parent = parent;
			parent.children.add(c1);
			parent.children.add(c2);

			FreqTuple tuple = new FreqTuple(e1.f + e2.f, parent);
			freqheap.add(tuple);
			currentIndex++;
		}
		FreqTuple root = freqheap.poll();
		indexToNode.put(0, root.node);
		indexToNode.remove(currentIndex - 1);
		root.node.index = 0;
		this.tree = root.node;
	}

}
XMLC/src/util/Tree.java
public abstract class Tree {

	protected int k = 2; //k-ary tree
	
	protected int m = 0; //number of leaves
	
	protected int size = 0; //size of the tree
	
	protected int numberOfInternalNodes = 0;
	
	public void initialize(int k, int m) {
		this.k = k ;
		this.m = m;
	}
	
	abstract public ArrayList<Integer> getChildNodes(int node);
	
	abstract public int getParent(int node);
	
	abstract public boolean isLeaf(int node); 
	
	abstract public int getTreeIndex(int label);
	
	abstract public int getLabelIndex(int treeIndex);
	
	public int getNumberOfLeaves() {
		return this.m;
	}
	
	public int getSize() {
		return this.size;
	}

	public int getNumberOfInternalNodes() {
		return this.numberOfInternalNodes;
	}
	
	
}
XMLC/src/Data/EstimatePair.java
public class EstimatePair implements Comparable<EstimatePair> {
    private double  p;
    private int label;

    public EstimatePair( int label, double p ){
    	this.label = label;
    	this.p = p;
    }
    
    public double getP() {
        return this.p;
    }

    public int getLabel() {
        return this.label;
    }
    
	public boolean equals(Object obj) {
        if(obj != null && obj instanceof EstimatePair) {
        	EstimatePair pair = (EstimatePair) obj;
            if(this.label != pair.label) return false;
            if(this.p != pair.p) return false;
            return true;
        	
        }
        return false;
    }
	
	public int hashCode() {
    
		int hash = 1;
        hash = hash * 17 + label;
        hash = hash * 31 + (int) p*1000;
        return hash;

	}

	
	@Override
	public int compareTo(EstimatePair o) {
		return Double.compare(-this.getP(),-o.getP());
	}
	
	public String toString() {
		return "[" + this.label + ", " + this.p + "]";
	}
	
}
XMLC/src/Data/NodeComparatorPLT.java
public class NodeComparatorPLT implements Comparator<NodePLT> {
    @Override
	public int compare(NodePLT n1, NodePLT n2) {
    	return (n1.p < n2.p) ? 1 : -1;
    }
} ;
XMLC/src/preprocessing/FeatureHasherFactory.java
public class FeatureHasherFactory {
	private static Logger logger = LoggerFactory.getLogger(FeatureHasherFactory.class);

	public static FeatureHasher createFeatureHasher( String hasher, int fhseed, int hd, int d ) {
		FeatureHasher fh = null;
		if ( hasher.compareTo("Universal") == 0 ) {			
			fh = new UniversalHasher(fhseed, hd, d);
		} else if ( hasher.compareTo("Murmur") == 0 ) {
			fh = new MurmurHasher(fhseed, hd, d);
		} else if ( hasher.compareTo("Mask") == 0 ) {
			fh = new MaskHasher(fhseed, hd, d);
		} else {
			logger.info("Unknown hasher");
			System.exit(-1);
		}		
		return fh;
	}

}
XMLC/src/util/CompleteTree.java
public class CompleteTree extends Tree implements Serializable {
	private static final long serialVersionUID = 5656121729850759773L;
	private static Logger logger = LoggerFactory.getLogger(CompleteTree.class);
	final static public String name = "Complete";

	//int[] childNodes = new int[this.k];
	
	public CompleteTree(int k, int m) {
		initialize(k, m);
		
	}
	
	protected int computeSize(int k, int m) {
		
		double a = Math.pow(k, Math.floor(Math.log(m)/Math.log(k)));
		
		double b = m - a;
		
		double c = Math.ceil(b/(k-1.0));

		double d = (k*a - 1.0)/(k-1.0);

		double e = m - (a - c);
		
		return (int) e + (int) d;
	}
	
	
	@Override
	public void initialize(int k, int m) {
		super.initialize(k, m);
		this.size = computeSize(k,m);
		this.numberOfInternalNodes = this.size - m;
	}
	
	@Override
	public ArrayList<Integer> getChildNodes(int node) {
		
		if(node < this.numberOfInternalNodes) {
			
			//int[] childNodes = new int[this.k];
			ArrayList<Integer> childNodes = new ArrayList<Integer>(this.k); //new int[this.k];
			
			for(int i = 0; (i < k) && (k*node + i + 1 < this.size); i++) {
				//childNodes[i] = k  * node + i + 1;
				childNodes.add(k  * node + i + 1);
			}
			return childNodes;
		}
		else return null;
	}

	@Override
	public int getParent(int node) {
		if(node > 0) {
			return (int) Math.floor((node - 1.0) / (double) this.k);
		}
		else {
			return -1;
		}
	}

	public int getTreeIndex(int label) {
		return this.numberOfInternalNodes + label;
	}
	
	public int getLabelIndex(int treeIndex) {
		return treeIndex - this.numberOfInternalNodes;
	}
	
	@Override
	public boolean isLeaf(int node) {
		return (node >= this.numberOfInternalNodes);
	}
	
	public static void main(String[] argv) {

		int k = 2, m = 933;
		CompleteTree ct = new CompleteTree(k, m);
		
		logger.info(Integer.toString(ct.getSize()));
		
	}
	
}
XMLC/src/Data/Instance.java
public class Instance {
	public int[] y;
	public AVPair[] x;

	
	public Instance(AVPair[] x, int[] y) {
		this.x = x;
		this.y = y;
	}

}
XMLC/src/Data/NodePLT.java
public class NodePLT {

	public int treeIndex;
	public double p;

	public NodePLT(int treeIndex, double p) {
		this.treeIndex = treeIndex;
		this.p = p;
	}

	@Override
	public String toString() {
		return new String("(" + this.treeIndex + ", " + this.p + ")");
	}
};
XMLC/src/Data/AVPair.java
public class AVPair {
	public int index;
	public double value;

	public AVPair() {
	}

	public AVPair(int index, double value) {
		this.index = index;
		this.value = value;
	}
}
XMLC/src/preprocessing/FeatureHasher.java
public interface FeatureHasher {
	
	public AVPair[] transformRowSparse(AVPair[] row);
	public AVPair[] transformRowSparse(AVPair[] row, int taskid);
	public AVTable transformSparse(AVTable data);
	public int getIndex(int task, int feature);
	public int getSign( int task, int feature );
	
}
XMLC/src/util/PrecomputedTree.java
public class PrecomputedTree extends Tree implements Serializable {
	private static final long serialVersionUID = 5656121729850759773L;
	private static Logger logger = LoggerFactory.getLogger(PrecomputedTree.class);
	final static public String name = "Precomputed";

	transient TreeNode tree;
	transient Map<Integer, TreeNode> indexToNode = new HashMap<Integer, TreeNode>();
	transient Map<Integer, Integer> labelToIndex = new HashMap<Integer, Integer>();

	public PrecomputedTree(int k, int m) {
		this.size = 2 * m - 1;
		this.k = k;
		this.numberOfInternalNodes = (int) this.size / 2;
	}

	public PrecomputedTree(String treeFileName) {
		initialize(treeFileName);
		this.size = this.indexToNode.size();
		this.numberOfInternalNodes = (int) this.size / 2;
	}

	public class TreeNode {
		public int index;
		public int label;
		public TreeNode parent;
		public List<TreeNode> children;

		public TreeNode(int index) {
			this.index = index;
			this.label = -1;
			this.parent = null;
			this.children = new ArrayList<TreeNode>();
		}

		public boolean isLeaf() {
			if (this.children.size() > 0)
				return false;
			return true;
		}
	}

	public void initialize(String treeFileName) {
		readTreeFile(treeFileName);
		super.initialize(this.k, this.m);
	}

	protected void readTreeFile(String treeFileName) {
		File file = null;
		Scanner inputScanner = null;
		try {

			file = new File(treeFileName);
			inputScanner = new Scanner(file);

			while (inputScanner.hasNextInt()) {
				int parent = inputScanner.nextInt();
				int child = inputScanner.nextInt();

				if (parent == child) { // root
					this.tree = new TreeNode(parent);
					this.indexToNode.put(parent, this.tree);
				} else if (child > 0) { // internal node
					TreeNode node = new TreeNode(child);
					TreeNode parent_node = this.indexToNode.get(new Integer(parent));
					node.parent = parent_node;
					parent_node.children.add(node);
					this.indexToNode.put(child, node);
				} else { // leaf and label index
					int label = -child;
					TreeNode node = this.indexToNode.get(new Integer(parent));
					node.label = label;
					this.labelToIndex.put(label, parent);
					assert (node.children.size() == 0);
				}
			}

			inputScanner.close();
		} catch (java.io.IOException e) {
			e.printStackTrace();
		}
	}

	protected String bfsTree() {
		StringBuilder str = new StringBuilder();

		LinkedList<Integer> indexes = new LinkedList<>();
		indexes.add(0);
		str.append(0 + " " + 0 + "\n");
		int i;
		ArrayList<Integer> children;
		while (!indexes.isEmpty()) {
			i = indexes.poll();
			if (isLeaf(i)) {
				str.append(i + " " + -getLabelIndex(i) + "\n");
			} else {
				children = getChildNodes(i);
				for (Integer child : children) {
					str.append(i + " " + child + "\n");
				}
				indexes.addAll(children);
			}
		}
		return str.toString();
	}

	protected void writeTree(String treeFileName) {
		File file;
		Writer wr;
		try {
			file = new File(treeFileName);
			wr = new FileWriter(file);
			wr.write(bfsTree());
			wr.close();
		} catch (java.io.IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public ArrayList<Integer> getChildNodes(int nodeIndex) {
		TreeNode node = this.indexToNode.get(new Integer(nodeIndex));
		if (!node.isLeaf()) {
			ArrayList<Integer> childNodes = new ArrayList<>();

			for (int i = 0; i < node.children.size(); i++) {
				childNodes.add(node.children.get(i).index);
			}
			return childNodes;
		} else {
			return null;
		}
	}

	@Override
	public int getParent(int nodeIndex) {
		TreeNode node = this.indexToNode.get(nodeIndex);
		if (node.parent == null)
			return -1;
		return node.parent.index;
	}

	public int getTreeIndex(int label) {
		return this.labelToIndex.get(label);
	}

	public int getLabelIndex(int nodeIndex) {
		return this.indexToNode.get(nodeIndex).label;
	}

	@Override
	public boolean isLeaf(int nodeIndex) {
		return this.indexToNode.get(nodeIndex).isLeaf();
	}

	public static void main(String[] argv) {
		String treeFile = "examples/huffmantree";
		System.out.println(treeFile);
		PrecomputedTree ct = new PrecomputedTree(treeFile);
		for (int i = 0; i < ct.indexToNode.size(); i++) {
			System.out.println("-------------------");
			TreeNode currNode = (TreeNode) ct.indexToNode.get(i);
			System.out.println("index: " + currNode.index);
			System.out.println("label: " + currNode.label);
			System.out.println("parent: " + ct.getParent(i));
			System.out.println("children: " + ct.getChildNodes(i));
			System.out.println("isLeaf: " + ct.isLeaf(i));
		}
		System.out.println("-------------------");
		int treeIndex = 2;
		System.out.println("Label of tree index " + treeIndex + ": " + ct.getLabelIndex(treeIndex));
		treeIndex = 5;
		System.out.println("Label of tree index " + treeIndex + ": " + ct.getLabelIndex(treeIndex));

		int labelIndex = 3;
		System.out.println("Tree index of label " + labelIndex + ": " + ct.getTreeIndex(labelIndex));
		labelIndex = 2;
		System.out.println("Tree index of label " + labelIndex + ": " + ct.getTreeIndex(labelIndex));

	}

}
XMLC/src/IO/DataManager.java
public abstract class DataManager {
	static Logger logger = LoggerFactory.getLogger(DataManager.class);
	
	public abstract boolean hasNext();
	public abstract Instance getNextInstance();
	public abstract int getNumberOfFeatures();
	public abstract int getNumberOfLabels();
	public abstract void setInputStream( InputStreamReader input );
	public abstract void reset();
	public abstract DataManager getCopy();
	public void close() {};
	
	public static DataManager managerFactory(String filename, String datamanagertype ) {
		DataManager datamanager = null;
				
		if (datamanagertype.compareTo( "Batch" ) == 0)
			datamanager = new BatchDataManager(filename);
		else if (datamanagertype.compareTo("Online") == 0)
			datamanager = new OnlineDataManager(filename);
		else {
			System.err.println("Unknown data manager");
			System.exit(-1);
		}
				
		return datamanager;		
		
	}
}
XMLC/src/Data/ComparablePair.java
public class ComparablePair implements Comparable<ComparablePair> {
    private double  key;
    private int value;

    public ComparablePair( double key, int value ){
    	this.key = key;
    	this.value = value;
    }
    
    public double getKey() {
        return key;
    }

    public int getValue() {
        return value;
    }


	@Override
	public int compareTo(ComparablePair o) {
		return Double.compare(this.getKey(),o.getKey());
	}
}	


Question: package Learner;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Properties;
import java.util.TreeSet;
import org.apache.commons.math3.analysis.function.Sigmoid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import Data.AVPair;
import Data.ComparablePair;
import Data.EstimatePair;
import Data.Instance;
import Data.NodeComparatorPLT;
import Data.NodePLT;
import IO.DataManager;
import preprocessing.FeatureHasher;
import preprocessing.FeatureHasherFactory;
import util.CompleteTree;
import util.HuffmanTree;
import util.PrecomputedTree;
import util.Tree;



//import Data.AVTable;

public class PLT extends AbstractLearner {
	private static final long serialVersionUID = 1L;
	private static Logger logger = LoggerFactory.getLogger(PLT.class);
	/**
	 * Number of inner node of the trees
	 */
	transient protected int t = 0;	
	protected Tree tree = null;
	
	/**
	 * Order of the tree (k-ary).
	 */
	protected int k = 2;
	protected String treeType = "Complete";
	protected String treeFile = null;

	transient protected int T = 1;
	//transient protected AVTable traindata = null;
	transient protected DataManager traindata = null;
	
	
	transient protected FeatureHasher fh = null;
	protected String hasher = "Universal";
	protected int fhseed = 1;
	/**
	 * Hashed dimension, i.e. number of ML hashed features.
	 */
	protected int hd;
	
	protected double[] bias;
	protected double[] w = null;
	
	transient protected int[] Tarray = null;	
	protected double[] scalararray = null;

	protected double gamma = 0; // learning rate
	transient protected int step = 0;
	static Sigmoid s = new Sigmoid();
	transient protected double learningRate = 1.0;
	protected double scalar = 1.0;
	protected double lambda = 0.00001;
	protected int epochs = 1;	
		
	
	public PLT(Properties properties) {
		super(properties);
		
		System.out.println("#####################################################" );
		System.out.println("#### Learner: PLT" );
		// learning rate
		this.gamma = Double.parseDouble(this.properties.getProperty("gamma", "1.0"));
		logger.info("#### gamma: " + this.gamma );

		// scalar
		this.lambda = Double.parseDouble(this.properties.getProperty("lambda", "1.0"));
		logger.info("#### lambda: " + this.lambda );

		// epochs
		this.epochs = Integer.parseInt(this.properties.getProperty("epochs", "30"));
		logger.info("#### epochs: " + this.epochs );

		// epochs
		this.hasher = this.properties.getProperty("hasher", "Mask");
		logger.info("#### Hasher: " + this.hasher );
		
		
		this.hd = Integer.parseInt(this.properties.getProperty("MLFeatureHashing", "50000000")); 
		logger.info("#### Number of ML hashed features: " + this.hd );
		

		// k-ary tree
		this.k = Integer.parseInt(this.properties.getProperty("k", "2"));
		logger.info("#### k (order of the tree): " + this.k );

		// tree type (Complete, Precomputed, Huffman)
		this.treeType = this.properties.getProperty("treeType", "Complete");
		logger.info("#### tree type " + this.treeType );

		// tree file name
		this.treeFile = this.properties.getProperty("treeFile", null);
		logger.info("#### tree file name " + this.treeFile );

		System.out.println("#####################################################" );

	}

	public void printParameters() {
		super.printParameters();
		logger.info("#### gamma: " + this.gamma );
		logger.info("#### lambda: " + this.lambda );		
		logger.info("#### epochs: " + this.epochs );
		logger.info("#### Hasher: " + this.hasher );
		logger.info("#### Number of ML hashed features: " + this.hd );
		logger.info("#### k (order of the tree): " + this.k );		
		logger.info("#### tree type: " + this.treeType );
		logger.info("#### tree file: " + this.treeFile );
	}
	
	
	@Override
	public void allocateClassifiers(DataManager data) {
		this.traindata = data;
		this.m = data.getNumberOfLabels();
		this.d = data.getNumberOfFeatures();
		
		switch (this.treeType){
			case CompleteTree.name:
				this.tree = new CompleteTree(this.k, this.m);
				break;
			case PrecomputedTree.name:
				this.tree = new PrecomputedTree(this.treeFile);
				break;
Answer: 			case HuffmanTree.name: