Abstract

1　はじめに
前回の研究集会「数学ソフトウエアーとその効果的教育利用に関する研究」で，大学初年度での線型代数の教育を例にとって，数式処理の活用について報告した（cf. [1, 3]). 行基本変形の問題に対する解法の自動作成について述べたが，その際に問題の自動作成の可能性について質問を受けた． 2016年1月の名古屋大での教式処理学会合同分科会におけるパネルディスカッション「TFX/数式処理による教材作成」においても同様の質問を受けたこともあり，問題の自動作成のプログラムを作成した．また，不定積分の問題の解答の自動作成もRisa/Asir上で実現したので，合わせて報告する．より具体的には，線形代数における行基本変形，対角化， Jordan標準形などを求める問題の自動作成と，不定積分の解法の自動作成を中心に報告する. これらはTFXを用いてPDFファイルとして出力するものであり, [7]で公開している（作成した350余りの関数の中のunim( )とintegrate( )の2つ).
2　行基本変形
数（一般には体）を成分とする行列に「ある行に（左から）ある数を掛けたものを別の行に加える」, 「ある行に0でない数（一般には可逆元）を（左から）掛ける」, 「2つの行を入れ替える」の3つの行基本変形を繰り返し施すことにより，（元の行列から一意に定まる）簡約行列に変形することである（これに関連した話題が[4]にある).行列の各行を先頭から見て0でない最初の成分があればそれを行頭と呼ぶことにすると,簡約行列とは，行頭があればその値は全て1で，その行以外のその列の成分は0となっていて，行頭のある列番号が行番号が増えるに従って増加している行列である（行頭のない列は最後に並ぶ).この行基本変形の演習問題のための整数行列を自動生成する関数unim( ）を数式処理Risa/Asirを用いて作成した（[7]に含まれている).  unim([m,n])とすると行基本変形用のm × n行列をランダムに出力する．たとえばos_md.unim([3,4]|res=1,dviout=1,lim=80);とすると，以下のような結果がPDFの形で得られる（毎回，異なる行列が得られる）. –2
2
なお，オプション・パラメータres=1,dviout=1は，得られた行列とその行基本変形の途中過程をTFXファイルとあわせてPDFまたはdviファイルで出力・表示することを意味する．また1im=80は，出力を上のように横幅80文字程度で改行することを意味する（これを指定しない場合は，行基本変形の1ステップ毎に改行した出力となる)．行基本変形過程の出力について，詳しくは[3]を参照して下さい. os_md.は[7]の関数を使うときにモジュール指定のため関数の頭につける識別子. A=os_md.unim([3,4]);では，行基本変形の問題用の3行4列の行列が，Risa/Asirで扱われる行列の形式で得られて，Aに代入される. [1] A=os_md.unim([3,4]); [ 2 -1 -3 3 ] [ -5 3 5 -9 ]
100題の問題の自動生成でも1秒とかからないので，多くの問題を生成してその中から演習問題やテストの問題を選ぶとよい．３× 4, 4 × 4, 4 × 5のそれぞれの場合の100題程度の例がPDFファイルの形で[7]に公開してある.デフォルトでは●得られる行列と適当な行基本変形の途中で現れる行列（dviout=1の指定で例示される行基本変形に現れる行列とは異なるかもしれない）の成分の絶対値が9以下. ●簡約形の成分には，小さな分母（一桁の自然数）の分数を許す. ●行列の階数はランダムに選ばれる．階数は2からmやnを超えない範囲でほぼ等確率となるように生成する. ●行頭の1の位置はランダムに選ばれる．ただし，1列目と2列目が一次独立となるものが現れる確率を高く設定してある.関連するオプション・パラメータについて以下に記す. ● rank=r：階数がrとなるもののみを生成する. ● int=1：簡約形が整数行列となるもののみを生成する. ● abs=v：変形途中や簡約形も含め行列の成分の絶対値がv以下になる範囲で生成する。たとえば[2] os_md.unim([3,3]|rank=2,abs=99);  /*階数が2の3x3行列 */ [ 28 -55 24 ] [ -15 49 -91 ] [ -33 64 -25 ] ● wt=w : １列目と２列目が一次独立となる行列の生成確率を変える．wは非負整数で， wを増やすと確率が高くなる（デフォルトはw = 2). ● num=r :ランダム化の程度を指定する（デフォルトはr = 100またはr = 200.大きい値ほどランダム化が大). ● res=1：（dviout=1を指定しないとき）得られた行列とそれから行基本変形で得られる整数行列（行頭の位置は簡約化した行列と同じ）との組を返す.さらにdviout=1を指定すると，行基本変形の過程も含めたものをTFXのソースやPDFの形で出力・表示する.一方，dviout=-1を指定すると，行基本変形の過程も含めたものをTEXのソースで返す.さらに，os_md.unim( )の引数による指定では● [m,n,k1,k2,...] :ある行のk,列目(ν = 1,2,...)が行頭となる簡約行列に行基本変形されるm × n行列に限る.たとえば[4,5,0,1,3]とすると,階数３の４×５の行列で，簡約化で得られる行列の行頭が0, 1, 3列目となるものに限る. [3] os_md.unim([4,5,0,1,3]); /* 0,1,3列目が行頭となる行をもつ簡約型に変換できる行列*/ [ 4 5 -6 2 -7 ] [ -4 -6 8 1 -1 ] [ 3 6 -9 -2 3 ] [ 6 5 -4 -1 4 ] ●行列Aを指定：Aに行基本変形を何度かランダムに行って返す．さらにboth=1を指定すると，あわせて列に対しても同様な変換を何度かランダムに行って返す. ●正整数mを指定：ユニモジュラーなm次正方行列を生成する. 3 × 4行列の行基本変形で簡約化を行う問題例100題を,行基本変形のステップ数が少ないものから順に並び替えてその解答例と共に示したPDFファイルの形で得るには, Risa/Asir上で[7]を用いて，たとえば次のようにすればよい. [4] for(I=0,M=[];I<100;I++) M=cons(os_md.unim([3,4]),M)$ [5] for(N=[];M!=[];M=cdr(M)) N=cons([length(os_md.mtoupper(car(M),Ol step=1,opt=7,dviout=-2)),car(M)],N)$ [6] for(M=qsort(N);M!=[];M=cdr(M)) os_md.mtoupper(car(M)[1],O|step=1, opt=7,dviout=2,lim=80)$ [4]でデフォルトのパラメータで100題の問題のリストMを作成し，[5]で行基本変形を求めてそのステップ数と問題との組のリストNを得，さらに［6］でステップ数でソートして順に100題の行基本変形の問題例とその解答をPDFファイルの形で出力している.
対角化とJordan標準形
3
対角化やJordan標準形を計算する演習問題のための整数成分の行列も，unim(  )においてオプションconj=1を指定することによってランダムに生成できる．たとえばos_md.unim(4|conj=1,res=1,dviout=1,int=1);によって，以下のような内容のPDFファイルが得られる.
これは
という行列の例を示しており，デフォルトでは，全ての行列が整数行列となる（演習問題用の行列はAで，BはそれのJordan標準形，Pは変換行列）.なお，上のように生成された行列に対して，ＡとＢに同じスカラー行列を加えてもよいことに注意すれば，問題のバリエーションが増える.関連するオプション・パラメータについて次に記す. ● diag=1：対角化可能行列に制限する. ● wt=w：行列の固有値は整数であるが，その絶対値を行列サイズ+w以下になるように制限する（wは非負整数で，w = 2がデフォルト). ● int=1：自明な部分があってつまらない行列が少なくなるようにする. ● int=2：Pは整数行列であるが，P−1は整数行列でないことも許す．int=kの値kをより大きな整数とすると，P-1は整数行列となならない問題が生成される確率がより高くなる. [7] os_md.unim(4|int=2,conj=1,res=1,dviout=1); −1 0 0 0
3 1 0 0 0 0 11 12 ● abs=v：基本行列による基底の変換によって行列をJordan標準形に直すことができるが，その基本行列や変換の過程で現れる行列（変換行列は除く）の全ての成分の絶対値がν以下の範囲で可能なもののみを生成する（デフォルトはν = 9). ● res=1：デフォルトでは変換行列とその逆行列の組[A,B]を返すが，これを指定すると変換行列も返す. [A,B,P,Q]が返されたとすると，B = QAP, Q = P-1で, BはJodran標準形. [8] os_md.unim(4|conj=1);  /*正方行列とJordan標準形の組*/ [[ 8 9 -1 -9 ] [ -5 -5 6 4 ] [ 2 2 -1 -2 ] [ 2 3 5 -4 ], [ -1 1 0 0 ] [ 0 -1 1 0 ] [ 0 0 -1 0 ] [ 0 0 0 1 ]]さらにdviout=1を指定すると，TEXを使ってPDFに変換して画面表示する. dviout=-1を指定すると，結果をTEXのソースで返す. ● num=r :ランダム化の程度を指定する(行基本変形の場合と同じ). os_md.unim( )の引数による指定では● os_md.unim( A | conj=1)：行列Aに共役な行列をランダムに返す．たとえば[9] os_md.unim(os_md.diagm(3,[0,-1,1])|conj=1); [ 4 -5 -8 ] [ -6 -1 -6 ] [ 7 -1 5 ]によって，固有値が0, −1,1となる3次の正方行列がランダムに得られる.ここで, os_md.diagm(n,[a1,...,an])は,対角成分がα1,...,anのn次対角行列を得る関数である. 4次の正方行列のJordan標準形を求める問題例とJordan標準形への変換行列を100題作成してPDFファイルとして出力・表示するには，たとえば以下のようにすればよい. [10] for(I=0,R=[];I<100;I++){T=os_md.unim(4|conj=1,res=1,int=1); R=cons([T[1] ,"&=" ,T[2] ,T[0] ,T[3]] ,R);}$ [11] S=os_md.ltotex(R|opt=["cr","spts0"],str=1,cr=11)$ [12] os_md.dviout(S|eq="align")$    /* Jordan標準形と変換行列100題 */ 100題の問題作成[10]は，1秒とかからずに終了する．その結果のTEX化[11]も1秒以内. それをPDFファイルにして表示するのに約3秒で，あわせて5秒程度．なお，3次と4次の正方行列の場合の問題と解の250題ずつをPDFファイルの形で[7]に公開してある.
4
積分
関数などのグラフを綺麗に描くための曲線の新たな描画方法を提案した（[2, 5]）が，それには与えられた点を通過する曲線のよい近似手法の提案でもあった．その手法は数値積分の計算に使えるのではないか，とKETpicを開発している高遠氏より2015年9月に問い合わせを受けた．そこで，曲線で囲まれた領域の面積の数値計算や，定積分（広義積分も含む）の教値計算を行う関数をRisa/Asir上で作成し，それをさらに線積分や複素積分の場合にも拡張した（[6]）.一方，教育用には正確な計算が必要なので，（正確な）留教計算や不定積分の計算をする関数も作成し（もともとのRisa/Asirには積分の計算機能は備わっていない），それらを[7]に含めて公開している．特に不定積分の計算では，最終結果だけなく，置換積分などの途中計算を含めて出力できるようにした．詳しくは[7]で公開されているライプラリos_muldif.rrのマニュアルos_muldif.pdfを参考にしていただくとして，ここではいくつかの実行例を記す. integrate(f,x)が，変数xによる不定積分ffdxを求める関数で，オプションdviout=2を指定すると，途中の変形過程もPDFファイルなどに変換されて示される.たとえば[13] os_md.integrate((a^2-x^2)^(1/2),x|dviout=2)$ [14] os_md.integrate(((1-cos(x))/(1/2-cos(x)))^(1/2),x|dviout=2)$ [15] os_md.integrate(1/(x^4+1),x|dviout=2)$としたとき，生成されるPDFファイルの中身をそのまま以下に載せると
オプション・パラメータをdviout=1とすると，途中経過を示さずに問題と結果のみを表示する.  dviout=-2とすると結果（dviout=-1では問題と結果）のTEXソースを返す. [16] os_md.integrate(2/(x^2-1),x|dviout=-1); \int \frac{2{dx}}{x^2-1}&=  \log\left| \frac{x-1}{x+1}\right| [17] os_md.integrate(2/(x^2-1),x|dviout=1)$ [18] os_md.integrate(sin(x)^3-sin(x),x|dviout=1)$ [19] os_md.integrate(4*sin(x)^3-3*sin(x),x|dviout=1)$
I=[a,b]を指定すると，区間[a,b]上での定積分を意味する（a,bを文字列inftyとすると，－∞または∞を表す． ["+",0]などとすると+0を表す．なお，これら広義積分の計算にはまだ改良の余地がある）. [20] os_md.integrate(x^2+alpha,x|I=[-1,1],dviout=1)$ [21] os_md.integrate(x*sin(x),x|I=[0,@pi],dviout=1)$ [22] os_md.integrate(x^2*exp(-x),x|I=[0,"infty"],dviout=1)$ [23] os_md.integrate(log(x),x|I=[["+",0],1],dviout=1)$とすると以下が得られる.