4

分布のエントロピーを確立する関数に取り組んでいます。それに精通している場合は、コピュラを使用します。どの次元が「気になる」かに基づいて、配列内の値を合計する必要があります。

例:次の例を考えてみましょう...

次元0(全体)
_ _ _ _ _ _ _ _ _ _ _ _ _
| _ 0 _ | _ 0 _ | _ 0 _ | _ 2 _ | 次元1
| _ 1 _ | _ 0 _ | _ 2 _ | _ 0 _ | (下)
| _ 0 _ | _ 3 _ | _ 0 _ | _ 6 _ |
| _ 0 _ | _ 0 _ | _ 0 _ | _ 0 _ |

私は次元0のみを「気にし」、残りは「気にしない」(薄暗い1)。
この配列を上記の仕様と合計すると、
次元1の「スタック」を単一の4x1配列に「折りたたむ」:

_ _ _ _ _ _ _ _ _ _ _ _ _
| _ 1 _ | _ 3 _ | _ 2 _ | _ 8 _ |

次に、これを合計するか、任意の操作を実行できます。

'n'次元の配列を使用してこれを行う必要があります。これは、実行可能に20になる可能性があります。また、特定の次元を考慮し、残りを折りたたむことで、これを実行できる必要があります。20次元を視覚化できないため、これで特に苦労しています:p。誰かがc/c ++コードを折りたたみ/合計するように設定するのを手伝ってくれるなら、私は非常に感謝しています。

アップデート:

家に着いたばかり。ここにあなたの質問に答えるためのいくつかの情報があります:

  1. 編集をロールバックして申し訳ありませんが、ロールバックをクリックすると変更が表示され、ウィキペディアのように混乱した内容を確認できると期待していました。私が知ったように、これはそうではありませんでした。
  2. @jeff-何が意味をなさないのですか?私はこの素晴らしいサービスを(私が思うに)正当な理由で使用しています。高校生なので趣味はもっと上手になりたいです。私の投稿の多くは、遺伝的アルゴリズムの実装に関するものです(この投稿、sparsearray、配列のランク付け、ポインター操作)。
  3. 従来の(密な)配列を使用すると、宇宙の分子の数を超える可能性があるため、スパース配列表現を使用しています。今のところ、スパース表現に進む前に標準配列で動作するように取り組んでいるので、スパース配列自体の実装はそれほど重要ではありません。以前の質問を見たことがない人のために、スパース配列ポイントを含む構造としてバイナリ検索ツリーを使用し、必要に応じてツリーをトラバースする「ドライバー」関数を使用して、関数が実行するように設計されているものを返します。これは柔軟性があるので、配列にアクセスするためのさまざまな方法に対応できます。
  4. 構造はハイパーキューブであり、ディメンションの数は実行時に指定され、各ディメンションの長さも指定されます(ハイパーキューブであるため、これらはすべて同じです)。

あなたの入力をみんなに感謝します。

4

10 に答える 10

2

@ジェフ

実はこれは面白い質問だと思います。それがどれほど役立つかはわかりませんが、それは有効な質問です。

@Ed

この質問についてもう少し情報を提供できますか?配列の次元は動的であるとおっしゃいましたが、要素の数も動的ですか?

編集:とにかく質問に答えようとします。私はあなたに私の頭のてっぺんからコードを与えることはできません(このPCにコンパイラがなければそれを正しくするのに時間がかかります)が、私はあなたを正しい方向に向けることができます...

例として、インデックス0〜3の8つのディメンション(0〜7)を使用してみましょう。気にするのは1、2、6だけです。これは、2つのアレイがあることを意味します。まず、array_care[4][4][4]1、2、および6のarray_care[4][4][4]場合。は最終結果を保持します。

次に、非常に具体的な方法で反復します。解析する配列があり、input[4][4][4][4][4][4][4][4]次元1、2、および6に関心があります。

いくつかの一時インデックスを定義する必要があります。

int dim[8] = {0,0,0,0,0,0,0,0};

また、インデックスを増やす順序を保存する必要があります。

int increase_index_order[8] = {7,5,4,3,0,6,2,1};
int i = 0;

この順序は、要求したことを実行するために重要です。

終了フラグを定義します。

bool terminate=false;

これで、ループを作成できます。

while (terminate)
{
array_care[dim[1]][dim[2]][dim[6]] += input[dim[0]][dim[1]][dim[2]][dim[3]][dim[4]][dim[5]][dim[6]][dim[7]];

while ((dim[increase_index_order[i]] = 3) && (i < 8))
{
dim[increase_index_order[i]]=0;
i++;
}

if (i < 8) {
dim[increase_index_order[i]]++; i=0;
} else {
terminate=true;
}
}

これは8次元で機能し、約3次元で機能するはずです。動的にするのにもう少し時間がかかり、時間がありません。お役に立てれば。申し訳ありませんが、コードのマークアップについてはまだ学習していません。:(

于 2008-08-22T19:32:36.043 に答える
2

これには応用があるかもしれません。2D コンウェイのライフ ゲーム (2D 平面を定義し、「生きている」を 1、「死んでいる」を 0) を実装し、反復ごとにゲームの履歴を保存したとします (3D キューブを定義します)。過去に生きていたバクテリアの数を知りたい場合は、上記のアルゴリズムを使用します。Game of Life グリッドの 3D (および 4D、5D など) バージョンに同じアルゴリズムを使用できます。

これは再帰に関する質問だと思います。私はまだ C プログラマーではありませんが、C でそれが可能であることは知っています。Python では、


def iter_arr(array):
  sum = 0
  for i in array:
    if type(i) == type(list()):
      sum = sum + iter_arr(i)
    else:
      sum = sum + i
  return sum 
  1. 配列内の各要素を反復処理する
  2. 要素が別の配列の場合、関数を再度呼び出します
  3. 要素が配列でない場合は、合計に追加します
  4. 合計を返します

次に、これを「気遣う」次元の各要素に適用します。

ただし、ダックタイピングにより、これはPythonの方が簡単です...

于 2008-08-24T12:27:40.617 に答える
2

この種のことは、STL コンテナーまたはBoost.MultiArrayを使用すると、はるかに簡単になります。ただし、配列を使用する必要がある場合:

#include <iostream>
#include <boost/foreach.hpp>
#include <vector>

int sum(int x) {
    return x;
}

template <class T, unsigned N>
int sum(const T (&x)[N]) {
    int r = 0;
    for(int i = 0; i < N; ++i) {
        r += sum(x[i]);
    }
    return r;
}

template <class T, unsigned N>
std::vector<int> reduce(const T (&x)[N]) {
    std::vector<int> result;
    for(int i = 0; i < N; ++i) {
        result.push_back(sum(x[i]));
    }
    return result;
}

int main() {
    int x[][2][2] = {
        { { 1, 2 }, { 3, 4 } },
        { { 5, 6 }, { 7, 8 } }
    };

    BOOST_FOREACH(int v, reduce(x)) {
        std::cout<<v<<"\n";
    }
}
于 2008-08-22T20:46:19.110 に答える
0

これをc/c ++で実行しているので、配列の配列の配列があります... 20次元を視覚化する必要はありません。これは、2次元の場合、データがメモリに配置される方法ではないためです。次元:

[1] --> [1,2,3,4,5,6,...]
[2] --> [1,2,3,4,5,6,...]
[3] --> [1,2,3,4,5,6,...]
[4] --> [1,2,3,4,5,6,...]
[5] --> [1,2,3,4,5,6,...]
 .           .
 .           .
 .           .

では、最初の内容を合計して繰り返し処理できないのはなぜですか?サイズを見つけようとしているなら、それsizeof(array)/sizeof(int)は危険なアプローチです。このデータを処理できるようにするための次元を知っている必要があり、メモリを設定して、合計する再帰の深さを知っている必要があります。これがあなたがすべきだと思われることのいくつかの擬似コードです、

sum( n_matrix, depth )
  running_total = 0
  if depth = 0 then
    foreach element in the array
      running_total += elm
  else 
     foreach element in the array
       running_total += sum( elm , depth-1 )
  return running_total
于 2008-08-22T19:29:03.460 に答える
0
x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

(申し訳ありませんが、抵抗できませんでした。)

于 2008-08-22T19:46:57.863 に答える
0

実際には、列を折りたたむことで、すでにそれらを合計しているので、例では寸法はまったく重要ではありません。私は何かを逃しましたか、それともあなたはしましたか?

于 2008-08-22T18:58:07.967 に答える
0

ここで行うのに最適なことは、次の2つのうちの1つまたは両方であると思います。

  1. デザインを再考し、複雑すぎる場合は、それほど複雑でない方法を見つけます。
  2. 視覚化するのはやめましょう。:P合計する必要のある問題のディメンションを保存してから、一度に1つずつ実行します。基本コードを入手したら、アルゴリズムの効率を改善することを検討してください。
于 2008-08-22T19:04:34.940 に答える
0

私の理解が正しければ、各「ビン」で定義された断面のすべての値を 1 次元に沿って合計する必要があります。宛先の 1D 配列を作成し、配列内の各要素をループして、目的の次元のインデックスを使用して値を宛先に追加することをお勧めします。

任意の数の次元を使用している場合は、要素をアドレス指定する方法が必要です (これをどのように実装しているか興味があります)。これの実装は、宛先インデックスの設定方法に影響します。しかし、明らかな方法は、反復ループでチェックされる if ステートメントを使用することです。

于 2008-08-22T20:16:57.683 に答える
0

私は違うことを懇願します、常に別の方法があります..

そして、本当にリファクタリングできない場合は、問題をより小さな部分に分割する必要があります..私が言ったように、合計する必要がある次元を確立し、それらを一度に1つずつヒットします..

また、編集を変更するのをやめてください。彼らはあなたのスペルミスを修正し、あなたを助けようとしています ;)

于 2008-08-22T19:13:10.347 に答える
0

次元がいくつあるかわからないと言うとき、データ構造をどのように正確に定義していますか?

ある時点で、誰かがこの配列を作成する必要があり、そのためには配列の次元を知る必要があります。作成者にこのデータを配列とともに渡すように強制できます。

問題がそのようなデータ構造を定義することでない限り...

于 2008-08-22T19:13:50.860 に答える