1% ---------------------------------------------------------------------- 2% BEGIN LICENSE BLOCK 3% Version: CMPL 1.1 4% 5% The contents of this file are subject to the Cisco-style Mozilla Public 6% License Version 1.1 (the "License"); you may not use this file except 7% in compliance with the License. You may obtain a copy of the License 8% at www.eclipse-clp.org/license. 9% 10% Software distributed under the License is distributed on an "AS IS" 11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 12% the License for the specific language governing rights and limitations 13% under the License. 14% 15% The Original Code is The ECLiPSe Constraint Logic Programming System. 16% The Initial Developer of the Original Code is Cisco Systems, Inc. 17% Portions created by the Initial Developer are 18% Copyright (C) 1995-2006 Cisco Systems, Inc. All Rights Reserved. 19% 20% Contributor(s): IC-Parc, Imperal College London 21% 22% END LICENSE BLOCK 23% 24% System: ECLiPSe Constraint Logic Programming System 25% Version: $Id: matrix_util.pl,v 1.3 2015/01/14 01:31:09 jschimpf Exp $ 26% ---------------------------------------------------------------------- 27 28:- module(matrix_util). 29 30:- comment(categories, ["Data Structures","Programming Utilities"]). 31:- comment(summary, "Predicates to build matrices from lists"). 32:- comment(author, "Joachim Schimpf, IC-Parc"). 33:- comment(copyright, "Cisco Systems, Inc"). 34:- comment(date, "$Date: 2015/01/14 01:31:09 $"). 35:- comment(desc, html( 36 "<p>This library contains predicates for representing and manipulating " 37 "matrices as nested lists. Both list of rows and list of columns " 38 "can be created and mapped into each other." 39 "</p><p>" 40 "Note that newer versions of ECLiPSe have good support for representing " 41 "matrices as multi-dimensional arrays, which is often preferrable to " 42 "the list representation used here.</p>" 43 )). 44 45:- comment(matrix/3, [ 46 summary:"Create a matrix as a list of rows", 47 template:"matrix(+NRow, +NCols, -Rows)", 48 eg:" 49 ?- matrix(2,3,M). 50 M = [[_175, _177, _179], [_183, _185, _187]] 51 Yes (0.00s cpu) 52 "]). 53:- comment(matrix/4, [ 54 summary:"Create a matrix as both a list of rows and a list of columns", 55 template:"matrix(+NRows, +NCols, -Rows, -Cols)", 56 eg:" 57 ?- matrix(2,3,Rows,Cols). 58 Rows = [[_183, _185, _187], [_191, _193, _195]] 59 Cols = [[_183, _191], [_185, _193], [_187, _195]] 60 Yes (0.00s cpu) 61 "]). 62:- comment(list2rows/4, [ 63 summary:"Create a matrix from a flat list of row-wise listed elements", 64 template:"list2rows(+List, +NRows, +NCols, -Rows)", 65 eg:" 66 ?- list2rows([1,2,3,4,5,6],2,3,Rows). 67 Rows = [[1, 2, 3], [4, 5, 6]] 68 Yes (0.00s cpu) 69 "]). 70:- comment(list2cols/4, [ 71 summary:"Create a matrix from a flat list of row-wise listed elements", 72 template:"list2cols(+List, +NRows, +NCols, -Cols)", 73 eg:" 74 ?- list2cols([1,2,3,4,5,6],2,3,Cols). 75 Cols = [[1, 4], [2, 5], [3, 6]] 76 Yes (0.00s cpu) 77 "]). 78:- comment(transpose/2, [ 79 summary:"Transpose a matrix (list of rows or list of columns)", 80 template:"transpose(+Matrix, -Transposed)", 81 eg:" 82 ?- list2rows([1,2,3,4,5,6],2,3,Rows), transpose(Rows,Cols). 83 Rows = [[1, 2, 3], [4, 5, 6]] 84 Cols = [[1, 4], [2, 5], [3, 6]] 85 Yes (0.00s cpu) 86 "]). 87:- comment(concat/2, [ 88 summary:"Concatenate all the rows (or columns) into a flat list", 89 template:"concat(+RowsOrCols, -List)", 90 see_also:[list2rows/4,list2cols/4,transpose/2], 91 eg:" 92 ?- list2rows([1,2,3,4,5,6],2,3,Rows), concat(Rows,Xs). 93 Rows = [[1, 2, 3], [4, 5, 6]] 94 Xs = [1, 2, 3, 4, 5, 6] 95 Yes (0.00s cpu) 96 "]). 97:- comment(read_data/3, [ 98 summary:"Read numbers from a file into List", 99 desc:html("Read numbers from a file into List until either the list is full or 100 the end of file has been reached. In the first case, not all numbers in the 101 file may be read, in the second, the list may not be fully instantiated. 102 The count of numbers that have actually been read is returned in Length. 103 "), 104 template:"read_data(+File, ?List, -Length)", 105 see_also:[list2rows/4,list2cols/4,transpose/2] 106 ]). 107 108:- export 109 matrix/3, % matrix(+NRow, +NCol, -Rows) 110 matrix/4, % matrix(+NRow, +NCol, -Rows, -Cols) 111 list2rows/4, % list2rows(+List, +NRows, +NCols, -Rows) 112 list2cols/4, % list2cols(+List, +NRows, +NCols, -Cols) 113 transpose/2, % transpose(+Rows, -Cols) or transpose(+Cols, -Rows) 114 concat/2, % concat(+RowsOrCols, -List) 115 read_data/3. % read_data(+File, ?List, -Length) 116 117 118 119matrix(NRow, NCol, Rows, Cols) :- 120 matrix(NRow, NCol, Rows), 121 transpose(Rows, Cols). 122 123matrix(0, _NCol, LoL) :- !, LoL=[]. 124matrix(NRow, NCol, [L|LoL1]) :- 125 integer(NRow), NRow > 0, 126 NRow1 is NRow-1, 127 length(L, NCol), 128 matrix(NRow1, NCol, LoL1). 129 130list2matrix([], 0, _NCol, []) :- !. 131list2matrix(List, NRow, NCol, [Row|Rows]) :- 132 integer(NRow), NRow > 0, 133 NRow1 is NRow-1, 134 first_n(NCol, List, Row, Rest), 135 list2matrix(Rest, NRow1, NCol, Rows). 136 137first_n(0, L, [], L) :- !. 138first_n(N, [X|Xs], [X|Fs], Rest) :- 139 N1 is N-1, 140 first_n(N1, Xs, Fs, Rest). 141 142list2rows([], 0, _, []) :- !. 143list2rows(List, NRow, NCol, [Row|Rows]) :- 144 plus(NRow1,1,NRow), 145 first_n(NCol, List, Row, Rest), 146 list2rows(Rest, NRow1, NCol, Rows). 147 148list2cols(List, NRow, NCol, Cols) :- 149 list2rows(List, NRow, NCol, Rows), 150 transpose(Rows, Cols). 151 152transpose([], []). 153transpose(LoL, Cols) :- 154 heads_and_tails(LoL, Col, LoL1), 155 ( Col == [] -> 156 Cols = [] 157 ; 158 Cols = [Col|Cols0], 159 transpose(LoL1, Cols0) 160 ). 161 162heads_and_tails([], [], []). 163heads_and_tails([L|Ls], Hs, Ts) :- 164 ( L == [] -> 165 Hs = Hs0, Ts = Ts0 166 ; 167 L = [H|T], Hs = [H|Hs0], Ts = [T|Ts0] 168 ), 169 heads_and_tails(Ls, Hs0, Ts0). 170 171concat([], []). 172concat([L|Ls], C) :- 173 concat(L, C, C0), 174 concat(Ls, C0). 175 176concat([], L, L). 177concat([X|Xs], [X|Ys], L) :- 178 concat(Xs, Ys, L). 179 180% read numbers until list is full or end of file. 181 182read_data(File, L, N) :- 183 open(File, read, Stream), 184 read_floats(Stream, L, 0, N), 185 close(Stream). 186 187read_floats(Stream, [X|Xs], N0, N) :- 188 read_token(Stream, Token, _), 189 ( number(Token) -> 190 !, % if called with a variable 191 X is float(Token), 192 N1 is N0+1, 193 read_floats(Stream, Xs, N1, N) 194 ; 195 Token \= end_of_file, 196 get_stream_info(Stream, name, Name), 197 get_stream_info(Stream, line, Line), 198 printf(error, "Syntax error in file \"%w\", line %d: %w\n", 199 [Name, Line, Token]), 200 close(Stream), 201 abort 202 ). 203read_floats(_Stream, [], N, N). 204 205 206