| | 62 | package Vectors "Library of functions operating on vectors" |
| | 63 | extends Modelica.Icons.Library; |
| | 64 | |
| | 65 | annotation ( |
| | 66 | preferedView = "info", |
| | 67 | Documentation(info="<HTML> |
| | 68 | <h4>Library content</h4> |
| | 69 | <p> |
| | 70 | This library provides functions operating on vectors: |
| | 71 | </p> |
| | 72 | <table border=1 cellspacing=0 cellpadding=2> |
| | 73 | <tr><th><i>Function</i></th> |
| | 74 | <th><i>Description</i></th> |
| | 75 | </tr> |
| | 76 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.isEqual\">isEqual</a>(v1, v2)</td> |
| | 77 | <td>Determines whether two vectors have the same size and elements</td> |
| | 78 | </tr> |
| | 79 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.norm\">norm</a>(v,p)</td> |
| | 80 | <td>p-norm of vector v</td> |
| | 81 | </tr> |
| | 82 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.length\">length</a>(v)</td> |
| | 83 | <td>Length of vector v (= norm(v,2), but inlined and therefore usable in |
| | 84 | symbolic manipulations) </td> |
| | 85 | </tr> |
| | 86 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.normalize\">normalize</a>(v)</td> |
| | 87 | <td>Return normalized vector such that length = 1 and prevent |
| | 88 | zero-division for zero vector</td> |
| | 89 | </tr> |
| | 90 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.reverse\">reverse</a>(v)</td> |
| | 91 | <td>Reverse vector elements</td> |
| | 92 | </tr> |
| | 93 | <tr><td><a href=\"Modelica:Modelica.Math.Vectors.sort\">sort</a>(v)</td> |
| | 94 | <td>Sort elements of vector in ascending or descending order</td> |
| | 95 | </tr> |
| | 96 | </table> |
| | 97 | <h4>See also</h4> |
| | 98 | <a href=\"Modelica:Modelica.Math.Matrices\">Matrices</a> |
| | 99 | </HTML>")); |
| | 100 | |
| | 101 | function isEqual "Determine if two Real vectors are numerically identical" |
| | 102 | extends Modelica.Icons.Function; |
| | 103 | input Real v1[:] "First vector"; |
| | 104 | input Real v2[:] "Second vector (may have different length as v1"; |
| | 105 | input Real eps(min=0) = 0 |
| | 106 | "Two elements e1 and e2 of the two vectors are identical if abs(e1-e2) <= eps"; |
| | 107 | output Boolean result |
| | 108 | "= true, if vectors have the same length and the same elements"; |
| | 109 | |
| | 110 | annotation (preferedView="info", Documentation(info="<HTML> |
| | 111 | <h4>Syntax</h4> |
| | 112 | <blockquote><pre> |
| | 113 | Vectors.<b>isEqual</b>(v1, v2); |
| | 114 | Vectors.<b>isEqual</b>(v1, v2, eps=0); |
| | 115 | </pre></blockquote> |
| | 116 | <h4>Description</h4> |
| | 117 | <p> |
| | 118 | The function call \"<code>Vectors.isEqual(v1, v2)</code>\" returns <b>true</b>, |
| | 119 | if the two Real vectors v1 and v2 have the same dimensions and |
| | 120 | the same elements. Otherwise the function |
| | 121 | returns <b>false</b>. Two elements e1 and e2 of the two vectors |
| | 122 | are checked on equality by the test \"abs(e1-e2) ≤ eps\", where \"eps\" |
| | 123 | can be provided as third argument of the function. Default is \"eps = 0\". |
| | 124 | </p>Modelica.Utilities.Strings.isEqual |
| | 125 | <h4>Example</h4> |
| | 126 | <blockquote><pre> |
| | 127 | Real v1[3] = {1, 2, 3}; |
| | 128 | Real v2[3] = {1, 2, 3, 4}; |
| | 129 | Real v3[3] = {1, 2, 3.0001}; |
| | 130 | Boolean result; |
| | 131 | <b>algorithm</b> |
| | 132 | result := Vectors.isEqual(v1,v2); // = <b>false</b> |
| | 133 | result := Vectors.isEqual(v1,v3); // = <b>false</b> |
| | 134 | result := Vectors.isEqual(v1,v1); // = <b>true</b> |
| | 135 | result := Vectors.isEqual(v1,v3,0.1); // = <b>true</b> |
| | 136 | </pre></blockquote> |
| | 137 | <h4>See also</h4> |
| | 138 | <a href=\"Modelica:Modelica.Math.Matrices.isEqual\">Matrices.isEqual</a>, |
| | 139 | <a href=\"Modelica:Modelica.Utilities.Strings.isEqual\">Strings.isEqual</a> |
| | 140 | </HTML>")); |
| | 141 | protected |
| | 142 | Integer n=size(v1, 1) "Dimension of vector v1"; |
| | 143 | Integer i=1; |
| | 144 | algorithm |
| | 145 | result := false; |
| | 146 | if size(v2, 1) == n then |
| | 147 | result := true; |
| | 148 | while i <= n loop |
| | 149 | if abs(v1[i] - v2[i]) > eps then |
| | 150 | result := false; |
| | 151 | i := n; |
| | 152 | end if; |
| | 153 | i := i + 1; |
| | 154 | end while; |
| | 155 | end if; |
| | 156 | end isEqual; |
| | 157 | |
| | 158 | function norm "Returns the norm of a vector" |
| | 159 | extends Modelica.Icons.Function; |
| | 160 | input Real v[:] "Vector"; |
| | 161 | input Real p(min=1) = 2 |
| | 162 | "Type of p-norm (often used: 1, 2, or Modelica.Constants.inf)"; |
| | 163 | output Real result "p-norm of vector v"; |
| | 164 | |
| | 165 | annotation (preferedView="info", Documentation(info="<HTML> |
| | 166 | <h4>Syntax</h4> |
| | 167 | <blockquote><pre> |
| | 168 | Vectors.<b>norm</b>(v); |
| | 169 | Vectors.<b>norm</b>(v,p=2); // 1 ≤ p ≤ ∞ |
| | 170 | </pre></blockquote> |
| | 171 | <h4>Description</h4> |
| | 172 | <p> |
| | 173 | The function call \"<code>Vectors.<b>norm</b>(v)</code>\" returns the |
| | 174 | <b>Euclidean norm</b> \"<code>sqrt(v*v)</code>\" of vector v. |
| | 175 | With the optional |
| | 176 | second argument \"p\", any other p-norm can be computed: |
| | 177 | </p> |
| | 178 | <center> |
| | 179 | <IMG SRC=\"../Images/vectorNorm.png\" ALT=\"function Vectors.norm\"> |
| | 180 | </center> |
| | 181 | <p> |
| | 182 | Besides the Euclidean norm (p=2), also the 1-norm and the |
| | 183 | infinity-norm are sometimes used: |
| | 184 | </p> |
| | 185 | <table border=1 cellspacing=0 cellpadding=2> |
| | 186 | <tr><td><b>1-norm</b></td> |
| | 187 | <td>= sum(abs(v))</td> |
| | 188 | <td><b>norm</b>(v,1)</td> |
| | 189 | </tr> |
| | 190 | <tr><td><b>2-norm</b></td> |
| | 191 | <td>= sqrt(v*v)</td> |
| | 192 | <td><b>norm</b>(v) or <b>norm</b>(v,2)</td> |
| | 193 | </tr> |
| | 194 | <tr><td><b>infinity-norm</b></td> |
| | 195 | <td>= max(abs(v))</td> |
| | 196 | <td><b>norm</b>(v,Modelica.Constants.<b>inf</b>)</td> |
| | 197 | </tr> |
| | 198 | </table> |
| | 199 | <p> |
| | 200 | Note, for any vector norm the following inequality holds: |
| | 201 | </p> |
| | 202 | <blockquote><pre> |
| | 203 | <b>norm</b>(v1+v2,p) ≤ <b>norm</b>(v1,p) + <b>norm</b>(v2,p) |
| | 204 | </pre></blockquote> |
| | 205 | <h4>Example</h4> |
| | 206 | <blockquote><pre> |
| | 207 | v = {2, -4, -2, -1}; |
| | 208 | <b>norm</b>(v,1); // = 9 |
| | 209 | <b>norm</b>(v,2); // = 5 |
| | 210 | <b>norm</b>(v); // = 5 |
| | 211 | <b>norm</b>(v,10.5); // = 4.00052597412635 |
| | 212 | <b>norm</b>(v,Modelica.Constants.inf); // = 4 |
| | 213 | </pre></blockquote> |
| | 214 | <h4>See also</h4> |
| | 215 | <a href=\"Modelica:Modelica.Math.Matrices.norm\">Matrices.norm</a> |
| | 216 | </HTML>")); |
| | 217 | algorithm |
| | 218 | if p == 2 then |
| | 219 | result:=sqrt(v*v); |
| | 220 | elseif p == Modelica.Constants.inf then |
| | 221 | result:=max(abs(v)); |
| | 222 | elseif p == 1 then |
| | 223 | result:=sum(abs(v)); |
| | 224 | else |
| | 225 | result:=(sum(abs(v[i])^p for i in 1:size(v, 1)))^(1/p); |
| | 226 | end if; |
| | 227 | end norm; |
| | 228 | |
| | 229 | function length "Return length of a vector" |
| | 230 | extends Modelica.Icons.Function; |
| | 231 | input Real v[:] "Vector"; |
| | 232 | output Real result "Length of vector v"; |
| | 233 | |
| | 234 | annotation (preferedView="info", Documentation(info="<html> |
| | 235 | <h4>Syntax</h4> |
| | 236 | <blockquote><pre> |
| | 237 | Vectors.<b>length</b>(v); |
| | 238 | </pre></blockquote> |
| | 239 | <h4>Description</h4> |
| | 240 | <p> |
| | 241 | The function call \"<code>Vectors.<b>length</b>(v)</code>\" returns the |
| | 242 | <b>Euclidean length</b> \"<code>sqrt(v*v)</code>\" of vector v. |
| | 243 | The function call is equivalent to Vectors.norm(v). The advantage of |
| | 244 | length(v) over norm(v)\"is that function length(..) is implemented |
| | 245 | in one statement and therefore the function is usually automatically |
| | 246 | inlined. Further symbolic processing is therefore possible, which is |
| | 247 | not the case with function norm(..). |
| | 248 | </p> |
| | 249 | <h4>Example</h4> |
| | 250 | <blockquote><pre> |
| | 251 | v = {2, -4, -2, -1}; |
| | 252 | <b>length</b>(v); // = 5 |
| | 253 | </pre></blockquote> |
| | 254 | <h4>See also</h4> |
| | 255 | <a href=\"Modelica:Modelica.Math.Vectors.norm\">Vectors.norm</a> |
| | 256 | </html>")); |
| | 257 | algorithm |
| | 258 | result := sqrt(v*v); |
| | 259 | end length; |
| | 260 | |
| | 261 | function normalize |
| | 262 | "Return normalized vector such that length = 1 and prevent zero-division for zero vector" |
| | 263 | extends Modelica.Icons.Function; |
| | 264 | input Real v[:] "Vector"; |
| | 265 | input Real eps = 100*Modelica.Constants.eps "if |v| < eps then result = v"; |
| | 266 | output Real result[size(v, 1)] "Input vector v normalized to length=1"; |
| | 267 | |
| | 268 | annotation (preferedView="info", Documentation(info="<html> |
| | 269 | <h4>Syntax</h4> |
| | 270 | <blockquote><pre> |
| | 271 | Vectors.<b>normalize</b>(v); |
| | 272 | Vectors.<b>normalize</b>(v,eps=100*Modelica.Constants.eps); |
| | 273 | </pre></blockquote> |
| | 274 | <h4>Description</h4> |
| | 275 | <p> |
| | 276 | The function call \"<code>Vectors.<b>normalize</b>(v)</code>\" returns the |
| | 277 | <b>unit vector</b> \"<code>v/length(v)</code>\" of vector v. |
| | 278 | If length(v) is close to zero (more precisely, if length(v) < eps), |
| | 279 | v is returned in order to avoid |
| | 280 | a division by zero. For many applications this is useful, because |
| | 281 | often the unit vector <b>e</b> = <b>v</b>/length(<b>v</b>) is used to compute |
| | 282 | a vector x*<b>e</b>, where the scalar x is in the order of length(<b>v</b>), |
| | 283 | i.e., x*<b>e</b> is small, when length(<b>v</b>) is small and then |
| | 284 | it is fine to replace <b>e</b> by <b>v</b> to avoid a division by zero. |
| | 285 | </p> |
| | 286 | <p> |
| | 287 | Since the function is implemented in one statement, |
| | 288 | it is usually inlined and therefore symbolic processing is |
| | 289 | possible. |
| | 290 | </p> |
| | 291 | <h4>Example</h4> |
| | 292 | <blockquote><pre> |
| | 293 | <b>normalize</b>({1,2,3}); // = {0.267, 0.534, 0.802} |
| | 294 | <b>normalize</b>({0,0,0}); // = {0,0,0} |
| | 295 | </pre></blockquote> |
| | 296 | <h4>See also</h4> |
| | 297 | <a href=\"Modelica:Modelica.Math.Vectors.length\">Vectors.length</a> |
| | 298 | </html>")); |
| | 299 | algorithm |
| | 300 | result := if length(v) >= eps then v/length(v) else v; |
| | 301 | end normalize; |
| | 302 | |
| | 303 | function reverse "Reverse vector elements (e.g. v[1] becomes last element)" |
| | 304 | extends Modelica.Icons.Function; |
| | 305 | input Real v[:] "Vector"; |
| | 306 | output Real result[size(v, 1)] "Elements of vector v in reversed order"; |
| | 307 | |
| | 308 | annotation (preferedView="info", Documentation(info="<html> |
| | 309 | <h4>Syntax</h4> |
| | 310 | <blockquote><pre> |
| | 311 | Vectors.<b>reverse</b>(v); |
| | 312 | </pre></blockquote> |
| | 313 | <h4>Description</h4> |
| | 314 | <p> |
| | 315 | The function call \"<code>Vectors.<b>reverse</b>(v)</code>\" returns the |
| | 316 | vector elements in reverse order. |
| | 317 | </p> |
| | 318 | <h4>Example</h4> |
| | 319 | <blockquote><pre> |
| | 320 | <b>reverse</b>({1,2,3,4}); // = {4,3,2,1} |
| | 321 | </pre></blockquote> |
| | 322 | </html>")); |
| | 323 | algorithm |
| | 324 | result := {v[end-i+1] for i in 1:size(v,1)}; |
| | 325 | end reverse; |
| | 326 | |
| | 327 | function sort "Sort elements of vector in ascending or descending order" |
| | 328 | extends Modelica.Icons.Function; |
| | 329 | input Real v[:] "Vector to be sorted"; |
| | 330 | input Boolean ascending = true |
| | 331 | "= true if ascending order, otherwise descending order"; |
| | 332 | output Real sorted_v[size(v,1)] = v "Sorted vector"; |
| | 333 | output Integer indices[size(v,1)] = 1:size(v,1) "sorted_v = v[indices]"; |
| | 334 | |
| | 335 | annotation (preferedView="info",Documentation(info="<HTML> |
| | 336 | <h4>Syntax</h4> |
| | 337 | <blockquote><pre> |
| | 338 | sorted_v = Vectors.<b>sort</b>(v); |
| | 339 | (sorted_v, indices) = Vectors.<b>sort</b>(v, ascending=true); |
| | 340 | </pre></blockquote> |
| | 341 | <h4>Description</h4> |
| | 342 | <p> |
| | 343 | Function <b>sort</b>(..) sorts a Real vector v |
| | 344 | in ascending order and returns the result in sorted_v. |
| | 345 | If the optional argument \"ascending\" is <b>false</b>, the vector |
| | 346 | is sorted in descending order. In the optional second |
| | 347 | output argument the indices of the sorted vector with respect |
| | 348 | to the original vector are given, such that sorted_v = v[indices]. |
| | 349 | </p> |
| | 350 | <h4>Example</h4> |
| | 351 | <blockquote><pre> |
| | 352 | (v2, i2) := Vectors.sort({-1, 8, 3, 6, 2}); |
| | 353 | -> v2 = {-1, 2, 3, 6, 8} |
| | 354 | i2 = {1, 5, 3, 4, 2} |
| | 355 | </pre></blockquote> |
| | 356 | </HTML>")); |
| | 357 | /* shellsort algorithm; should be improved later */ |
| | 358 | protected |
| | 359 | Integer gap; |
| | 360 | Integer i; |
| | 361 | Integer j; |
| | 362 | Real wv; |
| | 363 | Integer wi; |
| | 364 | Integer nv = size(v,1); |
| | 365 | Boolean swap; |
| | 366 | algorithm |
| | 367 | gap := div(nv,2); |
| | 368 | |
| | 369 | while gap > 0 loop |
| | 370 | i := gap; |
| | 371 | while i < nv loop |
| | 372 | j := i-gap; |
| | 373 | if j>=0 then |
| | 374 | if ascending then |
| | 375 | swap := sorted_v[j+1] > sorted_v[j + gap + 1]; |
| | 376 | else |
| | 377 | swap := sorted_v[j+1] < sorted_v[j + gap + 1]; |
| | 378 | end if; |
| | 379 | else |
| | 380 | swap := false; |
| | 381 | end if; |
| | 382 | |
| | 383 | while swap loop |
| | 384 | wv := sorted_v[j+1]; |
| | 385 | wi := indices[j+1]; |
| | 386 | sorted_v[j+1] := sorted_v[j+gap+1]; |
| | 387 | sorted_v[j+gap+1] := wv; |
| | 388 | indices[j+1] := indices[j+gap+1]; |
| | 389 | indices[j+gap+1] := wi; |
| | 390 | j := j - gap; |
| | 391 | if j >= 0 then |
| | 392 | if ascending then |
| | 393 | swap := sorted_v[j+1] > sorted_v[j + gap + 1]; |
| | 394 | else |
| | 395 | swap := sorted_v[j+1] < sorted_v[j + gap + 1]; |
| | 396 | end if; |
| | 397 | else |
| | 398 | swap := false; |
| | 399 | end if; |
| | 400 | end while; |
| | 401 | i := i + 1; |
| | 402 | end while; |
| | 403 | gap := div(gap,2); |
| | 404 | end while; |
| | 405 | end sort; |
| | 406 | end Vectors; |
| 168 | | |
| 169 | | function norm "Returns the norm of a matrix" |
| 170 | | extends Modelica.Icons.Function; |
| 171 | | input Real A[:, :] "Input matrix"; |
| 172 | | input Real p(min=1) = 2 |
| 173 | | "Type of p-norm (only allowed: 1, 2 or Modelica.Constants.inf)"; |
| 174 | | output Real result=0.0 "p-norm of matrix A"; |
| 175 | | |
| 176 | | annotation (preferedView="info", Documentation(info="<HTML> |
| 177 | | <h3><font color=\"#008000\">Syntax</font></h3> |
| 178 | | <blockquote><pre> |
| 179 | | Matrices.<b>norm</b>(A); |
| 180 | | Matrices.<b>norm</b>(A, p=2); |
| 181 | | </pre></blockquote> |
| 182 | | <h3><font color=\"#008000\">Description</font></h3> |
| 183 | | <p> |
| 184 | | The function call \"<code>Matrices.norm(A)</code>\" returns the |
| 185 | | 2-norm of matrix A, i.e., the largest singular value of A.<br> |
| 186 | | The function call \"<code>Matrices.norm(A, p)</code>\" returns the |
| 187 | | p-norm of matrix A. The only allowed values for p are</p> |
| 188 | | <ul> |
| 189 | | <li> \"p=1\": the largest column sum of A</li> |
| 190 | | <li> \"p=2\": the largest singular value of A</li> |
| 191 | | <li> \"p=Modelica.Constants.inf\": the largest row sum of A</li> |
| 192 | | </ul> |
| 193 | | <p> |
| 194 | | Note, for any matrices A1, A2 the following inequality holds: |
| 195 | | </p> |
| 196 | | <blockquote><pre> |
| 197 | | Matrices.<b>norm</b>(A1+A2,p) ≤ Matrices.<b>norm</b>(A1,p) + Matrices.<b>norm</b>(A2,p) |
| 198 | | </pre></blockquote> |
| 199 | | <p> |
| 200 | | Note, for any matrix A and vector v the following inequality holds: |
| 201 | | </p> |
| 202 | | <blockquote><pre> |
| 203 | | Vectors.<b>norm</b>(A*v,p) ≤ Matrices.<b>norm</b>(A,p)*Vectors.<b>norm</b>(A,p) |
| 204 | | </pre></blockquote> |
| 205 | | </HTML>")); |
| 206 | | algorithm |
| 207 | | if p == 1 then |
| 208 | | // column sum norm |
| 209 | | for i in 1:size(A, 2) loop |
| 210 | | result := max(result, sum(abs(A[:, i]))); |
| 211 | | end for; |
| 212 | | elseif p == 2 then |
| 213 | | // largest singular value |
| 214 | | result := max(singularValues(A)); |
| 215 | | elseif p == Modelica.Constants.inf then |
| 216 | | // row sum norm |
| 217 | | for i in 1:size(A, 1) loop |
| 218 | | result := max(result, sum(abs(A[i, :]))); |
| 219 | | end for; |
| 220 | | else |
| 221 | | assert(false, "Optional argument \"p\" of function \"norm\" must be |
| 222 | | 1, 2 or Modelica.Constants.inf"); |
| 223 | | end if; |
| 224 | | end norm; |
| | 588 | function norm "Returns the norm of a matrix" |
| | 589 | extends Modelica.Icons.Function; |
| | 590 | input Real A[:, :] "Input matrix"; |
| | 591 | input Real p(min=1) = 2 |
| | 592 | "Type of p-norm (only allowed: 1, 2 or Modelica.Constants.inf)"; |
| | 593 | output Real result=0.0 "p-norm of matrix A"; |
| | 594 | |
| | 595 | annotation (preferedView="info", Documentation(info="<HTML> |
| | 596 | <h4>Syntax</h4> |
| | 597 | <blockquote><pre> |
| | 598 | Matrices.<b>norm</b>(A); |
| | 599 | Matrices.<b>norm</b>(A, p=2); |
| | 600 | </pre></blockquote> |
| | 601 | <h4>Description</h4> |
| | 602 | <p> |
| | 603 | The function call \"<code>Matrices.norm(A)</code>\" returns the |
| | 604 | 2-norm of matrix A, i.e., the largest singular value of A.<br> |
| | 605 | The function call \"<code>Matrices.norm(A, p)</code>\" returns the |
| | 606 | p-norm of matrix A. The only allowed values for p are</p> |
| | 607 | <ul> |
| | 608 | <li> \"p=1\": the largest column sum of A</li> |
| | 609 | <li> \"p=2\": the largest singular value of A</li> |
| | 610 | <li> \"p=Modelica.Constants.inf\": the largest row sum of A</li> |
| | 611 | </ul> |
| | 612 | <p> |
| | 613 | Note, for any matrices A1, A2 the following inequality holds: |
| | 614 | </p> |
| | 615 | <blockquote><pre> |
| | 616 | Matrices.<b>norm</b>(A1+A2,p) ≤ Matrices.<b>norm</b>(A1,p) + Matrices.<b>norm</b>(A2,p) |
| | 617 | </pre></blockquote> |
| | 618 | <p> |
| | 619 | Note, for any matrix A and vector v the following inequality holds: |
| | 620 | </p> |
| | 621 | <blockquote><pre> |
| | 622 | Vectors.<b>norm</b>(A*v,p) ≤ Matrices.<b>norm</b>(A,p)*Vectors.<b>norm</b>(A,p) |
| | 623 | </pre></blockquote> |
| | 624 | </HTML>")); |
| | 625 | algorithm |
| | 626 | if p == 1 then |
| | 627 | // column sum norm |
| | 628 | for i in 1:size(A, 2) loop |
| | 629 | result := max(result, sum(abs(A[:, i]))); |
| | 630 | end for; |
| | 631 | elseif p == 2 then |
| | 632 | // largest singular value |
| | 633 | result := max(singularValues(A)); |
| | 634 | elseif p == Modelica.Constants.inf then |
| | 635 | // row sum norm |
| | 636 | for i in 1:size(A, 1) loop |
| | 637 | result := max(result, sum(abs(A[i, :]))); |
| | 638 | end for; |
| | 639 | else |
| | 640 | assert(false, "Optional argument \"p\" of function \"norm\" must be |
| | 641 | 1, 2 or Modelica.Constants.inf"); |
| | 642 | end if; |
| | 643 | end norm; |
| | 644 | |
| | 645 | function sort |
| | 646 | "Sort rows or columns of matrix in ascending or descending order" |
| | 647 | extends Modelica.Icons.Function; |
| | 648 | input Real M[:,:] "Matrix to be sorted"; |
| | 649 | input Boolean sortRows = true |
| | 650 | "= true if rows are sorted, otherwise columns"; |
| | 651 | input Boolean ascending = true |
| | 652 | "= true if ascending order, otherwise descending order"; |
| | 653 | output Real sorted_M[size(M,1), size(M,2)] = M "Sorted matrix"; |
| | 654 | output Integer indices[if sortRows then size(M,1) else size(M,2)] |
| | 655 | "sorted_M = if sortRows then M[indices,:] else M[:,indices]"; |
| | 656 | |
| | 657 | annotation (preferedView="info",Documentation(info="<HTML> |
| | 658 | <h4>Syntax</h4> |
| | 659 | <blockquote><pre> |
| | 660 | sorted_M = Matrices.<b>sort</b>(M); |
| | 661 | (sorted_M, indices) = Matrices.<b>sort</b>(M, sortRows=true, ascending=true); |
| | 662 | </pre></blockquote> |
| | 663 | <h4>Description</h4> |
| | 664 | <p> |
| | 665 | Function <b>sort</b>(..) sorts the rows of a Real matrix M |
| | 666 | in ascending order and returns the result in sorted_M. |
| | 667 | If the optional argument \"sortRows\" is <b>false</b>, the columns |
| | 668 | of the matrix are sorted. |
| | 669 | If the optional argument \"ascending\" is <b>false</b>, the rows or |
| | 670 | columns are sorted in descending order. In the optional second |
| | 671 | output argument, the indices of the sorted rows or columns with respect |
| | 672 | to the original matrix are given, such that |
| | 673 | </p> |
| | 674 | <pre> |
| | 675 | sorted_M = <b>if</b> sortedRow <b>then</b> M[indices,:] <b>else</b> M[:,indices]; |
| | 676 | </pre> |
| | 677 | <h4>Example</h4> |
| | 678 | <blockquote><pre> |
| | 679 | (M2, i2) := Matrices.sort([2, 1, 0; |
| | 680 | 2, 0, -1]); |
| | 681 | -> M2 = [2, 0, -1; |
| | 682 | 2, 1, 0 ]; |
| | 683 | i2 = {2,1}; |
| | 684 | </pre></blockquote> |
| | 685 | </HTML>")); |
| | 686 | /* shellsort algorithm; should be improved later */ |
| | 687 | protected |
| | 688 | Integer gap; |
| | 689 | Integer i; |
| | 690 | Integer j; |
| | 691 | Real wM2[size(M,2)]; |
| | 692 | Integer wi; |
| | 693 | Integer nM1 = size(M,1); |
| | 694 | Boolean swap; |
| | 695 | Real sorted_MT[size(M,2), size(M,1)]; |
| | 696 | |
| | 697 | encapsulated function greater "Compare whether vector v1 > v2" |
| | 698 | import Modelica; |
| | 699 | extends Modelica.Icons.Function; |
| | 700 | import Modelica.Utilities.Types.Compare; |
| | 701 | input Real v1[:]; |
| | 702 | input Real v2[size(v1,1)]; |
| | 703 | output Boolean result; |
| | 704 | protected |
| | 705 | Integer n = size(v1,1); |
| | 706 | Integer i=1; |
| | 707 | algorithm |
| | 708 | result := false; |
| | 709 | while i <= n loop |
| | 710 | if v1[i] > v2[i] then |
| | 711 | result := true; |
| | 712 | |