【出典】https://twitter.com/TakaoOzaki/status/306175708726706177
【要約】述語 単位行列/2 を“うまく”定義する。
単位行列 E_n := [ δ_i,j ]_n×n からの連想として「添字」を用いる実装をすると、双方向性を保つのがめんどくさい
(組み込み述語 var による条件分岐がどうしても必要になる気がする)。
【出典】https://twitter.com/TakaoOzaki/status/306175708726706177
【要約】述語 単位行列/2 を“うまく”定義する。
単位行列 E_n := [ δ_i,j ]_n×n からの連想として「添字」を用いる実装をすると、双方向性を保つのがめんどくさい
(組み込み述語 var による条件分岐がどうしても必要になる気がする)。
mylength([], 0). mylength([_|T], N) :- mylength(T, N1), N is N1 + 1. 零リスト([]). 零リスト([0|T]) :- 零リスト(T). 単位行列(N, LL) :- mylength(LL, N), 単位行列_(N, LL). 単位行列_(0, []). 単位行列_(N, [[1|RowT]|T]) :- % number(N), N > 0, N1 is N - 1, mylength(RowT, N1), !, % important! 行列の左に列ベクトルを加える(T1, ClmT, T), 零リスト(RowT), 零リスト(ClmT), 単位行列_(N1, T1). 行列の左に列ベクトルを加える([], [], []). 行列の左に列ベクトルを加える([T|LL1], [H|V], [[H|T]|LL]) :- 行列の左に列ベクトルを加える(LL1, V, LL). ?- 単位行列(2, [[1, 0], [0, 1]]). /* yes */ ?- 単位行列(N, [[1, 0], [0, 1]]). /* N = 2 ; no */ % うまく定義しないと no が返らず無限ループに陥ることも。 ?- 単位行列(2, LL). /* LL = [[1, 0], [0, 1]] ; ... (無限ループに陥る) */ % no を返してほしいところだが、次の結果を得るためにはこの挙動にならざるをえない? ?- 単位行列(N, LL). /* N = 0, LL = [] ; N = 1, LL = [[1, 0], [0, 1]] ; N = 2, LL = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] ; N = 3, LL = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] ; ... (各Nについて無限に成功する) */ % うまく定義しないと N = 0, 1 だけで終わってしまうことも。