選択多項式
- AMRG 演算を一般化したらそうなった.
- 暗号文から要素を選択するのでそう名付けた
線形変換は置換を表す?
- ex. は置換にすると
- では は?
- 内積は に対し,
- 置換では表現できない
演算を多項式表現する
定義(選択多項式)
暗号文の組 に対し, 演算をした結果は多変数多項式のベクトル で表される.
Add:Mult:Rotl:
命題
選択多項式 は1つ以上の選択多項式 の線形結合に分解出来る
定義(自明な分解)
選択多項式 は単位選択多項式(=1つだけの非零要素からなる1変数1次の選択多項式) の線形結合に出来る.
例:
分解と演算コスト
- ex. の分解を考える.
自明な分解
ops: 2 add, 3 mult, 6rots
最適な分解
ops: 2 add, 1 mult, 3rots
最適な分解の構成の仕方について(WIP)
- 多項式が与えられた時に最適な分解を探索するのは困難そう
- 定式化をしてソルバで解くことは恐らく出来る
- 自明な分解をしてからコストの低い結合をする?
- 前ページの例のように0が含まれていると厄介
命題
置換 に対して置換行列 が決まるように, 多変多項式である選択多項式行列 に対しても置換マスク行列 がある
-
関係ないが, グレブナー基底 ?
-
例えば置換マスク行列の足し合わせとかは同じ要素を足すとかあるので要素はuint(=インデックス) or 0(=使わない)ではなく多項式だと良い? 定数倍や定数演算も表せるので
- ex.
[x_1, x_2] |-> [3x_1 + x_2]- それって 線形作用素 では?
- ex.
-
ループを伴う演算を置換マスク行列 で表した後に最適な演算(=最も演算コストが低いinstructions)に分解
- これが難しそう, 置換の分解の拡張になりそう
rotlは連続巡回置換(l l+1, ... n, 1, ... l-1)ってこと?- 回転量が最小になるような置換の分解の仕方は一意ではない気がする
- Cyclic permutation - Wikipedia これの連続になってる版に関する知見がほしい
- 逆変換は逆向きの書き換え規則を作ってeggにやらせるのが丸いか
- これが難しそう, 置換の分解の拡張になりそう
とりあえずソルバを使って最適解を求めてみる
- 目的関数: 多項式ベクトルのコストだと思ったけど多項式から一意に決まらない -> 各演算に対応した単位行列?の分解に対してのコスト
- 疎行列の分解に対応している?
- マスク行列が重み, 定数項がバイアスと見ればperceptronの活性化関数ない版に見える気もする, 気のせいかも
問題
多変数多項式ベクトル が与えられた時に演算コストが最小になるような多変数多項式ベクトルの和の分解 を計算したい.
- 関連研究探し, 「vector of multivariate polynomial decomposition」とかで調べても全然出てこない. 多変数多項式を並べるということをしないらしい.
- もう少し抽象化できれば数学のテーマとしてあるんだろうか? 全くわからない
- https://www.jstage.jst.go.jp/article/sicetr1965/30/5/30_5_519/_pdf
- 制御理論 の論文だが, 多変数多項式の行列で要素同士の共通因数みたいな話が出てきた. 少し近いかも しれない
まずは多項式が線形な場合のみ考える?.
-
線形作用素に対するスペクトル分解というのがあるらしい
-
- やはり, 計算グラフの最適化の方が近いか
定式化
,
選択多項式 の分解 は
ただし,
制約,
ソルバ実装
現状, 回転に対応していない, ベクトルから多項式にする.
- Q: E-graphによる自明な分解から結合は可能? todo
a0 a1 b0 b1 a0 a1 b0 b3
a2 a3 . b2 b3 = a3 a2 . b2 b1 +
get_index
get_index(A: vec, i: uint)
<=> A * mask({i}) << i
例: get_index(A, 1)
set_index
set_index(A: vec, i: usize, v: uint)
<=> (A * mask(inv({i})) + ((all(v) * mask({i})) >> i)
naive
rep i d
rep j d
rep k d
c[i][j] += a[i][k] * b[k][j]
c
into dot-product
fn matmul (a b) =
(rep i d
(rep j d
c[i][j] = a[Li] . b[Cj]
)
)
col
- 行列としてみたとき, 列目を先頭 個に並べる
# cのk列目(=[d * i + k])を先頭d個(=[i])に並べる
fn col(v k) =
(rep + i d
rotl(v[d * i + k], (d * i + k - i))
)
置換行列
- 値が不要な所は0
ex. col(A, 1)
が定まり,
line
- 行列の 行目を取得して先頭 個に並べる
line(A, k)
<=>
A * mask({ kd, ..., kd + d }) << kd
内積
fn dp (va vb) =
(rep + i n
(get_index va i) * (get_index vb i)
)
行列積
fn matmul (a b) =
let r = (const 0)
(rep %i then d
(rep %j then d
let a_line_i = rotl(a .* mask(d * i, d * (i + 1)), d * i)
let b_col_j = col_vec(b, j)
// r[i * d + j] = <a_i | b_j>
set_index(r, i * d + j, dp(a_line_i, b_col_j))
)
)- verified
- ここで は単射より
- <=>
- 単射なのでマスクして回転する必要が無い位の意味
- <=>
get_index(k) =
line(k) =
col(k) =
具体例:
写像で表す.
a = [1, 2, 3, 4], b = [5, 6, 7, 8]
naive
# (kd + i → i) . (id + k → i)
dp := line(i) . col(j) = [*, *, 0, 0]
# (0..d +→ 0)
dp_sum = sum_{d} dp << i = [*, *, 0, 0]
dp_sum_mask = dp_sum * mask(id + j) = [*, 0, 0, 0]
# (0 → id + j)
dp_sum_mask_rot = dp_sum_mask >> (id + j) = [0, *, 0, 0]
matmul(a, b)[id + j] = dp_sum_mask_rot
->lintrans
# (kd + i → i) . (id + k → i) devided by k
dp := line(i) . col(j) = [*, *, 0, 0]
dp_k=0 :=