このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1320365280/140
#  [1] 授業単元: Cプロ 
#  [2] 問題文(含コード&リンク):  
#  3行3列の行列aを入力後、余因子行列で行列値|a|を求める 
#  

'3行3列の行列aを入力後、余因子行列で行列値|a|を求める' :-
        '3行3列の行列aを入力'(_a),
        '余因子行列で行列値|a|を求める'(_a,_行列式_aの値),
        writef('行列値|a|は%tです。\n',[_行列値_aの値]).

'3行3列の行列aを入力'(_a) :-
        length(_a,3),
        findall(L,(
                    nth1(_nth1,_a,L),
                    length(L,3),
                    '3列入力する'(_nth1,1,L)),
               _a).

'3列入力する'(_,_,[]).
'3列入力する'(_行位置,_列位置,[V|R]) :-
        writef('列入力[%t][%t] : ',[_行位置,_列位置]),
        get_line(Line),
        atom_to_term(Line,V,_),
        _列位置_2 is _列位置 + 1,
        '3列入力する'(_行位置,_列位置_2,R).

'余因子行列を使って逆行列を得る'(_n,_正方行列,_逆行列) :-
        '余因子行列で行列値|a|を求める'(_正方行列,_行列式の値),
        余因子行列(_n,_正方行列,_余因子行列),
        転置(_余因子行列,_転置された余因子行列),
        行列のすべての要素に値を掛ける(1,_n,_転置された余因子行列,1 / _行列式の値,_逆行列).

行列のすべての要素に値を掛ける(_行目,_n,LL,_,LL) :-
        _行目 > _n,!.
行列のすべての要素に値を掛ける(_行目,_n,LL1,_乗数 / _除数,LL2) :-
        '行基本変形'(_乗数 / _除数 # _行目,LL1,LL3),
        _行目_2 is _行目 + 1,
        行列のすべての要素に値を掛ける(_行目_2,_n,LL3,_乗数 / _除数,LL2).

'余因子行列で行列値|a|を求める'(_a,_行列式_aの値) :-
        余因子行列(_n,_a,_余因子行列),
        _a = [_aの第一行|_],
        _余因子行列 = [_余因子行列の第一行|_],
        '二つのならびの積の和'(_aの第一行,_余因子行列の第一行,_行列式_aの値).

'二つのならびの積の和'([],[],0).
'二つのならびの積の和'([A|R1],[B|R2],S) :-
        '二つのならびの積の和'(R1,R2,S_1),
        S is S_1 + A * B.

余因子行列(_n,_正方行列,_余因子行列) :-
        length(_余因子行列,_n),
        findall(L,(
                    nth1(_i,_余因子行列,L),
                    余因子行列の要素が余因子である(_n,_正方行列,_i,L)), 
                _余因子行列).

余因子行列の要素が余因子である(_n,_正方行列,_i,L) :-
        length(L,_n),
        findall(_余因子,(
                    nth1(_j,L,_余因子),
                    余因子(_n,_正方行列,_i,_j,_余因子)),
                L).

行列式の値(_正方行列,_i,_n,_行列式の値) :-
        findsum(W,(
                    'n次正方行列の要素を列・行取り出す'(_n,_正方行列,_i,_j,_正方行列の要素),
                    余因子(_n,_正方行列,_i,_j,_余因子),
                    W is _正方行列の要素 * _余因子),
                _行列式の値).

余因子(_n,_正方行列,_i,_j,_余因子) :-
        'n次正方行列から、第i行と第j列を取り除いた正方行列(n-1次正方行列の行列式に、(-1)のi+j乗をかけたものを、Aの(i,j)余因子といい、Cijで表します。'(_n,_正方行列,_i,_j,_余因子).

'n次正方行列から、第i行と第j列を取り除いた正方行列(n-1次正方行列の行列式に、(-1)のi+j乗をかけたものを、Aの(i,j)余因子といい、Cijで表します。'(_n,_正方行列,_i,_j,_余因子) :-
        '正方行列から第i行と第j列を取り除く'(_正方行列,_i,_j,_n_1次正方行列),
        'i,jから乗数を得る'(_i,_j,_乗数),
        二つの対角要素の積を得る(_n,_n_1次正方行列,_右下がり対角要素の積,_右上がり対角要素の積),        
        _余因子 is _乗数 * (_右下がり対角要素の積-_右上がり対角要素の積).

'正方行列から第i行と第j列を取り除く'(_正方行列,_i,_j,_n_1次正方行列) :-
        '第何行を取り除く'(_正方行列,_i,_第i行が取り除かれた行列),
        転置(_第i行が取り除かれた行列,_転置された第i行が取り除かれた行列),
        '第何行を取り除く'(_転置された第i行が取り除かれた行列,_j,_転置された第i行第j列が取り除かれた行列),
        転置(_転置された第i行第j列が取り除かれた行列,_n_1次正方行列).

'第何行を取り除く'(_正方行列,_第何行,_第i行が取り除かれた行列) :-
        append(L0,[L|R],_正方行列),
        length([_|L0],_第何行),
        append(L0,R,_第i行が取り除かれた行列).

二つの対角要素の積を得る(_n,_正方行列,_右下がり対角要素の積,_右上がり対角要素の積) :-
        二つの対角要素を得る(_n,_正方行列,_右下がり対角要素ならび,_右上がり対角要素ならび),
        対角要素の掛算(_右下がり対角要素ならび,_右下がり対角要素の積),
        対角要素の掛算(_右上がり対角要素ならび,_右上がり対角要素の積).


二つの対角要素を得る(_n,_正方行列,_右下がり対角要素ならび,_右上がり対角要素ならび) :-
        右下がり対角要素ならび(_n,_正方行列,_右下がり対角要素ならび),
        右上がり対角要素ならび(_n,_正方行列,_右上がり対角要素ならび).        

右下がり対角要素ならび(_n,_正方行列,_右下がり対角要素ならび) :-
        findall(V,(
                    nth1(_nth1,_正方行列,L),
                    nth1(_nth1,L,V)),
                _右下がり対角要素ならび).

右上がり対角要素ならび(_n,_正方行列,_右上がり対角要素ならび) :-
        findall(V,(
                    append(_,[L|R],_正方行列),
                    length([_|R],_nth1),
                    nth1(_nth1,L,V)),
                _右上がり対角要素ならび),!.

左下がり対角要素ならび(_n,_正方行列,_左下がり対角要素ならび) :-
        findall(V,(
                    nth1(_nth1,_正方行列,L),
                    length([_|R],_nth1),
                    append(_,[V|R],L)),
                _左下がり対角要素ならび),!.

左上がり対角要素ならび(_n,_正方行列,_左下がり対角要素ならび) :-
        findall(V,(
                    append(_,[L|R1],_正方行列),
                    length([_|R1],_nth1),
                    length([_|R2],_nth1),
                    append(_,[V|R2],L)),
                _左上がり対角要素ならび),!.

'i,jから乗数を得る'(_i,_j,(-1)) :-
        1 is (_i + _j) mod 2,!.
'i,jから乗数を得る'(_i,_j,1) :-
        0 is (_i + _j) mod 2,!.

対角要素の掛算([],1).
対角要素の掛算([A|R],X) :-
        対角要素の掛算(R,Y),
        X is A * Y.

行列式の値(_正方行列,_i,_n,_行列式の値) :-
        findsum(W,(

                    'n次正方行列の要素を列・行順序で取り出す'(_n,_正方行列,_i,_j,_正方行列の要素),
                    余因子(_n,_正方行列,_i,_j,_余因子),
                    W is _正方行列の要素 * _余因子),
                _行列式の値).

'n次正方行列の要素を行・列順序で取り出す'(_n,_正方行列,_i行,_j列,_正方行列の要素) :-
        between(1,_n,_i行),
        nth1(_i行,_正方行列,L),
        nth1(_j列,L,_正方行列の要素).

'n次正方行列の要素を列・行順序で取り出す'(_n,_正方行列,_i行,_j列,_正方行列の要素) :-
        between(1,_n,_j列),
        nth1(_i行,_正方行列,L),
        nth1(_j列,L,_正方行列の要素).