package com.googlecode.gaal.suffix.impl;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
import com.googlecode.gaal.data.api.IntSequence;
import com.googlecode.gaal.data.impl.ArraySequence;
import com.googlecode.gaal.suffix.api.EnhancedSuffixArray;
import com.googlecode.gaal.suffix.api.IntervalTree.Interval;
import com.googlecode.gaal.suffix.api.SuffixTree.Node;
import com.googlecode.gaal.suffix.impl.EnhancedSuffixArrayImpl;
public class EnhancedSuffixArrayImplTest {
// caggtcagtcacggtatca#
private static final int[] text = { 2, 1, 3, 3, 4, 2, 1, 3, 4, 2, 1, 2, 3, 3, 4, 1, 4, 2, 1, 5 };
private static final String[] alphabet = { null, "a", "c", "g", "t", "#" };
private static final int[] suffixTable = { 10, 1, 6, 15, 18, 9, 0, 5, 17, 11, 12, 2, 13, 7, 3, 14, 8, 4, 16, 19 };
private static final int[] prefixTable = { 18, 1, 9, 13, 4, 19, 8, 2, 10, 14, 17, 12, 7, 16, 6, 3, 11, 15, 5, 0 };
private static final int[] sLcpTable = { -1, 1, 2, 1, 1, 0, 2, 3, 2, 1, 0, 3, 1, 2, 4, 0, 1, 3, 3, 0 };
private static final int[] pLcpTable = { -1, 2, 3, 4, 1, 0, 1, 1, 2, 3, 0, 3, 1, 1, 2, 0, 1, 2, 3, 0 };
private static final int[] sChildTable = { 5, 3, 2, 4, 1, 10, 8, 7, 6, 9, 15, 11, 13, 14, 12, 19, 17, 18, 16, 0 };
private static final int[] pChildTable = { 5, 2, 3, 1, 4, 10, 7, 8, 9, 6, 15, 11, 13, 14, 12, 19, 17, 18, 16, 0 };
private static final IntervalImpl[][] children;
static {
children = new IntervalImpl[11][];
children[0] = new IntervalImpl[] { new IntervalImpl(0, 4, 1), new IntervalImpl(5, 9, 1),
new IntervalImpl(10, 14, 1), new IntervalImpl(15, 18, 1), new IntervalImpl(19, 19, -1) };
children[1] = new IntervalImpl[] { new IntervalImpl(0, 0, -1), new IntervalImpl(1, 2, 2),
new IntervalImpl(3, 3, -1), new IntervalImpl(4, 4, -1), new IntervalImpl(5, 8, 2),
new IntervalImpl(9, 9, -1), new IntervalImpl(10, 11, 3), new IntervalImpl(12, 14, 2),
new IntervalImpl(15, 15, -1), new IntervalImpl(16, 18, 3) };
children[2] = new IntervalImpl[] { new IntervalImpl(1, 1, -1), new IntervalImpl(2, 2, -1),
new IntervalImpl(5, 5, -1), new IntervalImpl(6, 7, 3), new IntervalImpl(8, 8, -1),
new IntervalImpl(10, 10, -1), new IntervalImpl(11, 11, -1), new IntervalImpl(12, 12, -1),
new IntervalImpl(13, 14, 4), new IntervalImpl(16, 16, -1), new IntervalImpl(17, 17, -1),
new IntervalImpl(18, 18, -1) };
children[3] = new IntervalImpl[] { new IntervalImpl(6, 6, -1), new IntervalImpl(7, 7, -1),
new IntervalImpl(13, 13, -1), new IntervalImpl(14, 14, -1) };
}
private static final IntervalImpl[] preOrder = { new IntervalImpl(0, 19, 0), new IntervalImpl(0, 4, 1),
new IntervalImpl(0, 0, -1), new IntervalImpl(1, 2, 2), new IntervalImpl(1, 1, -1),
new IntervalImpl(2, 2, -1), new IntervalImpl(3, 3, -1), new IntervalImpl(4, 4, -1),
new IntervalImpl(5, 9, 1), new IntervalImpl(5, 8, 2), new IntervalImpl(5, 5, -1),
new IntervalImpl(6, 7, 3), new IntervalImpl(6, 6, -1), new IntervalImpl(7, 7, -1),
new IntervalImpl(8, 8, -1), new IntervalImpl(9, 9, -1), new IntervalImpl(10, 14, 1),
new IntervalImpl(10, 11, 3), new IntervalImpl(10, 10, -1), new IntervalImpl(11, 11, -1),
new IntervalImpl(12, 14, 2), new IntervalImpl(12, 12, -1), new IntervalImpl(13, 14, 4),
new IntervalImpl(13, 13, -1), new IntervalImpl(14, 14, -1), new IntervalImpl(15, 18, 1),
new IntervalImpl(15, 15, -1), new IntervalImpl(16, 18, 3), new IntervalImpl(16, 16, -1),
new IntervalImpl(17, 17, -1), new IntervalImpl(18, 18, -1), new IntervalImpl(19, 19, -1) };
private EnhancedSuffixArray esa;
private EnhancedSuffixArray epa;
@Before
public void setUp() throws Exception {
IntSequence sequence = new ArraySequence(text);
esa = new EnhancedSuffixArrayImpl(sequence, alphabet.length - 1);
epa = new EnhancedSuffixArrayImpl(sequence.reverse(), alphabet.length - 1);
}
@Test
public void testGetChildTable() {
assertArrayEquals(sChildTable, esa.getChildTable());
assertArrayEquals(pChildTable, epa.getChildTable());
}
@Test
public void testTop() {
Interval top = esa.top();
assertTrue(top.left() == 0);
assertTrue(top.right() == text.length - 1);
assertTrue(top.lcp() == 0);
}
@Test
public void testChildIterator() {
compareChildren(esa.top(), 1, new int[4]);
}
private void compareChildren(Node node, int depth, int[] levelCounter) {
Iterator<Node> iterator = node.childIterator();
assertTrue("terminal or has next test failed", node.isTerminal() || iterator.hasNext());
while (iterator.hasNext()) {
Node child = iterator.next();
IntervalImpl ref = children[depth - 1][levelCounter[depth - 1]++];
System.out.println(node + " -> " + child);
if (!ref.equals(child)) {
System.err.println(ref + " != " + child + "," + depth);
fail("child mismatch");
} else {
System.out.println(ref + " == " + child + "," + depth);
}
compareChildren(child, depth + 1, levelCounter);
System.out.println("going up...");
}
}
@Test
public void testTraversePreOrder() {
Iterator<Node> iterator = esa.preorderIterator();
int i = 0;
while (iterator.hasNext()) {
Interval node = iterator.next();
IntervalImpl ref = preOrder[i++];
if (!ref.equals(node)) {
System.err.println(ref + " != " + node);
fail("node mismatch");
} else {
System.out.println(ref + " == " + node);
}
}
assertTrue(i == preOrder.length);
}
@Test
public void testGetSuffixTable() {
assertArrayEquals(suffixTable, esa.getSuffixTable());
assertArrayEquals(prefixTable, epa.getSuffixTable());
}
@Test
public void testGetLcpTable() {
assertArrayEquals(sLcpTable, esa.getLcpTable());
assertArrayEquals(pLcpTable, epa.getLcpTable());
}
@Test
public void testAlpabetSize() {
assertTrue(esa.alphabetSize() == alphabet.length - 1);
}
public static class IntervalImpl implements Interval {
private final int left;
private final int right;
private final int lcp;
protected IntervalImpl(int left, int right, int lcp) {
this.left = left;
this.right = right;
this.lcp = lcp;
}
@Override
public int left() {
return left;
}
@Override
public int right() {
return right;
}
@Override
public int lcp() {
return lcp;
}
@Override
public int size() {
return right - left + 1;
}
@Override
public boolean isTerminal() {
return left == right;
}
@Override
public IntSequence indices() {
throw new UnsupportedOperationException();
}
@Override
public IntSequence label() {
throw new UnsupportedOperationException();
}
@Override
public IntSequence edgeLabel(Interval parent) {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return String.format("%d-%d:%d", left, right, lcp());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + lcp;
result = prime * result + left;
result = prime * result + right;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Interval))
return false;
Interval other = (Interval) obj;
if (lcp != other.lcp())
return false;
if (left != other.left())
return false;
if (right != other.right())
return false;
return true;
}
}
}