I have a vector of positive numerical values. I need to normalize it so that the sum of the values is 1 (e.g. a probability). This is simple just use x_i/sum(x) as weights. but here is the caveat: I need that no weight will be less than some minimum cutoff, and not weight is greater than some maximum cutoff. Now, this means two things: First, it means that there are cases with no solutions (e.g. 3 objects can't be weights if the maximum cutoff is 0.2). Second, it means that the "relativity" of weights is broken. That is, in standard normalizations (where w_i is the weight given to x_i for all i), w_i/w_j=x_i/x_j for all i,j. with cutoffs, this can't be done. more Formally I'd like to find a function w=rwc(x,min,max) where x is a vector, that returns a vector of the same length that has the following properties:
1) sum(w)=1
2) min <= w_i <= max for all i
3) if x_i <= x_j then w_i<=w_j for all i,j
4) if w_i and w_j are both different from the cutoffs (min and max) then they keep relativity: that is, if min < w_i < max and min < w_j < max then w_i/w_j=x_i/x_j
if there is no solution NULL should be returned.
so my question is:
a) how do you suggest doing that (in R or any other language)?
b) given x, can there be more than one solution (that is, at least two different vectors, w and v, each conforming to the formal requirements above)
This is not strictly an R problem but I encountered it within an project i'm doing in R, so I post it as R. any suggestion for better classification are welcomed.
update
Following the discussion below and after more thoughts it seems necessary to add a fifth requirement to the the 4 above: 5) of all the possible assignments of weights satisfying 1-4, W is the one with minimum number of extreme weights (min or max).
here is a my r code that (hopefully) does that:
#
mwc = function(x,mxw=1,mnw=0) {
cake = 1
agnts = 1:length(x)
result = numeric(length(x))
while(cake>0 & length(agnts)>0) {
tmp = cake*x[agnts]/sum(x[agnts])
low = which(tmp<mnw)
high = which(tmp>mxw)
if(length(low)+length(high)==0 ) {
result[agnts] = tmp[agnts]
break;
}
if (length(low)>0) {
result[agnts[low]] = mnw
}
if (length(high)>0) {
result[agnts[high]] = mxw
}
cake = 1-sum(result)
agnts=agnts[-c(low,high)]
}
if (cake<0) return(NULL) #no solution
if (abs(sum(result)-1)>1e-17) return(NULL)
return(result)
}
# the end