OMCompiler/Compiler/NFFrontEnd/NFSimplifyModel.mo
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of OpenModelica. | ||
| 3 | * | ||
| 4 | * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), | ||
| 5 | * c/o Linköpings universitet, Department of Computer and Information Science, | ||
| 6 | * SE-58183 Linköping, Sweden. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR | ||
| 11 | * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. | ||
| 12 | * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES | ||
| 13 | * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL | ||
| 14 | * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. | ||
| 15 | * | ||
| 16 | * The OpenModelica software and the OSMC (Open Source Modelica Consortium) | ||
| 17 | * Public License (OSMC-PL) are obtained from OSMC, either from the above | ||
| 18 | * address, from the URLs: | ||
| 19 | * http://www.openmodelica.org or | ||
| 20 | * https://github.com/OpenModelica/ or | ||
| 21 | * http://www.ida.liu.se/projects/OpenModelica, | ||
| 22 | * and in the OpenModelica distribution. | ||
| 23 | * | ||
| 24 | * GNU AGPL version 3 is obtained from: | ||
| 25 | * https://www.gnu.org/licenses/licenses.html#GPL | ||
| 26 | * | ||
| 27 | * This program is distributed WITHOUT ANY WARRANTY; without | ||
| 28 | * even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 29 | * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH | ||
| 30 | * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. | ||
| 31 | * | ||
| 32 | * See the full OSMC Public License conditions for more details. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | encapsulated package NFSimplifyModel | ||
| 37 | |||
| 38 | import FlatModel = NFFlatModel; | ||
| 39 | import Equation = NFEquation; | ||
| 40 | import Statement = NFStatement; | ||
| 41 | import Expression = NFExpression; | ||
| 42 | import Type = NFType; | ||
| 43 | import ComponentRef = NFComponentRef; | ||
| 44 | import NFFlatten.FunctionTree; | ||
| 45 | import Class = NFClass; | ||
| 46 | import NFInstNode.InstNode; | ||
| 47 | import NFInstNode; | ||
| 48 | import NFFunction.Function; | ||
| 49 | import Sections = NFSections; | ||
| 50 | import Binding = NFBinding; | ||
| 51 | import Variable = NFVariable; | ||
| 52 | import Algorithm = NFAlgorithm; | ||
| 53 | import Dimension = NFDimension; | ||
| 54 | import Subscript = NFSubscript; | ||
| 55 | |||
| 56 | protected | ||
| 57 | import Ceval = NFCeval; | ||
| 58 | import DAE; | ||
| 59 | import ExecStat.execStat; | ||
| 60 | import MetaModelica.Dangerous.*; | ||
| 61 | import NFPrefixes.Variability; | ||
| 62 | import SimplifyExp = NFSimplifyExp; | ||
| 63 | |||
| 64 | public | ||
| 65 | function simplify | ||
| 66 | input output FlatModel flatModel; | ||
| 67 | algorithm | ||
| 68 |
4/4✓ Branch 0 taken 240727 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 240727 times.
✓ Branch 3 taken 1576 times.
|
242303 | flatModel.variables := list(simplifyVariable(v) for v in flatModel.variables); |
| 69 | flatModel.equations := simplifyEquations(flatModel.equations); | ||
| 70 | flatModel.initialEquations := simplifyEquations(flatModel.initialEquations); | ||
| 71 | flatModel.algorithms := simplifyAlgorithms(flatModel.algorithms); | ||
| 72 | flatModel.initialAlgorithms := simplifyAlgorithms(flatModel.initialAlgorithms); | ||
| 73 | |||
| 74 | 1574 | execStat(getInstanceName()); | |
| 75 | end simplify; | ||
| 76 | |||
| 77 | function simplifyVariable | ||
| 78 | input output Variable var; | ||
| 79 | algorithm | ||
| 80 |
8/8✓ Branch 1 taken 472029 times.
✓ Branch 2 taken 241172 times.
✓ Branch 3 taken 472029 times.
✓ Branch 4 taken 241172 times.
✓ Branch 6 taken 445 times.
✓ Branch 7 taken 241172 times.
✓ Branch 8 taken 445 times.
✓ Branch 9 taken 241172 times.
|
713646 | var.binding := simplifyBinding(var.binding); |
| 81 | var.typeAttributes := list(simplifyTypeAttribute(a) for a in var.typeAttributes); | ||
| 82 | var.children := list(simplifyVariable(v) for v in var.children); | ||
| 83 | end simplifyVariable; | ||
| 84 | |||
| 85 | function simplifyBinding | ||
| 86 | input output Binding binding; | ||
| 87 | protected | ||
| 88 | Expression exp, sexp; | ||
| 89 | algorithm | ||
| 90 |
2/2✓ Branch 1 taken 109997 times.
✓ Branch 2 taken 603204 times.
|
713201 | if Binding.isBound(binding) then |
| 91 | 603204 | exp := Binding.getTypedExp(binding); | |
| 92 | 603204 | sexp := SimplifyExp.simplify(exp); | |
| 93 | 603204 | sexp := removeEmptyFunctionArguments(sexp); | |
| 94 | |||
| 95 |
2/2✓ Branch 0 taken 478857 times.
✓ Branch 1 taken 124347 times.
|
603204 | if not referenceEq(exp, sexp) then |
| 96 | 124347 | binding := Binding.setTypedExp(sexp, binding); | |
| 97 | end if; | ||
| 98 | end if; | ||
| 99 | end simplifyBinding; | ||
| 100 | |||
| 101 | function simplifyTypeAttribute | ||
| 102 | input output tuple<String, Binding> attribute; | ||
| 103 | protected | ||
| 104 | String name; | ||
| 105 | Binding binding, sbinding; | ||
| 106 | algorithm | ||
| 107 | 472029 | (name, binding) := attribute; | |
| 108 | 472029 | sbinding := simplifyBinding(binding); | |
| 109 | |||
| 110 |
2/2✓ Branch 0 taken 386776 times.
✓ Branch 1 taken 85253 times.
|
472029 | if not referenceEq(binding, sbinding) then |
| 111 | 85253 | attribute := (name, sbinding); | |
| 112 | end if; | ||
| 113 | end simplifyTypeAttribute; | ||
| 114 | |||
| 115 | function simplifyDimension | ||
| 116 | input Dimension dim; | ||
| 117 | output Dimension outDim; | ||
| 118 | algorithm | ||
| 119 | outDim := match dim | ||
| 120 | local | ||
| 121 | Expression e; | ||
| 122 | |||
| 123 | case Dimension.EXP() | ||
| 124 | algorithm | ||
| 125 | 224 | e := SimplifyExp.simplify(dim.exp); | |
| 126 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | then |
| 127 | if referenceEq(e, dim.exp) then dim else Dimension.fromExp(e, dim.var); | ||
| 128 | |||
| 129 | else dim; | ||
| 130 | end match; | ||
| 131 | end simplifyDimension; | ||
| 132 | |||
| 133 | function simplifyEquations | ||
| 134 | input list<Equation> eql; | ||
| 135 | output list<Equation> outEql = {}; | ||
| 136 | algorithm | ||
| 137 |
2/2✓ Branch 0 taken 142841 times.
✓ Branch 1 taken 4477 times.
|
147318 | for eq in eql loop |
| 138 | 142841 | outEql := simplifyEquation(eq, outEql); | |
| 139 | end for; | ||
| 140 | |||
| 141 | 4477 | outEql := listReverseInPlace(outEql); | |
| 142 | end simplifyEquations; | ||
| 143 | |||
| 144 | function simplifyEquation | ||
| 145 | input Equation eq; | ||
| 146 | input output list<Equation> equations; | ||
| 147 | algorithm | ||
| 148 | equations := match eq | ||
| 149 | local | ||
| 150 | Expression e; | ||
| 151 | list<Equation> body; | ||
| 152 | Dimension dim; | ||
| 153 | |||
| 154 | 138341 | case Equation.EQUALITY() then simplifyEqualityEquation(eq, equations); | |
| 155 | |||
| 156 | case Equation.FOR(range = SOME(e)) | ||
| 157 | algorithm | ||
| 158 | 349 | dim := Type.nthDimension(Expression.typeOf(e), 1); | |
| 159 | |||
| 160 |
6/6✓ Branch 1 taken 345 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 289 times.
✓ Branch 7 taken 53 times.
✓ Branch 8 taken 3 times.
|
349 | if Dimension.isZero(dim) then |
| 161 | // Discard the for-loop if the iteration range is empty. | ||
| 162 | elseif Dimension.isOne(dim) and Flags.getConfigBool(Flags.NEW_BACKEND) then | ||
| 163 | // Unroll the loop if the iteration range is size 1. | ||
| 164 | // TODO: This breaks some of the -d=-nfScalarize tests because they rely on the broken way | ||
| 165 | // the old backend handles for-loops, so only enable it for the new backend for now. | ||
| 166 | 53 | e := Expression.applySubscript(Subscript.INDEX(Expression.INTEGER(1)), e); | |
| 167 | 53 | e := SimplifyExp.simplify(e); | |
| 168 | 53 | body := Equation.replaceIteratorList(eq.body, eq.iterator, e); | |
| 169 | 53 | body := simplifyEquations(body); | |
| 170 | 53 | equations := List.append_reverse(body, equations); | |
| 171 | else | ||
| 172 | // Otherwise just simplify the range and body of the loop. | ||
| 173 | 584 | eq.range := Util.applyOption(eq.range, function SimplifyExp.simplify(includeScope = false)); | |
| 174 | 292 | eq.body := simplifyEquations(eq.body); | |
| 175 | equations := eq :: equations; | ||
| 176 | end if; | ||
| 177 | then | ||
| 178 | equations; | ||
| 179 | |||
| 180 | case Equation.IF() | ||
| 181 | 1429 | then simplifyIfEqBranches(eq.branches, eq.scope, eq.source, equations); | |
| 182 | |||
| 183 | case Equation.WHEN() | ||
| 184 | algorithm | ||
| 185 |
4/4✓ Branch 0 taken 361 times.
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 361 times.
✓ Branch 3 taken 320 times.
|
681 | eq.branches := list( |
| 186 | match b | ||
| 187 | case Equation.Branch.BRANCH() | ||
| 188 | algorithm | ||
| 189 | 361 | b.condition := SimplifyExp.simplify(b.condition); | |
| 190 | 361 | b.body := simplifyEquations(b.body); | |
| 191 | then | ||
| 192 | b; | ||
| 193 | end match | ||
| 194 | for b in eq.branches); | ||
| 195 | then | ||
| 196 | eq :: equations; | ||
| 197 | |||
| 198 | case Equation.ASSERT() | ||
| 199 | algorithm | ||
| 200 | 4539 | eq.condition := SimplifyExp.simplify(eq.condition); | |
| 201 |
2/2✓ Branch 1 taken 2011 times.
✓ Branch 2 taken 2528 times.
|
4539 | then |
| 202 | if Expression.isTrue(eq.condition) then equations else eq :: equations; | ||
| 203 | |||
| 204 | case Equation.REINIT() | ||
| 205 | algorithm | ||
| 206 | 28 | eq.reinitExp := SimplifyExp.simplify(eq.reinitExp); | |
| 207 | then | ||
| 208 | eq :: equations; | ||
| 209 | |||
| 210 | case Equation.NORETCALL() | ||
| 211 | algorithm | ||
| 212 | 66 | e := SimplifyExp.simplify(eq.exp); | |
| 213 | |||
| 214 |
1/2✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
|
66 | if Expression.isCall(e) then |
| 215 | 66 | eq.exp := removeEmptyFunctionArguments(e); | |
| 216 | equations := eq :: equations; | ||
| 217 | end if; | ||
| 218 | then | ||
| 219 | equations; | ||
| 220 | |||
| 221 | else eq :: equations; | ||
| 222 | end match; | ||
| 223 | end simplifyEquation; | ||
| 224 | |||
| 225 | function simplifyEqualityEquation | ||
| 226 | input Equation eq; | ||
| 227 | input output list<Equation> equations; | ||
| 228 | protected | ||
| 229 | Expression lhs, rhs; | ||
| 230 | Type ty; | ||
| 231 | DAE.ElementSource src; | ||
| 232 | NFInstNode.ScopeRef scope; | ||
| 233 | Equation.ScalarizeMode scalarize_mode; | ||
| 234 | algorithm | ||
| 235 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 138341 times.
|
138341 | Equation.EQUALITY(lhs = lhs, rhs = rhs, ty = ty, scope = scope, source = src, scalarizeMode = scalarize_mode) := eq; |
| 236 | 138341 | ty := Type.mapDims(ty, simplifyDimension); | |
| 237 | |||
| 238 |
2/2✓ Branch 1 taken 2346 times.
✓ Branch 2 taken 135995 times.
|
138341 | if Type.isEmptyArray(ty) then |
| 239 | 2346 | return; | |
| 240 | end if; | ||
| 241 | |||
| 242 | 135995 | lhs := SimplifyExp.simplify(lhs); | |
| 243 | 135995 | lhs := removeEmptyTupleElements(lhs); | |
| 244 | 135995 | rhs := SimplifyExp.simplify(rhs); | |
| 245 | 135995 | rhs := removeEmptyFunctionArguments(rhs); | |
| 246 | |||
| 247 | equations := match (lhs, rhs) | ||
| 248 | case (Expression.TUPLE(), Expression.TUPLE()) | ||
| 249 | 4 | then simplifyTupleElement(lhs.elements, rhs.elements, ty, src, | |
| 250 | function Equation.makeEquality(scope = InstNode.fromCell(scope), scalarizeMode = scalarize_mode), equations); | ||
| 251 | |||
| 252 | 135991 | else Equation.EQUALITY(lhs, rhs, ty, scope, src, scalarize_mode) :: equations; | |
| 253 | end match; | ||
| 254 | end simplifyEqualityEquation; | ||
| 255 | |||
| 256 | function simplifyAlgorithms | ||
| 257 | input list<Algorithm> algs; | ||
| 258 | output list<Algorithm> outAlgs = {}; | ||
| 259 | algorithm | ||
| 260 |
2/2✓ Branch 0 taken 197 times.
✓ Branch 1 taken 3148 times.
|
3345 | for alg in algs loop |
| 261 | 197 | alg := simplifyAlgorithm(alg); | |
| 262 | |||
| 263 |
2/2✓ Branch 0 taken 196 times.
✓ Branch 1 taken 1 time.
|
197 | if not listEmpty(alg.statements) then |
| 264 | outAlgs := alg :: outAlgs; | ||
| 265 | end if; | ||
| 266 | end for; | ||
| 267 | |||
| 268 | 3148 | outAlgs := listReverseInPlace(outAlgs); | |
| 269 | end simplifyAlgorithms; | ||
| 270 | |||
| 271 | function simplifyAlgorithm | ||
| 272 | input output Algorithm alg; | ||
| 273 | algorithm | ||
| 274 | 1377 | alg.statements := simplifyStatements(alg.statements); | |
| 275 | end simplifyAlgorithm; | ||
| 276 | |||
| 277 | function simplifyStatements | ||
| 278 | input list<Statement> stmts; | ||
| 279 | output list<Statement> outStmts = {}; | ||
| 280 | algorithm | ||
| 281 |
2/2✓ Branch 0 taken 110866 times.
✓ Branch 1 taken 23153 times.
|
134019 | for s in stmts loop |
| 282 | 110866 | outStmts := simplifyStatement(s, outStmts); | |
| 283 | end for; | ||
| 284 | |||
| 285 | 23153 | outStmts := listReverseInPlace(outStmts); | |
| 286 | end simplifyStatements; | ||
| 287 | |||
| 288 | function simplifyStatement | ||
| 289 | input Statement stmt; | ||
| 290 | input output list<Statement> statements; | ||
| 291 | algorithm | ||
| 292 | statements := match stmt | ||
| 293 | local | ||
| 294 | Expression e; | ||
| 295 | Dimension dim; | ||
| 296 | list<Statement> body; | ||
| 297 | |||
| 298 | 101577 | case Statement.ASSIGNMENT() then simplifyAssignment(stmt, statements); | |
| 299 | |||
| 300 | // if there are no body equations, remove the for-loop | ||
| 301 | case Statement.FOR(body = {}) then statements; | ||
| 302 | |||
| 303 | case Statement.FOR(range = SOME(e)) | ||
| 304 | algorithm | ||
| 305 | 512 | dim := Type.nthDimension(Expression.typeOf(e), 1); | |
| 306 | |||
| 307 | //if Dimension.isOne(dim) then | ||
| 308 | // // Unroll the loop if the iteration range consists of only one value. | ||
| 309 | // e := Expression.applySubscript(Subscript.INDEX(Expression.INTEGER(1)), e); | ||
| 310 | // body := Statement.replaceIteratorList(stmt.body, stmt.iterator, e); | ||
| 311 | // body := simplifyStatements(body); | ||
| 312 | // statements := listAppend(listReverse(body), statements); | ||
| 313 | //elseif not Dimension.isZero(dim) then | ||
| 314 |
2/2✓ Branch 1 taken 504 times.
✓ Branch 2 taken 8 times.
|
512 | if not Dimension.isZero(dim) then |
| 315 | // Otherwise just simplify if the iteration range is not empty. | ||
| 316 | 1008 | stmt.range := SOME(SimplifyExp.simplify(e)); | |
| 317 | 504 | stmt.body := simplifyStatements(stmt.body); | |
| 318 | statements := stmt :: statements; | ||
| 319 | end if; | ||
| 320 | then | ||
| 321 | statements; | ||
| 322 | |||
| 323 | case Statement.IF() | ||
| 324 | 4914 | then simplifyIfStmtBranches(stmt.branches, stmt.source, Statement.makeIf, simplifyStatements, statements); | |
| 325 | |||
| 326 | case Statement.WHEN() | ||
| 327 | algorithm | ||
| 328 | 109 | stmt.branches := simplifyWhenBranches(stmt.branches); | |
| 329 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1 time.
|
109 | then |
| 330 | if listEmpty(stmt.branches) then statements else stmt :: statements; | ||
| 331 | |||
| 332 | case Statement.ASSERT() | ||
| 333 | algorithm | ||
| 334 | 3407 | stmt.condition := SimplifyExp.simplify(stmt.condition); | |
| 335 | 3407 | stmt.message := SimplifyExp.simplify(stmt.message); | |
| 336 | 3407 | stmt.level := SimplifyExp.simplify(stmt.level); | |
| 337 | then | ||
| 338 | stmt :: statements; | ||
| 339 | |||
| 340 | case Statement.TERMINATE() | ||
| 341 | algorithm | ||
| 342 | 1 | stmt.message := SimplifyExp.simplify(stmt.message); | |
| 343 | then | ||
| 344 | stmt :: statements; | ||
| 345 | |||
| 346 | case Statement.WHILE() | ||
| 347 | algorithm | ||
| 348 | 206 | stmt.condition := SimplifyExp.simplify(stmt.condition); | |
| 349 | 206 | stmt.body := simplifyStatements(stmt.body); | |
| 350 | then | ||
| 351 | stmt :: statements; | ||
| 352 | |||
| 353 | case Statement.NORETCALL() | ||
| 354 | algorithm | ||
| 355 | 117 | e := SimplifyExp.simplify(stmt.exp); | |
| 356 | |||
| 357 |
1/2✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
|
117 | if Expression.isCall(e) then |
| 358 | 117 | stmt.exp := removeEmptyFunctionArguments(e); | |
| 359 | statements := stmt :: statements; | ||
| 360 | end if; | ||
| 361 | then | ||
| 362 | statements; | ||
| 363 | |||
| 364 | else stmt :: statements; | ||
| 365 | end match; | ||
| 366 | end simplifyStatement; | ||
| 367 | |||
| 368 | function simplifyWhenBranches | ||
| 369 | input output list<tuple<Expression, list<Statement>>> branches; | ||
| 370 | algorithm | ||
| 371 | branches := match branches | ||
| 372 | local | ||
| 373 | Expression condition; | ||
| 374 | list<Statement> body; | ||
| 375 | list<tuple<Expression, list<Statement>>> tail; | ||
| 376 | case (condition, body) :: tail algorithm | ||
| 377 | 145 | condition := SimplifyExp.simplify(condition); | |
| 378 | 145 | body := simplifyStatements(body); | |
| 379 | // if the condition is a constant boolean -> skip this unreachable branch | ||
| 380 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 144 times.
|
145 | then if Expression.isBoolean(condition) then simplifyWhenBranches(tail) else (condition, body) :: simplifyWhenBranches(tail); |
| 381 | else branches; | ||
| 382 | end match; | ||
| 383 | end simplifyWhenBranches; | ||
| 384 | |||
| 385 | function simplifyAssignment | ||
| 386 | input Statement stmt; | ||
| 387 | input output list<Statement> statements; | ||
| 388 | protected | ||
| 389 | Expression lhs, rhs; | ||
| 390 | Type ty; | ||
| 391 | DAE.ElementSource src; | ||
| 392 | algorithm | ||
| 393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101577 times.
|
101577 | Statement.ASSIGNMENT(lhs = lhs, rhs = rhs, ty = ty, source = src) := stmt; |
| 394 | 101577 | ty := Type.mapDims(ty, simplifyDimension); | |
| 395 | |||
| 396 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 101569 times.
|
101577 | if Type.isEmptyArray(ty) then |
| 397 | 8 | return; | |
| 398 | end if; | ||
| 399 | |||
| 400 | 101569 | lhs := SimplifyExp.simplify(lhs); | |
| 401 | 101569 | lhs := removeEmptyTupleElements(lhs); | |
| 402 | 101569 | rhs := SimplifyExp.simplify(rhs); | |
| 403 | 101569 | rhs := removeEmptyFunctionArguments(rhs); | |
| 404 | |||
| 405 | statements := match (lhs, rhs) | ||
| 406 | case (Expression.TUPLE(), Expression.TUPLE()) | ||
| 407 | 1 | then simplifyTupleElement(lhs.elements, rhs.elements, ty, src, Statement.makeAssignment, statements); | |
| 408 | |||
| 409 | 101568 | else Statement.ASSIGNMENT(lhs, rhs, ty, src) :: statements; | |
| 410 | end match; | ||
| 411 | end simplifyAssignment; | ||
| 412 | |||
| 413 | function simplifyTupleElement<ElementT> | ||
| 414 | "Helper function to simplifyEqualityEquation/simplifyAssignment. | ||
| 415 | Handles Expression.TUPLE() := Expression.TUPLE() assignments by splitting | ||
| 416 | them into a separate assignment statement for each pair of tuple elements." | ||
| 417 | input list<Expression> lhsTuple; | ||
| 418 | input list<Expression> rhsTuple; | ||
| 419 | input Type ty; | ||
| 420 | input DAE.ElementSource src; | ||
| 421 | input MakeElement makeFn; | ||
| 422 | input output list<ElementT> statements; | ||
| 423 | |||
| 424 | partial function MakeElement | ||
| 425 | input Expression lhs; | ||
| 426 | input Expression rhs; | ||
| 427 | input Type ty; | ||
| 428 | input DAE.ElementSource src; | ||
| 429 | output ElementT element; | ||
| 430 | end MakeElement; | ||
| 431 | protected | ||
| 432 | Expression rhs; | ||
| 433 | list<Expression> rest_rhs = rhsTuple; | ||
| 434 | Type ety; | ||
| 435 | list<Type> rest_ty; | ||
| 436 | algorithm | ||
| 437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | Type.TUPLE(types = rest_ty) := ty; |
| 438 | |||
| 439 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
|
16 | for lhs in lhsTuple loop |
| 440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | rhs :: rest_rhs := rest_rhs; |
| 441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | ety :: rest_ty := rest_ty; |
| 442 | |||
| 443 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 time.
|
11 | if not Expression.isWildCref(lhs) then |
| 444 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 time.
|
10 | statements := makeFn(lhs, rhs, ety, src) :: statements; |
| 445 | end if; | ||
| 446 | end for; | ||
| 447 | end simplifyTupleElement; | ||
| 448 | |||
| 449 | function removeEmptyTupleElements | ||
| 450 | "Replaces tuple elements that has one or more zero dimension with _." | ||
| 451 | input output Expression exp; | ||
| 452 | algorithm | ||
| 453 | () := match exp | ||
| 454 | local | ||
| 455 | list<Type> tyl; | ||
| 456 | |||
| 457 | case Expression.TUPLE(ty = Type.TUPLE(types = tyl)) | ||
| 458 | algorithm | ||
| 459 |
9/10✓ Branch 0 taken 1854 times.
✓ Branch 1 taken 827 times.
✓ Branch 2 taken 1854 times.
✓ Branch 3 taken 827 times.
✓ Branch 4 taken 1854 times.
✓ Branch 5 taken 827 times.
✓ Branch 7 taken 25 times.
✓ Branch 8 taken 1829 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 827 times.
|
3508 | exp.elements := list( |
| 460 | if Type.isEmptyArray(t) then Expression.CREF(t, ComponentRef.WILD()) else e | ||
| 461 | threaded for e in exp.elements, t in tyl); | ||
| 462 | then | ||
| 463 | (); | ||
| 464 | |||
| 465 | else (); | ||
| 466 | end match; | ||
| 467 | end removeEmptyTupleElements; | ||
| 468 | |||
| 469 | function removeEmptyFunctionArguments | ||
| 470 | input Expression exp; | ||
| 471 | input Boolean isArg = false; | ||
| 472 | output Expression outExp; | ||
| 473 | protected | ||
| 474 | Boolean is_arg; | ||
| 475 | algorithm | ||
| 476 |
2/2✓ Branch 0 taken 235835 times.
✓ Branch 1 taken 2694074 times.
|
2929909 | if isArg then |
| 477 | () := match exp | ||
| 478 | case Expression.CREF() guard Type.isEmptyArray(exp.ty) | ||
| 479 | algorithm | ||
| 480 | 161 | outExp := Expression.fillType(exp.ty, Expression.INTEGER(0)); | |
| 481 | 161 | return; | |
| 482 | then | ||
| 483 | (); | ||
| 484 | |||
| 485 | else (); | ||
| 486 | end match; | ||
| 487 | end if; | ||
| 488 | |||
| 489 |
4/4✓ Branch 0 taken 2694074 times.
✓ Branch 1 taken 235674 times.
✓ Branch 3 taken 49804 times.
✓ Branch 4 taken 2644270 times.
|
2929748 | is_arg := isArg or Expression.isCall(exp); |
| 490 | 2929748 | outExp := Expression.mapShallow(exp, function removeEmptyFunctionArguments(isArg = is_arg)); | |
| 491 | end removeEmptyFunctionArguments; | ||
| 492 | |||
| 493 | function simplifyIfEqBranches | ||
| 494 | input list<Equation.Branch> branches; | ||
| 495 | input NFInstNode.ScopeRef scope; | ||
| 496 | input DAE.ElementSource src; | ||
| 497 | input output list<Equation> elements; | ||
| 498 | protected | ||
| 499 | Expression cond; | ||
| 500 | list<Equation> body; | ||
| 501 | Variability var; | ||
| 502 | list<Equation.Branch> accum = {}; | ||
| 503 | algorithm | ||
| 504 |
2/2✓ Branch 0 taken 2065 times.
✓ Branch 1 taken 186 times.
|
2251 | for branch in branches loop |
| 505 | accum := match branch | ||
| 506 | case Equation.Branch.BRANCH(cond, var, body) | ||
| 507 | algorithm | ||
| 508 | 2060 | cond := SimplifyExp.simplify(cond); | |
| 509 | |||
| 510 | // A branch with condition true will always be selected when encountered. | ||
| 511 |
2/2✓ Branch 1 taken 1241 times.
✓ Branch 2 taken 819 times.
|
2060 | if Expression.isTrue(cond) then |
| 512 |
2/2✓ Branch 0 taken 1077 times.
✓ Branch 1 taken 164 times.
|
1241 | if listEmpty(accum) then |
| 513 | // If it's the first branch, remove the if and keep only the branch body. | ||
| 514 |
2/2✓ Branch 0 taken 2236 times.
✓ Branch 1 taken 1077 times.
|
3313 | for eq in body loop |
| 515 | 2236 | elements := simplifyEquation(eq, elements); | |
| 516 | end for; | ||
| 517 | 1077 | return; | |
| 518 | else | ||
| 519 | // Otherwise just discard the rest of the branches. | ||
| 520 | 164 | accum := Equation.makeBranch(cond, simplifyEquations(body)) :: accum; | |
| 521 | 164 | accum := List.trim(accum, Equation.Branch.isEmpty); | |
| 522 | 164 | elements := Equation.makeIf(listReverseInPlace(accum), InstNode.fromCell(scope), src) :: elements; | |
| 523 | 164 | return; | |
| 524 | end if; | ||
| 525 | elseif not Expression.isFalse(cond) then | ||
| 526 | // Keep branches that are neither literal true or false. | ||
| 527 | 459 | accum := Equation.makeBranch(cond, simplifyEquations(body)) :: accum; | |
| 528 | end if; | ||
| 529 | then | ||
| 530 | accum; | ||
| 531 | |||
| 532 | case Equation.INVALID_BRANCH(branch = | ||
| 533 | Equation.Branch.BRANCH(condition = cond, conditionVar = var)) | ||
| 534 | algorithm | ||
| 535 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
|
5 | if var <= Variability.STRUCTURAL_PARAMETER then |
| 536 | 4 | cond := Ceval.evalExp(cond); | |
| 537 | end if; | ||
| 538 | |||
| 539 | // An invalid branch that can't be removed will trigger the errors | ||
| 540 | // stored in it. | ||
| 541 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
|
5 | if not Expression.isFalse(cond) then |
| 542 | 2 | Equation.Branch.triggerErrors(branch); | |
| 543 | end if; | ||
| 544 | then | ||
| 545 | accum; | ||
| 546 | |||
| 547 | else branch :: accum; | ||
| 548 | end match; | ||
| 549 | end for; | ||
| 550 | |||
| 551 | 186 | accum := List.trim(accum, Equation.Branch.isEmpty); | |
| 552 | |||
| 553 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 19 times.
|
186 | if not listEmpty(accum) then |
| 554 | 19 | elements := Equation.makeIf(listReverseInPlace(accum), InstNode.fromCell(scope), src) :: elements; | |
| 555 | end if; | ||
| 556 | end simplifyIfEqBranches; | ||
| 557 | |||
| 558 | function simplifyIfStmtBranches<ElemT> | ||
| 559 | input list<tuple<Expression, list<ElemT>>> branches; | ||
| 560 | input DAE.ElementSource src; | ||
| 561 | input MakeFunc makeFunc; | ||
| 562 | input SimplifyFunc simplifyFunc; | ||
| 563 | input output list<ElemT> elements; | ||
| 564 | |||
| 565 | partial function MakeFunc | ||
| 566 | input list<tuple<Expression, list<ElemT>>> branches; | ||
| 567 | input DAE.ElementSource src; | ||
| 568 | output ElemT element; | ||
| 569 | end MakeFunc; | ||
| 570 | |||
| 571 | partial function SimplifyFunc | ||
| 572 | input output list<ElemT> elements; | ||
| 573 | end SimplifyFunc; | ||
| 574 | protected | ||
| 575 | Expression cond; | ||
| 576 | list<ElemT> body; | ||
| 577 | list<tuple<Expression, list<ElemT>>> accum = {}; | ||
| 578 | algorithm | ||
| 579 |
2/2✓ Branch 0 taken 10700 times.
✓ Branch 1 taken 1200 times.
|
11900 | for branch in branches loop |
| 580 | 10700 | (cond, body) := branch; | |
| 581 | 10700 | cond := SimplifyExp.simplify(cond); | |
| 582 | |||
| 583 | // A branch with condition true will always be selected when encountered. | ||
| 584 |
2/2✓ Branch 1 taken 3714 times.
✓ Branch 2 taken 6986 times.
|
10700 | if Expression.isTrue(cond) then |
| 585 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 3691 times.
|
3714 | if listEmpty(accum) then |
| 586 | // If it's the first branch, remove the if and keep only the branch body. | ||
| 587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | elements := listAppend(listReverse(simplifyFunc(body)), elements); |
| 588 | 23 | return; | |
| 589 | else | ||
| 590 | // Otherwise just discard the rest of the branches. | ||
| 591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3691 times.
|
3691 | accum := (cond, simplifyFunc(body)) :: accum; |
| 592 | 3691 | break; | |
| 593 | end if; | ||
| 594 | elseif not Expression.isFalse(cond) then | ||
| 595 | // Keep branches that are neither literal true or false. | ||
| 596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6962 times.
|
6962 | accum := (cond, simplifyFunc(body)) :: accum; |
| 597 | end if; | ||
| 598 | end for; | ||
| 599 | |||
| 600 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4883 times.
|
4891 | if not listEmpty(accum) then |
| 601 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4883 times.
|
4883 | elements := makeFunc(listReverseInPlace(accum), src) :: elements; |
| 602 | end if; | ||
| 603 | end simplifyIfStmtBranches; | ||
| 604 | |||
| 605 | function simplifyFunction | ||
| 606 | input Function func; | ||
| 607 | protected | ||
| 608 | Class cls; | ||
| 609 | Algorithm fn_body; | ||
| 610 | Sections sections; | ||
| 611 | algorithm | ||
| 612 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12185 times.
|
12185 | if not Function.isSimplified(func) then |
| 613 | 12185 | Function.markSimplified(func); | |
| 614 | 12185 | Function.mapExp(func, function SimplifyExp.simplify(includeScope = false), mapBody = false); | |
| 615 | |||
| 616 | 12185 | cls := InstNode.getClass(InstNode.fromHandle(func.node)); | |
| 617 | () := match cls | ||
| 618 | case Class.INSTANCED_CLASS(sections = sections) | ||
| 619 | algorithm | ||
| 620 | () := match sections | ||
| 621 | case Sections.SECTIONS(algorithms = {fn_body}) | ||
| 622 | algorithm | ||
| 623 | 10245 | fn_body.statements := simplifyStatements(fn_body.statements); | |
| 624 | 10245 | sections.algorithms := {fn_body}; | |
| 625 | 10245 | cls.sections := sections; | |
| 626 | 10245 | InstNode.updateClass(cls, InstNode.fromHandle(func.node)); | |
| 627 | then | ||
| 628 | (); | ||
| 629 | |||
| 630 | else (); | ||
| 631 | end match; | ||
| 632 | then | ||
| 633 | (); | ||
| 634 | |||
| 635 | else (); | ||
| 636 | end match; | ||
| 637 | |||
| 638 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 12185 times.
|
12985 | for fn_der in func.derivatives loop |
| 639 |
2/2✓ Branch 2 taken 800 times.
✓ Branch 3 taken 800 times.
|
1600 | for der_fn in Function.getCachedFuncs(InstNode.borrow(fn_der.derivativeFn)) loop |
| 640 | 800 | simplifyFunction(der_fn); | |
| 641 | end for; | ||
| 642 | end for; | ||
| 643 | end if; | ||
| 644 | end simplifyFunction; | ||
| 645 | |||
| 646 | function combineBinaries | ||
| 647 | "author: kabdelhak 09-2020 | ||
| 648 | Combines binaries for better handling in the backend. | ||
| 649 | NOTE: does not do any other simplification | ||
| 650 | e.g. BINARY(BINARY(2, /, y^2), *, BINARY(3, *, x)) | ||
| 651 | --> MULTARY({2, 3, x}, {y^2}, *)" | ||
| 652 | input output FlatModel flatModel; | ||
| 653 | algorithm | ||
| 654 |
20/20✓ Branch 0 taken 6432 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 6432 times.
✓ Branch 3 taken 203 times.
✓ Branch 5 taken 4064 times.
✓ Branch 6 taken 203 times.
✓ Branch 7 taken 4064 times.
✓ Branch 8 taken 203 times.
✓ Branch 10 taken 84 times.
✓ Branch 11 taken 203 times.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 203 times.
✓ Branch 15 taken 11 times.
✓ Branch 16 taken 203 times.
✓ Branch 17 taken 11 times.
✓ Branch 18 taken 203 times.
✓ Branch 20 taken 6 times.
✓ Branch 21 taken 203 times.
✓ Branch 22 taken 6 times.
✓ Branch 23 taken 203 times.
|
10800 | flatModel.variables := list(Variable.mapExp(var, SimplifyExp.combineBinaries) for var in flatModel.variables); |
| 655 | flatModel.equations := list(Equation.mapExp(eqn, SimplifyExp.combineBinaries) for eqn in flatModel.equations); | ||
| 656 | flatModel.initialEquations := list(Equation.mapExp(eqn, SimplifyExp.combineBinaries) for eqn in flatModel.initialEquations); | ||
| 657 | flatModel.algorithms := list(Algorithm.mapExp(alg, SimplifyExp.combineBinaries) for alg in flatModel.algorithms); | ||
| 658 | flatModel.initialAlgorithms := list(Algorithm.mapExp(alg, SimplifyExp.combineBinaries) for alg in flatModel.initialAlgorithms); | ||
| 659 | end combineBinaries; | ||
| 660 | |||
| 661 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 662 | end NFSimplifyModel; | ||
| 663 |