Introducing antichains with effective compounds and encounters

Some information

I am working on a program that works with basic sets and antichains.

Antichains are subsets of the strength set of a set, so no two elements (sets) in this subset are subsets of another element (set) in this subset. For example, {{1}, {1,2}} is not antichain because {1} βŠ† {1,2}.

Some of the most important operations on antichains A and B can be defined as

  • a.join (b) = sup (a βˆͺ b)
  • a.meet (b) = sup ({X ∩ Y | X ∈ a and Y ∈ b})

Where sup is supremum of anticein, which means the smallest antichin is greater than a given set.

Presentation bye

The basic set is represented by long , bitarray-alike. This means that each element of the set is represented by the symbol 1 in bittra. For example, the set {1,2,3} is represented by 7 (bitrari 111), and the set {1,2,4} is represented by 11 (bitrari 1011), etc.

Now I wanted to raise this view in order to similarly present the anti-shops. This means that I could represent antichain {{1}, {2,3}} as 1000010 in bitarray, because long-term preservation of the set {1} is 1, and for {2,3} it is 6 (indices 1 in bitarray )
If I don’t find some better alternatives, I will use the BitSet class to work with this bitarray, hoping to save some time on working with any Collection<T> .

I have already managed to define and optimize most of the elementary operations indicated earlier, but they were optimized in the old version, just using TreeSet , therefore not optimized for working with bitarray.

My questions

  • My question now is whether BitSet is the optimal representation, knowing that these bitarray representations double in size each time an element is added to the original set. I also thought of BigInteger , for example, having the advantage of being comparable (which I also need).
  • I would also like to know if someone has already done something, and knows how to implement a connection and communicate effectively using the bitarray properties.

Thanks in advance.


Edit:

The code for my connection and meeting looks like this: at the moment:

 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 } 
+6
source share
2 answers

Now I wanted to raise this view in order to similarly present the anti-shops. This means that I could represent antichain {{1}, {2,3}} as 1000010 in bitarray, because long-term preservation of the set {1} is 1, and for {2,3} it is 6 (indices 1 in bitarray )

That doesn't sound right: how about {{1, 64}} . IIUYC index 2 ** 63 + 1, too large for BitSet . If you want an optimized presentation for this, consider some primitive long collections (trove4j, colt, hppc, ...).

  1. To be able to compare my bit rates, are there more efficient ways to convert BitSet to BigInteger?

The most effective way, of course, is to avoid conversion. A BitSet can be repeated (in both directions), so you can directly compare lexicography.

 BigInteger result = BigInteger.ZERO; for(int i = theAntiChain.nextSetBit(0); i >= 0; i = theAntiChain.nextSetBit(i+1)) result = result.setBit(i); return result; 

This is extremely inefficient, you can create byte[] instead, populate it and use new BigInteger(int signum, byte[] magnitude) .

+1
source

Well, I can think of a better way to store your antichains (still in BitSets). Currently, your sets will be quite rare - a high ratio of 0: 1.

I just concatenate them. Each guarantee will be less than 64 bits, since you represent them using long values, so I would do something like this

 public static void put(BitSet antiChain, long value) { int len = antiChain.length(); antiChain.clear(antiChain.size() - 1); len -= len % 64; for (int i = 0; i < 64; i++) if ((value & (1 << i)) != 0) antiChain.set(len + i); antiChain.set(antiChain.size()); } public static long get(BitSet antiChain, int index) { long value = 0; for (int i = 0; i < 64; i++) if (antiChain.get(index * 6 + i)) value |= (1 << i); return value; } public static boolean contains(BitSet antiChain, long value) { for (int i = 0; i < antiChain.size() / 64; i++) { if (get(antiChain, i) == value) return true; } return false; } 

which includes one set bit at the end, regardless of what is needed for the number of contained sets to be explicit; those. so that {} != {{}}

For a specific example, here's what happens with {{1},{2,3}} . (Note that s(n) refers to the set to which n belongs.

  • {{1},{2,3},{4,5}} = {s(0b10), s(0b110), s(0b110000)} = {s(2), s(6), s(48)}
  • The put function will encode this as 2*2^(64*0) + 6 * 2^(64*1) + 48*2^(64*2) (where ^ represents the exponent, not XOR).
  • BitSet representing this {1, 33, 64, 65, 66, 97, 98, 128, 132, 133, 164, 165, 256}

In addition, no matter how efficiently you convert BitSet to BigInteger , compare will still occur in O(L) time, where L is the length of your anticein in the sets. You are probably better

  • If there are several comparisons on antihein: just call toLongArray() and compare long values ​​manually
  • If one comparison is on antihein: manual switching from high bit to low bit and check.
+1
source

Source: https://habr.com/ru/post/983042/


All Articles