# 多次元配列の和について :::{container} prog-cpp ## 多次元配列の合計関数 QUBO++ は、変数や式の多次元配列に対して 2 種類の合計関数を提供しています: - `qbpp::sum()`: 配列内のすべての要素の合計を計算します。 - `qbpp::vector_sum()`: 最も内側の次元に沿った合計を計算します。結果の配列は入力配列よりも 1 次元少なくなります。入力配列は 2 次元以上である必要があります。 次のプログラムは、`qbpp::sum()` と `qbpp::vector_sum()` の違いを示しています: ```{literalinclude} ../../programFiles/cppPrograms/advanced/sum-functions-for-arrays-program1.cpp :language: cpp :caption: sum-functions-for-arrays-program1.cpp ``` まず、サイズ $2 \times 3 \times 3$ の変数配列 `x` が定義されます。次に、`x` の各要素に 1 を加えて配列 `y` を作成し、`y` のすべての要素を出力します。その後、`qbpp::sum(y)` を計算して出力します。次に、`qbpp::vector_sum()` 関数を `y` に適用し、その結果を `vector_sum` に格納します。`vector_sum` はサイズ $2 \times 3$ の 2 次元式配列です。最後に、`vector_sum` のすべての要素が出力されます。 このプログラムは次の出力を生成します: ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` 同じ結果は、明示的な for ループを使用しても得られます。しかし、大きな配列に対しては、`qbpp::sum()` および `qbpp::vector_sum()` の使用が推奨されます。これらの関数は内部でマルチスレッドを活用して計算を高速化するためです。 ## `vector_sum()` の軸指定 デフォルトでは、`qbpp::vector_sum()` は最も内側(最後)の軸に沿って合計を計算します。 `qbpp::vector_sum(array, axis)` で異なる軸を指定できます。 負のインデックスもサポートされています: 軸 `-1` は最後の軸、`-2` は最後から2番目の軸を指します。 上記と同じ $2 \times 3 \times 3$ の配列 `x` を使って、3つの軸それぞれに沿った合計を示します: ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` - `qbpp::vector_sum(x, 2)` は軸 `2`(最も内側の軸)に沿って合計し、$2 \times 3$ の配列を生成します。これは `qbpp::vector_sum(x)` と同等です。 `qbpp::vector_sum(x, 1)` は軸 `1`(中間の軸)に沿って合計し、$2 \times 3$ の配列を生成します。 ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` `qbpp::vector_sum(x, 0)` は軸 `0`(最も外側の軸)に沿って合計し、$3 \times 3$ の配列を生成します。 ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` ::: :::{container} prog-python ## 多次元配列の合計関数 pyQBPP は、変数や式の多次元配列に対して 2 種類の合計関数を提供しています: - `sum()`: 配列内のすべての要素の合計を計算します。 - `vector_sum()`: 最も内側の次元に沿った合計を計算します。結果の配列は入力配列よりも 1 次元少なくなります。入力配列は 2 次元以上である必要があります。 次のプログラムは、`sum()` と `vector_sum()` の違いを示しています: ```{literalinclude} ../../programFiles/pythonPrograms/advanced/sum-functions-for-arrays-program1.py :language: python :caption: sum-functions-for-arrays-program1.py ``` まず、サイズ $2 \times 3 \times 3$ の変数配列 `x` が定義されます。次に、`x` の各要素に 1 を加えて配列 `y` を作成し、`y` のすべての要素を出力します。その後、`sum(y)` を計算して出力します。次に、`vector_sum()` 関数を `y` に適用し、その結果を `vector_sum` に格納します。`vector_sum` はサイズ $2 \times 3$ の 2 次元式配列です。最後に、`vector_sum` のすべての要素が出力されます。 このプログラムは次の出力を生成します: ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` 同じ結果は、明示的な for ループを使用しても得られます。しかし、大きな配列に対しては、`sum()` および `vector_sum()` の使用が推奨されます。これらの関数は内部でマルチスレッドを活用して計算を高速化するためです。 ## 受け付ける入力 `qbpp.sum()` は qbpp 配列だけでなく、list, tuple, ジェネレータ式, range など任意の Python iterable を受け付けます。 配列以外の入力は内部で `qbpp.array(...)` に暗黙変換されてから同じ高速パスで合計されるため、戻り値は常にスカラーの `Expr` です。 ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` この機能は、配列演算では表現しにくい**疎で不規則な総和**(グラフのエッジ集合、集合への所属など)を書くときに特に便利です。 > **注意**: Python 標準の `sum()` も qbpp 配列に対して動作しますが、多次元では挙動が異なります。2次元配列 `y` に対して `sum(y)` は軸0で縮約して1次元配列を返しますが、`qbpp.sum(y)` は全要素の総和(スカラ)を返します(`numpy.sum` と同じ規約)。QUBO の定式化では常に `qbpp.sum()` を使ってください。 ## `vector_sum()` の軸指定 デフォルトでは、`vector_sum()` は最も内側(最後)の軸に沿って合計を計算します。 `vector_sum(array, axis)` で異なる軸を指定できます。 負のインデックスもサポートされています: 軸 `-1` は最後の軸、`-2` は最後から2番目の軸を指します。 上記と同じ $2 \times 3 \times 3$ の配列 `x` を使って、3つの軸それぞれに沿った合計を示します: ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` - `vector_sum(x, 2)` は軸 `2`(最も内側の軸)に沿って合計し、$2 \times 3$ の配列を生成します。これは `vector_sum(x)` と同等です。 `vector_sum(x, 1)` は軸 `1`(中間の軸)に沿って合計し、$2 \times 3$ の配列を生成します。 ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` `vector_sum(x, 0)` は軸 `0`(最も外側の軸)に沿って合計し、$3 \times 3$ の配列を生成します。 ```{include} ../../programFiles/markDown/advanced/sum-functions-for-arrays-program.md :start-after: :end-before: ``` :::