2

正の数値のベクトルがあります。値の合計が1になるように正規化する必要があります(たとえば、確率)。これは単純で、重みとしてx_i / sum(x)を使用するだけです。ただし、ここに注意点があります。重量が最小カットオフを下回らないようにする必要があります。また、重量が最大カットオフを超えないようにする必要があります。さて、これは2つのことを意味します。1つは、解決策がない場合があることを意味します(たとえば、最大カットオフが0.2の場合、3つのオブジェクトを重みにすることはできません)。第二に、それは重みの「相対性理論」が壊れていることを意味します。つまり、標準の正規化(w_iはすべてのiのx_iに与えられる重み)では、すべてのi、jのw_i / w_j = x_i/x_jです。カットオフがあると、これはできません。more正式には、関数w = rwc(x、min、max)を見つけたいと思います。ここで、xはベクトルであり、次のプロパティを持つ同じ長さのベクトルを返します。

1)sum(w)= 1

2)すべてのiについて最小<=w_i<=最大

3)x_i <= x_jの場合、すべてのi、jに対してw_i <=w_j

4)w_iとw_jが両方ともカットオフ(最小と最大)と異なる場合、それらは相対性を維持します。つまり、最小<w_i<最大および最小<w_j<最大の場合、w_i / w_j = x_i / x_j

解決策がない場合は、NULLを返す必要があります。

だから私の質問は:

a)それを(Rまたは他の言語で)どのように提案しますか?

b)xが与えられた場合、複数の解が存在する可能性があります(つまり、それぞれが上記の正式な要件に準拠する、少なくとも2つの異なるベクトルwとv)

これは厳密にはRの問題ではありませんが、Rで行っているプロジェクト内で発生したので、Rとして投稿します。より適切な分類の提案を歓迎します。

アップデート

以下の説明に続いて、さらに検討した後、上記の4つに5番目の要件を追加する必要があるようです。5)1〜4を満たすすべての可能な重みの割り当てのうち、Wは極端な重みの数が最小(最小または最大)の要件です。 )。

これが(うまくいけば)それを行う私のrコードです:

#
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
4

3 に答える 3

1

a)

ブルートフォース反復アルゴリズムを提案します。

  1. させてx' = x
  2. 計算するsum(x')
  3. カットオフ限界を計算しmin_xmax_x
  4. から計算x'x、範囲外のすべての値を調整 [ min_x, max_x]
  5. x'安定するまで2~4を繰り返す
  6. 計算するw

ほとんどの場合、反復回数は少なくする必要があります。

b) 最小値または最大値 (両方ではない) がある場合、ソリューション ベクトルは一意です。

最小値と最大値の両方がある場合、わかりません。ユニークであるべきだと思いますが、簡単な証明が見つかりません。

于 2013-02-21T13:09:15.663 に答える
0

このようなことを意味しますか?例は Haskell で、"[ ]" は空のリストを意味します。

weights :: [Double] -> Double -> Double -> [Double]
weights my_vector min max = 
  let s = sum my_vector
      try = map (/s) my_vector
  in if all (>=min) try && all (<=max) try
        then try
        else []

出力:
*Main> weights [1,2,3,4] 0 2
[0.1,0.2,0.3,0.4]
*Main> weights [1,2,3,4] 1 2
[]

更新:これ
に基づいて、大まかな方向性 (Haskell 再び) を次に示します。

import Data.List
import Data.Ord

normalize :: Double -> Double -> Double -> Double -> Double
normalize targetMin targetMax rawMax val =
  let maxReduce = 1 - targetMax/rawMax
      factor = maxReduce * (abs val) / rawMax
  in max ((1 - factor) * val) targetMin

weights :: [Double] -> Double -> Double -> [Double]
weights myVector targetMin targetMax = 
  let try = map (/(sum myVector)) myVector
  in if all (>=targetMin) try && all (<=targetMax) try
        then try
        else weights normalized targetMin targetMax
    where normalized = 
            let targetMax' = (maximum myVector * targetMin / minimum myVector)
            in map (\x -> normalize targetMin targetMax' (maximum myVector) x) myVector

OUTPUT:
*Main> weights [4,4,4,1000] 0.1 0.7
[0.10782286784365082,0.10782286784365082,0.10782286784365082,0.6765313964690475]
*Main> weights [1,1,1000000] 0.05 0.8
[0.1204381​​8322274577,0.1204381​​8322274577,0.7591236335545084]

于 2013-02-21T13:12:44.570 に答える
0

これは私の 2 番目の回答であり、要件 4) にも対処できることを願っています。要件 4) が適用される場合、カットオフとして割り当てられていないすべての要素を次のように分割する必要があるように思えます。

    denominator = sum non_cutoff_elements / (1 - sum cutoff_elements)

「cutoff_elements」はカットオフ値として表されます。この再帰的なコードは、カットオフ代入の組み合わせを使い尽くそうとしています。このコードは、コメント内の amit と rici の両方の例を解決しているようです。Haskell 再び:

import Data.List
import Data.Ord

weights :: [Double] -> Double -> Double -> [[Double]]
weights myVector tMin tMax = 
  weights' 0
    where 
      weights' count
        | count == length myVector + 1 = []
        | otherwise =
            let new_list = take count myVector 
                           ++ replicate (length myVector - count) tMax
            in fromLeft new_list 0 ++ weights' (count+1)
                where 
                  fromLeft list' count' = 
                    let non_cutoffs = filter (\x -> x/=tMin && x/=tMax) list'
                        real_count = length list' - length non_cutoffs
                        cutoffs_l = filter (\x -> x==tMin) list'
                        cutoffs_r = filter (\x -> x==tMax) list'
                        denom = sum non_cutoffs / (1 - (sum $ cutoffs_l ++ cutoffs_r))
                        mapped = cutoffs_l ++ (map (/denom) non_cutoffs) ++ cutoffs_r
                        next_list = let left = tMin : cutoffs_l
                                        right = drop 1 cutoffs_r
                                    in left ++ non_cutoffs ++ right
                    in if count' == real_count
                          then []
                          else if sum cutoffs_r > 1 || sum cutoffs_l > 1 
                                  || sum cutoffs_r + sum cutoffs_l > 1
                                  then fromLeft next_list (count'+1)
                          else if sum mapped == 1 && all (>=tMin) mapped && all (<=tMax) mapped
                                  then mapped : fromLeft list' (count'+1)
                                  else fromLeft next_list (count'+1)

出力:
*Main> Weights [4,4,4,1000] 0.1 0.7
[[0.1,0.1,0.1,0.7]、[0.1,0.1,0.1000000000000000009,0.7]、[0.1,0.1000000000000000000003,0.10000000000000000000000000000002
[[0.1,0.1,0.1,0.7],[0.1,0.1,0.1,0.7],[0.1,0.1,0.1,0.7],[0.1,0.1 , 0.1,0.7]]

*Main> weights [1,1,1000000] 0.05 0.8
[[5.0e-2,0.1499999999999999,0.8],[9.999999999999998e-2,9.999999999999998e-2,0.8]]
小数点第 14 位に四捨五入: [[0.05,0.15,0.8],[0.1,0.1,0.8]]

于 2013-02-22T06:14:17.330 に答える