package edu.stanford.nlp.sempre.tables.alter;
import java.util.*;
public class Subset {
public final String id;
public final List<Integer> indices;
public final double score;
public Subset(String id, List<Integer> indices, double score) {
this.id = id;
this.indices = indices;
this.score = score;
}
// Subset {0, 1, 2, ..., k}
public Subset(String id, int k, double score) {
this.id = id;
this.indices = new ArrayList<>(k + 1);
for (int i = 0; i <= k; i++)
this.indices.add(i);
this.score = score;
}
// NULL subset with very negative score
public Subset(String id) {
this.id = id;
this.indices = new ArrayList<>();
this.score = Double.NEGATIVE_INFINITY;
}
// Format: ID <tab> score <tab> space-separated tables
public static Subset fromString(String line) {
String[] tokens = line.trim().split("\t");
if (tokens.length != 3)
throw new RuntimeException("Expected 3 fields; got " + tokens.length);
String[] indicesString = tokens[2].split(" ");
List<Integer> indices = new ArrayList<>(indicesString.length);
for (String x : indicesString)
indices.add(Integer.parseInt(x));
return new Subset(tokens[0], indices, Double.parseDouble(tokens[1]));
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder().append(id)
.append("\t").append(score).append("\t");
for (int graphIndex : indices) {
sb.append(graphIndex).append(" ");
}
return sb.toString().trim();
}
public static boolean areDisjoint(Collection<Integer> x1, Collection<Integer> x2) {
for (int x : x1)
if (x2.contains(x)) return false;
return true;
}
/**
* Iterate all subsets of size k of {1,...,n} in lexicographic order.
*/
public static class SubsetSizeKIterator implements Iterator<List<Integer>> {
List<Integer> next = new ArrayList<>(), last = new ArrayList<>();
public SubsetSizeKIterator(int numAlteredTables, int numRetainedTables) {
for (int i = 1; i <= numRetainedTables; i++) {
next.add(i);
last.add(numAlteredTables - numRetainedTables + i);
}
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public List<Integer> next() {
List<Integer> newNext = new ArrayList<>(), current = next;
int changeIndex, changeValue;
for (changeIndex = next.size() - 1; changeIndex >= 0; changeIndex--)
if (next.get(changeIndex) != last.get(changeIndex)) break;
if (changeIndex < 0) {
next = null;
} else {
changeValue = next.get(changeIndex) + 1;
for (int i = 0; i < changeIndex; i++)
newNext.add(next.get(i));
for (int i = 0; newNext.size() < next.size(); i++)
newNext.add(changeValue + i);
next = newNext;
}
return current;
}
}
/**
* Iterate all subsets of size AT MOST k of {1,...,n}.
* Smaller subsets are generated first.
*/
public static class SubsetSizeAtMostKIterator implements Iterator<List<Integer>> {
int numAlteredTables, numRetainedTables, currentK;
SubsetSizeKIterator sizeKIterator;
public SubsetSizeAtMostKIterator(int numAlteredTables, int numRetainedTables) {
this.numAlteredTables = numAlteredTables;
this.numRetainedTables = numRetainedTables;
this.currentK = 1;
this.sizeKIterator = new SubsetSizeKIterator(numAlteredTables, currentK);
}
@Override
public boolean hasNext() {
return currentK < numRetainedTables || sizeKIterator.hasNext();
}
@Override
public List<Integer> next() {
if (!sizeKIterator.hasNext()) {
currentK++;
sizeKIterator = new SubsetSizeKIterator(numAlteredTables, currentK);
}
return sizeKIterator.next();
}
}
}