algorithm: weighted sums under rotation

Viewed 208

Sorry, I hope this is not too far off topic for stackoverflow. I have an algorithm that I'd like to prove is correct, or find a counter example if it's not.

Here is the problem. I have a set of strictly positive weights: w1, w2, w3, ... wn.

I have a vector of booleans of length m, where m>n. The vector must have exactly n true values and m-n false values.

For example, if m=5 and n=3, then v could be (1, 1, 0, 1, 0)

Next, we have function which maps v vectors to natural numbers:

int f(vector v) {
  sum=0, wIndex=1, pow=1;

  // v must have exactly n ones
  for(int index=0;index<m;index++) {
    if(v[index]==1)
      sum=sum + w[wIndex++]*pow;
    pow=pow*2;
  }
  return sum;
}

where w[wIndex] is gives the weights, w1, w2, w3 ... wn.

EXAMPLE: 
   suppose v=(0, 1, 1, 0, 1) and w1=3, w2=4, w3=6
   f(v) would be 3*2 + 4*4 + 6*16 = 118.

Next Consider circular rotations of v, for example, if v=(0, 1, 1, 0, 1) then rotate(v, 3) is v rotated 3 positions to the left, or (0, 1, 0, 1, 1). Circular rotations preserve m (length) and n (number of ones).

We define the minF(v) to be the minimum f value over all possible circular rotations of v. It could be implemented as follows:

int minF(vector v) {
  int min=f(v);

  for(int amount=1; amount<m; amount++) {
    if(f(rotate(v, amount))<min)
      min=f(rotate(v, amount));
  }
  return min;
}

where rotate(v, k) rotates v by circularly by k places

EXAMPLE:
  suppose v=(0, 1, 1, 0, 1) and all weights are 3
  The rotation that has the minimum f is v=(1, 1, 0, 1, 0),
  Thus minF(v)=3 + 6 + 24 = 33

And now finally we get to the question:

Prove or disprove optimum(m, n) produces the vector such that minF(optimum(m, n)) >= minF(w) for all possible vectors w, of length m with n ones, where optimum is defined as follows:

vector optimum(int m, int n) {
  vector opt=new vector[m];
  int    ones=n, zeros=m-n, balance=0;

  for(int index=0; index<m; index++)
    if(balance<ones) {
      opt[index]=1;
      balance=balance + zeros;
    }
    else {
      opt[index]=0;
      balance=balance - ones;
    }
  }
  return opt;
}

Finally, here are some examples of runs of optimum:

optimum(10, 1) -->  1000000000
optimum(10, 2) -->  1000010000
optimum(10, 3) -->  1001001000
optimum(10, 4) -->  1010010100
optimum(10, 5) -->  1010101010
optimum(10, 6) -->  1101011010
optimum(10, 7) -->  1110110110
optimum(10, 8) -->  1111011110
optimum(10, 9) -->  1111111110

Optimum essentially spreads the ones as far apart as possible.

I've done many empirical tests and this algorithm always seems to work, but I really need a proof that it's correct.

PS If you solve this, I'll buy you a pizza.

1 Answers
Related