2017-01-20 4 views
1

私はn次元配列Tを持っています。各次元の長さは同じです。Lです。この配列は1DベクトルvTの「再構成」バージョンと見なすことができるので、vの長さはL^nです)によって表されます。ネストされたループ:ベクトルで表されるn次元配列を置換する

次の例では、vT(どこn = 3L = 4)の指標に応じてインデックスされる方法を示しています。

enter image description here

(例えばT(0,3,2) = v[14]

私がやりたいどのようなことでありn次元配列Sを表すベクトルuを作成します。ここで、Sは、/ rotati nはTで1、すなわち

T(i1,i2,...,in) = S(i2,i3,...,in,i1)のいずれかの場合は(i1,i2,...,in)です。

Tがマトリックスである場合、Sは、Tの転置に対応する)。

更新:

次のコードは、より良い私の質問を説明することがあります。

void permute(vector<double> &output, const vector<double> &v, int L) 
{ 
    int n = log(v.size())/log(L); 

    // Suppose that we have a function doing this 
    narray T = get_narray_from_vector(v, L); 

    // Get the permutation of T 
    narray S(T.size()); 
    for(int i1 = 0; i1 < L; i1++){ 
     for(int i2 = 0; i2 < L; i2++){ 
      ... 
      for(int in = 0; in < L; in++){ 
       S(i2,i3,...,in,i1) = T(i1,i2,...,in); 
      } 
     } 
    } 

    // get vector from narray 
    output.resize(v.size()); 
    int idx = 0; 
    for(int i1 = 0; i1 < L; i1++){ 
     for(int i2 = 0; i2 < L; i2++){ 
      ... 
      for(int in = 0; in < L; in++){ 
       output[idx] = S(i1,i2,...,in); 
       idx++; 
      } 
     } 
    } 
} 

は、実際には、しかし、私はそれがはるかに優れたベクターで直接作業していると思います。したがって、私はこのようなものだろう:

void permute(vector<double> &output, const vector<double> &v, int L) 
{ 
    int n = log(v.size())/log(L); 
    output.resize(v.size()); 

    // Get the permutation 
    for(int i1 = 0; i1 < L; i1++){ 
     for(int i2 = 0; i2 < L; i2++){ 
      ... 
      for(int in = 0; in < L; in++){ 
       output[i2*pow(L, n-1) + i3*pow(L, n-2) + ... + in*L + i1] = v[i1*pow(L, n-1) + i2*pow(L, n-2) + ... + i_{n-1}*L + in]; 
      } 
     } 
    } 
} 

ここに難しさをnがパラメータであるため、ネストされたループです。

どうすればいいですか? ご協力いただきありがとうございます!

+1

あなたの質問は本当に明確ではありません。あなたは何を試みましたか? 'i1'、' i2'などが "列"を表していると仮定した場合、最初の列を削除し、他の列をすべてシャッフルしてから、最初の列を最後に追加しますか? (注:多次元配列の文脈では、 "転置"という言葉は、あなたがその言葉を使用しているものとは異なるような特別な意味を持っています)。 – Peter

+0

Tをこのようにベクトルに格納する必要はありますか?私の最初の傾向は、 "配列の配列"をn次元に拡張して格納することです。次に、トップレベルの配列を1つのインデックスだけシフトする必要があると思うものは何でしょうか? – Nic

+0

また、たとえば、L = 3であると言うと、各次元の長さは4(0,1,2,3)です。 – Nic

答えて

1

ここでは、ループ用にネストされたnを必要としないソリューションがあります。

まず、数字をLベースの番号体系に分解する古いコードがあります。言い換えれば

std::vector<int> 
num2base(const int value, 
     const unsigned int base){ 

    // Represents an input int VALUE in a new BASE-based number system                          
    // n = a0*b^0 + a1*b^1 + ...                                   

    std::vector<int> base_representation; 
    unsigned int num_digs = (unsigned int) (floor(log(value)/log(base))+1); 
    base_representation.resize(num_digs); 

    for (unsigned int i_dig = 0; i_dig < num_digs; i_dig++){ 
    base_representation[i_dig] = 
     ((value % (int) pow(base,i_dig+1)) - (value % (int) pow(base, i_dig)))/
     (int) pow(base, i_dig); 
    } 

    return base_representation; 
} 

は、それはあなたのi1からinnタプルインデックスにあなたの単一の値のインデックスidxを変換する方法です。あなたはnタプルのインデックスを表すstd::vector<int>を持っていたら

idx = i1*L^0 + i2*L^1 + ... in*L^(n-1) 

はここで他の方法

int 
base2num(const std::vector<int> base_representation, 
     const unsigned int base){ 

    unsigned int digit_val = 1; 

    int value = 0; 

    for (unsigned int digit = 0; digit < base_representation.size(); digit++){ 
    value += base_representation[digit]*digit_val; 
    digit_val *= base; 
    } 

    return value; 
} 

を行くためのコードは、それを置換するために簡単ですです。

ので
void 
permute_once(std::vector<int> &base_representation){ 

    std::vector<int>::iterator pbr = base_representation.begin(); 
    int tmp = *pbr; 
    base_representation.erase(pbr); 
    base_representation.push_back(tmp); 

    return; 
} 

、新しいn次元配列を生成するためにS

  1. SのすべてのインデックスidxSを通過します。

  2. nタプルにidxSに変換(iS1iS2、...、iSn

  3. 関連するT内のエントリとそのnタプル(iT1iT2、...、iTn)を検索

  4. 単一のインデックスidxTに変換します。

  5. u[idxS] = v[idxT];

+1

ありがとうございます。これもやり方です。 – Khue