一些信息
我正在开发一个适用于基本设置和反链的程序。
Antichains是一个集合的幂集的子集,因此该子集中的任何两个元素(集)都不是该子集中的另一个元素(集)的子集。例如{{1},{1,2}}不是反链,因为{1}⊆{1,2}。
在反链A和B上一些最重要的操作可以定义为
其中sup是反链的supremum,表示大于给定集合的最小反链。
到目前为止的代表性
基本集合由类似于bitarray的
long
表示。这意味着该位集合中的每个元素在位数组中均由1表示。例如,集合{1,2,3}由7(位阵列111)表示,集合{1,2,4}由11(位阵列1011)表示,依此类推。现在,我想提升这种表示方式,以类似的方式表示反链。这意味着我可以在位数组中将反链{{1},{2,3}}表示为1000010,因为存储集{1}的长值是1,而对于{2,3}来说,长值是6(位数组中为1)。
除非找到更好的替代方法,否则我将使用BitSet -class来处理此位数组,以期节省使用任何
Collection<T>
的时间。我已经设法定义和优化了前面提到的大多数基本操作,但是在较旧的实现中,仅使用了
TreeSet
对它们进行了优化,因此并未针对使用位数组进行优化。我的问题
BigInteger
,它具有可比的优势(我也需要)。 提前致谢。
编辑:
目前,我加入和见面的代码如下所示:
public AntiChain join(AntiChain ac) {
AntiChain res = new AntiChain(this);
for(int i = ac.bitset.nextSetBit(0); i >= 0; i = ac.bitset.nextSetBit(i+1)) {
res.addAndMakeAntiChain(new BasicSet(i));
}
return res;
}
public AntiChain meet(AntiChain ac) {
AntiChain res = AntiChain.emptyAntiChain(this.getUniverse());
for(int i = bitset.nextSetBit(0); i >= 0; i = bitset.nextSetBit(i+1))
for(int j = ac.bitset.nextSetBit(0); j >= 0; j = ac.bitset.nextSetBit(j+1))
res.addAndMakeAntiChain(new BasicSet(j).intersection(new BasicSet(i)));
return res;
}
private void addAndMakeAntiChain(BasicSet x) {
for(int k = bitset.nextSetBit(0); k >= 0; k = bitset.nextSetBit(k+1)) {
BasicSet a = new BasicSet(k); //new BasicSet(7) = {1,2,3}
if(a.hasAsSubset(x)) return;
if(x.hasAsSubset(a)) bitset.set(k, false);
}
bitset.set(x.toIntRepresentation()); //{1,2,3}.toLong() = 7
}
最佳答案
这听起来是错误的:{{1, 64}}
呢? IIUYC索引是2 ** 63 +1,对于BitSet
来说太大了。如果您要对此进行优化表示,请考虑一些原始的长集合(trove4j,colt,hppc等)。
最有效的方法肯定是避免转换。可以对BitSet
进行迭代(双向),因此您可以直接进行字典比较。
BigInteger result = BigInteger.ZERO;
for(int i = theAntiChain.nextSetBit(0); i >= 0; i = theAntiChain.nextSetBit(i+1))
result = result.setBit(i);
return result;
这效率极低,您可以改为创建一个
byte[]
,填充它,然后使用new BigInteger(int signum, byte[] magnitude)
。关于java - 通过有效的加入和见面操作来代表反链,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28743659/