Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2^N Combinaisons with Integers (Kernel), how to generate them?

(Merry Christmas btw ^^)

Here is my problem (in JAVA) but it's definitely an algorithmic problem and I don't know how to solve it :/ So here it is, with an example (just for information, all my calculs are in Binary, so 1+1 = 0)

let's name variables:

  N : the number of elements in kernel.
  M : the length of an element in the kernel.

  int[][] Kernel: 

            ....
            i   : 0 1 1 1 0 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 0  (length = M)
            i+1 : 1 0 1 0 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 1 1 0 1 0 1  (length = M)
            ....
            N   : ....

My goal with theses things, is to generate all the possible combinaison (so 2^N elements) and I want to generate them. By generate I mean exactly this :

    Result[0]     = 0 0 0 0 0 0 0 0 0 0 0 0 0
    Result[1]     = Kernel[0]
    Result[2]     = Kernel[1]
    ....
    Result[i]     = Kernel[i-1]
    Result[N-1]   = Kernel[N-2]

    Result[N]     = Kernel[0] + Kernel[1]
    Result[N+1]   = Kernel[0] + Kernel[2]
    Result[N+i]   = Kernel[0] + Kernel[i]
    Result[2N-1]  = Kernel[0] + Kernel[N-1]
    ....
    Result[I]     = Kernel[0] + Kernel[1] + Kernel[2]
    Result[I+1]   = Kernel[0] + Kernel[1] + Kernel[i]
    Result[I+J]   = Kernel[0] + Kernel[1] + Kernel[N-1]
    ....
    Result[2^N+1] = Kernel[0] + Kernel[1] + ... + Kernel[i] + ... + Kernel[N-1]

Here is what I already success to do, but it's not complete and I don't know how to generalize the calcul in order to work with any N...

public static int[][] combinaisons(int[][] kernel) {

    /* if the kernel is empty, there is no possible combinaison */
    if(kernel.length == 0) return kernel;

    /* We allocate the good number of space... */
    int[][] result = new int[(int) (Math.pow(2, noyau.length)+1)][];

    /* Every element in result has the same length as in kernel's elements. */
    for(int i = 0; i < resultat.length; i++) {
        result[i] = new int[kernel[0].length];
    }

    /* The first element of result has to be only 0 0 0 0 0 0 0 */
    for(int j = 0; j < kernel[0].length; j++) {
        result[0][j] = 0;
    }

    /* We rewrite the element of kernel because they are a part of the solution... */
    for(int i = 0; i < kernel.length; i++) {
        for(int j = 0; j < kernel[i].length; j++) {
            result[i+1][j] = kernel[i][j];
        }
    }


    /* 
       I managed to do it when it's the sum of only 2 elements, 
       but it has to be with 3, 4 ... N-1 :/ 
    */
    for(int i = 0; i < kernel.length; i++) {
        for(int j = 0; j < kernel[i].length; j++) {
            for(int k = i+1; k < kernel.length; k++) {

                result[k*kernel.length+i][j] = (kernel[i][j]+kernel[k][j])%2;

            }
        }
    }

    return result;
}

Edit:

About an example, let's give this:

 N = 2 
 M = 4 
 Kernel: 
      0 1 1 0
      1 0 0 1 

In result I want: 
      0 0 0 0 
      0 1 1 0 
      1 0 0 1 
      1 1 1 1 (the sum of the 2 elements in Kernel) 

So this is a simple example (quite particularly values, if you want bigger, just ask :) )

Even if the array at the end seems to be VERY HUGE :) that's exactly what I want to generate (don't care about memory, it will for sure be okay)

like image 665
Valentin Montmirail Avatar asked Oct 20 '22 20:10

Valentin Montmirail


1 Answers

I am going to use boolean[][] instead of int[][]. 0 means false, 1 means true.

public static boolean[][] combinations(boolean kernel[][]) {
    int n = kernel.length;
    int m = kernel[0].length;
    int p = 1 << n;
    boolean[][] temp = new boolean[p][m];
    for (int i = 0; i < p; i++)
        for (int j = 0; j < n; j++)
            if (((1 << j) & i) != 0)
                for (int k = 0; k < m; k++)
                    temp[i][k] ^= kernel[j][k];
    return temp;
}
like image 198
Paul Boddington Avatar answered Oct 28 '22 23:10

Paul Boddington