简体   繁体   English

2 Java Power Power 77的力量

[英]2 power of 77 java Powerset

I have 77 elements n1,n2,n3... etc I need to calculate superset. 我有77个元素n1,n2,n3 ...等等,我需要计算超集。 I used the binary mask algorithme but the number is to big to fit in int. 我使用了二进制掩码算法,但数量很大以适合int。 Here is the code: 这是代码:

private static Vector powerset(String[] set) {

       //create the empty power set
       Vector power = new Vector();

       //get the number of elements in the set
       int elements = set.length;

       //the number of members of a power set is 2^n
       int powerElements = (int) Math.pow(2,elements);

       //run a binary counter for the number of power elements
       for (int i = 0; i < powerElements; i++) {

           //convert the binary number to a string containing n digits
           String binary = intToBinary(i, elements);

           //create a new set
           Vector innerSet = new Vector();

           //convert each digit in the current binary number to the corresponding element
            //in the given set
           for (int j = 0; j < binary.length(); j++) {
               if (binary.charAt(j) == '1')
                   innerSet.add(set[j]);
           }

           //add the new set to the power set
           power.add(innerSet); 
       }
       return power;
   }
   private static String intToBinary(int binary, int digits) {

       String temp = Integer.toBinaryString(binary);
       int foundDigits = temp.length();
       String returner = temp;
       for (int i = foundDigits; i < digits; i++) {
           returner = "0" + returner;
       }

       return returner;
   } 

I tried to remove the int by using long or double, but nothing worked. 我试图通过使用long或double来删除int,但没有任何效果。

You need a data structure storing binary digits that is 77 digits long. 您需要一个存储77位长的二进制数字的数据结构。 You could use an array of 77 ints and manually increment the array as one big binary number where each element of the array is one bit in your number. 您可以使用77个整数的数组,并手动将其递增为一个大的二进制数字,其中数组的每个元素在数字中都为一位。 I wrote the Increment method below. 我在下面编写了Increment方法。

int[] num = new int[77];
for (int i = 0; i < 77; i++) num[i]= 0;
//create a new set
for (int i = 0; i < powerElements; i++) {
    Vector innerSet = new Vector();

    for (int j = 0; j < 77; j++) {
        if (num[i] == 1)
            innerSet.add(set[j]); 
    }
    Increment(num);
}

// Increment an array of ints as if it is a binary number. The LSB is the 77th element in the array, index 76.
public void Increment(int[] num) {
    int carry = 1;
    int i = 76;
    while (i > 0) {
        tmp = int[i] + carry;
        if (tmp == 0) break;
        if (tmp == 1) {int[i] = 1; break;}
        carry = 1;
        int[i] = 0;
        i--;
    }
    if (carry == 1) throw new Exception("Overflow");
}

As noted by commenters, you won't have room to store 2^77 sets. 正如评论者所指出的那样,您将没有空间存储2 ^ 77套。 And it will take virtually forever to count up to 2^77. 实际上,要计算2 ^ 77几乎是永远的。

From the comments it become clear this is to find the maximum clique , so I will now focus on that instead of on the literal question. 从评论中可以很明显地看出这是找到最大的集团 ,所以我现在将重点放在这个问题上,而不是字面上的问题。

First some simple tricks. 首先是一些简单的技巧。 With backtracking, many branches of the search space can be pruned. 通过回溯,可以修剪搜索空间的许多分支。 The rough idea looks like 大概的想法是

findMaxClique(clique, banned, graph):
    if clique ∪ banned is everything:
        if isclique(clique) and size(clique) > size(bestFound):
            bestFound = clique
        return
    for each node n not in clique ∪ banned:
        try findMaxClique(clique + n, banned, graph)
        try findMaxClique(clique, banned + n, graph)

This is still the naive version, trying every possible subset. 这仍然是天真的版本,尝试所有可能的子集。 But there are some obvious improvements. 但是有一些明显的改进。 For example, there's no point in waiting to test whether the potential clique is actually a clique until the last moment, every subset of nodes that form a clique also form a clique. 例如,没有必要等到最后一刻才测试潜在的集团是否真正是集团,形成集团的节点的每个子集也都形成集团。 Adding a node to it that doesn't leave it a clique is pointless. 向其添加一个不会使其成组的节点毫无意义。 Call this #1. 称其为#1。 This prunes a lot . 这修剪了很多

Also, if the current clique plus the nodes that could possible be added to it is less than the best found clique, nothing better can be found in this branch of the search space. 同样,如果当前派系加上可能添加的节点少于找到的最好派系,则在搜索空间的此分支中找不到更好的派系。 There are several different levels of effort you can do here, the simplest is just counting all in the leftover set, but you could go for the biggest clique in that set or something. 您可以在此处进行几种不同级别的工作,最简单的方法就是将剩余的工作集中在所有工作中,但是您可以选择该工作组中最大的工作组。 Anyway I'll show the simple one, call it #2. 无论如何,我将展示一个简单的示例,将其称为#2。 Now we have something like: 现在我们有了类似的东西:

findMaxClique(clique, banned, graph):
    if clique ∪ banned is everything:
        if size(clique) > size(bestFound):
            bestFound = clique
        return
    for each node n not in clique ∪ banned:
        if isclique(clique + n):
            try findMaxClique(clique + n, banned, graph)
        notbanned = graph - (banned ∪ n)
        if size(notbanned) >= size(bestFound):
            try findMaxClique(clique, banned + n, graph)

An other option to estimate the size of clique you could build is to use linear programming. 估计您可以建立的集团规模的另一种选择是使用线性规划。

For example, this is an ILP model for max clique: 例如,这是最大集团的ILP模型:

maximize sum x[i]
s.t.
for each i,j that are not adjacent, x[i]+x[j] ≤ 1
x[i] in { 0, 1 }

The linear relaxation (ie dropping the last constraint) of that is easy to compute, and you can lazily add the constraints if you want. 线性松弛(即删除最后一个约束)易于计算,并且您可以根据需要延迟添加约束。 Obviously there are constraints coming from the clique / banned sets, forcing certain x's to be 1 or 0 respectively. 显然, clique / banned集有一些约束,迫使某些x分别为1或0。 If the objective value of the linear relaxation is not better than your biggest found clique, then you can prune the current branch. 如果线性松弛的目标值不比您发现的最大集团好,那么可以修剪当前分支。

There are an other fun property of that model. 该模型还有另一个有趣的特性。 If the resulting x has all entries from {0, 0.5, 1}, then you can immediately decide to pick all nodes for which x[i] = 1 to be in your clique, so you can skip a lot of branching in that case. 如果所得的x具有{0,0.5,1}中的所有条目,那么您可以立即决定选择x [i] = 1的所有节点纳入您的派系,因此在这种情况下,您可以跳过很多分支。 This is probably uncommon high in the search tree, but you can add some Gomory cuts to encourage integrality. 这在搜索树中可能并不常见,但是您可以添加一些Gomory削减以鼓励完整性。 Your favourite LP solver may have them built in. 您最喜欢的LP解算器可能内置了它们。

There are more clever tricks here, check the literature. 这里还有更多技巧,请查阅文献。

A completely different way to attack the problem is with SAT, which does not optimize at all, but you can try every size of clique and for every size use SAT to ask whether there is a clique of that size (and if it exists, what it looks like). 解决问题的一种完全不同的方法是使用SAT,它根本不会进行优化,但是您可以尝试各种规模的小集团,对于每种大小,请使用SAT询问是否存在该大小的小集团(如果存在,请问什么?看起来像)。 Actually it's easiest as a Pseudo boolean model: 实际上,作为伪布尔模型最简单:

for each i,j that are not adjacent: ¬i + ¬j ≥ 1
sum of everything = k

The usual adjacency constraint is trivial to state in pure SAT, the sum constraint is annoying, requiring an addition circuit. 通常的邻接约束对于纯SAT来说是微不足道的,总和约束很烦人,需要加法电路。 That's easy enough to generate, but hard to write out here, not only because it depends on k. 生成起来很容易,但是在这里很难写出来,不仅因为它取决于k。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM