« HumaneのAIピンの内部構造がFCCで公開されていた。QualcommのSnapdragon 720GにX15 LTEモデム、SkyworksのFEM、QualcommのSAWなどがなんとなくわかる。 | トップページ | 長岡京・下海印寺の小泉川の鯉のぼりを観てきた。 »

2024年4月12日 (金)

Excel VBAからOfficeスクリプト(TypeScript)へ乗換るための数値計算(4) LU分解(奥村先生のC言語による最新アルゴリズム事典のTypeScript移植版)で連立方程式を計算する。セルの範囲を指定して実行すると任意の大きさの連立方程式の解がセルに表示される。

先日、2次元配列と1次元配列がExcelのセルから読み出せるようになったので、早速行列計算をしてみる。最近のXで線形代数がトレンドに入ることが多いし。

まずはLU分解がいいだろう。奥村先生のC言語による最新アルゴリズム事典(今は改訂新版 C言語による標準アルゴリズム事典)の

https://github.com/okumuralab/algo-c

LU分解をそのままTypeScriptに移植させてもらいました。変数の宣言が違うだけなのですぐに移植完了。

画面はこんな感じで。

Officescript_lu01

実行している動画(クリックで現れます)。

Officescriptlu_20240410201501

ソースコード:

function main(workbook: ExcelScript.Workbook) {
  let range : number[][]= workbook.getSelectedRange().getValues() as number[][];
  let row : number  = workbook.getSelectedRange().getRowIndex();
  let column: number = workbook.getSelectedRange().getColumnIndex();
  const n : number = range.length;
  let a: number[][] = Array(n);
  let b: number[] = Array(n);
  let ip: number[] = Array(n);
  let x: number[] = Array(n);

 

  for (let i = 0 ; i < n; i++) {
    a[i] = range[i].slice(0, n);
    b[i] = range[i][n];
  }

 

    let det = lu(n, a, ip);
    solve(n, a, b, ip, x);
    workbook.getActiveWorksheet().getRangeByIndexes(row, column + n + 1, n, 1)
                    .setValues(x.map((x) => [x]));

 

}

 

function lu(n : number, a : number[][], ip : number[])
{
  let ii : number;  let ik : numberlet jj  : number;
  let t : number;   let u :  numberlet det : number;
  let weight : Array<number> = Array(n);

 

  det = 0;                   /* 行列式 */
  for (let k = 0; k < n; k++) {  /* 各行について */
    ip[k] = k;             /* 行交換情報の初期値 */
    u = 0;                 /* その行の絶対値最大の要素を求める */
    for (let j = 0; j < n; j++) {
      t = Math.abs(a[k][j]); if (t > u) u = t;
    }
    if (u == 0return null/* 0 なら行列はLU分解できない */
    weight[k] = 1 / u;     /* 最大絶対値の逆数 */
  }
  det = 1;                   /* 行列式の初期値 */
  for (let k = 0; k < n; k++) {  /* 各行について */
    u = -1;
    for (let i = k; i < n; i++) {  /* より下の各行について */
      ii = ip[i];            /* 重み×絶対値 が最大の行を見つける */
      t = Math.abs(a[ii][k]) * weight[ii];
      if (t > u) { u = t; jj = i; }
    }
    ik = ip[jj];
    if (jj != k) {
      ip[jj] = ip[k]; ip[k] = ik;  /* 行番号を交換 */
      det = -det;  /* 行を交換すれば行列式の符号が変わる */
    }
    u = a[ik][k]; det *= u;  /* 対角成分 */
    if (u == 0return null;    /* 0 なら行列はLU分解できない */
    for (let i = k + 1; i < n; i++) {  /* Gauss消去法 */
      ii = ip[i];
      t = (a[ii][k] /= u);
      for (let j = k + 1; j < n; j++)
        a[ii][j] -= t * a[ik][j];
    }
  }
  
  return det;           /* 戻り値は行列式 */
}

 

function solve(n : number, a : number[][], b : number[], ip : number[] , x : number[])
{
  let ii : number;
  let t : number;

 

  for (let i = 0; i < n; i++) {       /* Gauss消去法の残り */
    ii = ip[i]; t = b[ii];
    for (let j = 0; j < i; j++) t -= a[ii][j] * x[j];
    x[i] = t;
  }
  for (let i = n - 1; i >= 0; i--) {  /* 後退代入 */
    t = x[i]; ii = ip[i];
    for (let j = i + 1; j < n; j++) t -= a[ii][j] * x[j];
    x[i] = t / a[ii][i];
  }
}


結構いい感じで動くな。さらに次行ってみよう。FFTか、VBAとの速度比較か…

 

 

(過去のもの)

 Excel VBAからOfficeスクリプト(TypeScript)へ乗換るための数値計算(3) セル範囲を2次元配列、1次元配列に入れるところでハマる…as number[][]で数値型に直したり、[].concat(...a)で2次元から1次元に直したり、a.map((x) => [x])で1次元から2次元に直すなどした。

Excel VBAからOfficeスクリプト(TypeScript)へ乗換るための数値計算(2) 4段4次のルンゲクッタ法でローレンツ方程式を計算してみる。

Excelの自動化がいつの間にかVBAじゃなくてデスクトップ版でもOfficeスクリプト(TypeScript)で出来るようになっていた。Python in Excelとか触っているうちに出遅れた…そこで先日作った複素数クラスを使ってセルに入力した値を複素数計算できるようにした。

« HumaneのAIピンの内部構造がFCCで公開されていた。QualcommのSnapdragon 720GにX15 LTEモデム、SkyworksのFEM、QualcommのSAWなどがなんとなくわかる。 | トップページ | 長岡京・下海印寺の小泉川の鯉のぼりを観てきた。 »

パソコン・インターネット」カテゴリの記事

学問・資格」カテゴリの記事

日記・コラム・つぶやき」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« HumaneのAIピンの内部構造がFCCで公開されていた。QualcommのSnapdragon 720GにX15 LTEモデム、SkyworksのFEM、QualcommのSAWなどがなんとなくわかる。 | トップページ | 長岡京・下海印寺の小泉川の鯉のぼりを観てきた。 »

最近の記事

最近のコメント

2024年12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
フォト
無料ブログはココログ