Skip to content

Commit

Permalink
[NF] overconstrained connection graph (OCG)
Browse files Browse the repository at this point in the history
- creating and breaking of the OCG is working
- replacement of broken connect equation with the equalityConstraint call is missing
- update common

Belonging to [master]:
  - OpenModelica/OMCompiler#2578
  • Loading branch information
adrpo authored and OpenModelica-Hudson committed Jul 24, 2018
1 parent c5bc6e5 commit 15177bd
Show file tree
Hide file tree
Showing 16 changed files with 2,350 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Compiler/FrontEnd/SCodeUtil.mo
Expand Up @@ -90,6 +90,8 @@ algorithm
System.setHasInnerOuterDefinitions(false);
// set the external flag that signals the presence of expandable connectors in the model
System.setHasExpandableConnectors(false);
// set the external flag that signals the presence of overconstrained connectors in the model
System.setHasOverconstrainedConnectors(false);
// set the external flag that signals the presence of expandable connectors in the model
System.setHasStreamConnectors(false);

Expand Down
3 changes: 3 additions & 0 deletions Compiler/NFFrontEnd/NFClass.mo
Expand Up @@ -46,6 +46,7 @@ import Expression = NFExpression;
protected
import NFBinding.Binding;
import ComplexType = NFComplexType;
import System;

public

Expand Down Expand Up @@ -499,6 +500,8 @@ uniontype Class
algorithm
try
lookupElement("equalityConstraint", cls);
// set the external flag that signals the presence of expandable connectors in the model
System.setHasOverconstrainedConnectors(true);
isOverdetermined := true;
else
isOverdetermined := false;
Expand Down
27 changes: 27 additions & 0 deletions Compiler/NFFrontEnd/NFComponentRef.mo
Expand Up @@ -551,6 +551,26 @@ public
end match;
end isEqual;

function isPrefix
input ComponentRef cref1;
input ComponentRef cref2;
output Boolean isPrefix;
algorithm
if referenceEq(cref1, cref2) then
isPrefix := true;
return;
end if;

isPrefix := match (cref1, cref2)
case (CREF(), CREF())
then
if InstNode.name(cref1.node) == InstNode.name(cref2.node) then
isEqual(cref1.restCref, cref2.restCref)
else isEqual(cref1, cref2.restCref);
else false;
end match;
end isPrefix;

function toDAE
input ComponentRef cref;
output DAE.ComponentRef dcref;
Expand Down Expand Up @@ -613,6 +633,13 @@ public
end match;
end toString;

function listToString
input list<ComponentRef> crs;
output String str;
algorithm
str := "{" + stringDelimitList(List.map(crs, toString), ",") + "}";
end listToString;

function hash
input ComponentRef cref;
input Integer mod;
Expand Down
38 changes: 36 additions & 2 deletions Compiler/NFFrontEnd/NFConnectionSets.mo
Expand Up @@ -31,13 +31,16 @@

encapsulated package NFConnectionSets
import DisjointSets;
import ComponentRef = NFComponentRef;
import Connector = NFConnector;
import Connection = NFConnection;
import Connections = NFConnections;
import BrokenEdges = NFConnections.BrokenEdges;

protected
import Flags;
import List;
import NFOCConnectionGraph;

public
package ConnectionSets
Expand Down Expand Up @@ -73,7 +76,7 @@ package ConnectionSets
end if;

// Add the connections.
sets := List.fold(connections.connections, addConnection, sets);
sets := List.fold1(connections.connections, addConnection, connections.broken, sets);
end fromConnections;

function addScalarConnector
Expand All @@ -95,6 +98,7 @@ package ConnectionSets
"Adds a connection to the sets, which means merging the two sets that the
connectors belong to, unless they already belong to the same set."
input Connection connection;
input BrokenEdges broken;
input output ConnectionSets.Sets sets;
protected
Connector lhs, rhs, c2;
Expand All @@ -111,11 +115,41 @@ package ConnectionSets
// when collecting the connections, but if the connectors themselves
// contain connectors that have been deleted we need to remove them here.
if not (Connector.isDeleted(c1) or Connector.isDeleted(c2)) then
sets := merge(c1, c2, sets);
if listEmpty(broken) then
sets := merge(c1, c2, sets);
elseif isBroken(c1, c2, broken) then
// do nothing
// print("Ignore broken: connect(" + Connector.toString(c1) + ", " + Connector.toString(c2) + ")\n");
else
sets := merge(c1, c2, sets);
end if;
end if;
end for;
end addConnection;

function isBroken
input Connector c1, c2;
input BrokenEdges broken;
output Boolean b = false;
protected
ComponentRef lhs, rhs, cr1, cr2;
algorithm
cr1 := Connector.name(c1);
cr2 := Connector.name(c2);
// print("Check: connect(" + ComponentRef.toString(cr1) + ", " + ComponentRef.toString(cr2) + ")\n");

for c in broken loop
((lhs, rhs, _)) := c;

if ComponentRef.isPrefix(lhs, cr1) and ComponentRef.isPrefix(rhs, cr2) or
ComponentRef.isPrefix(lhs, cr2) and ComponentRef.isPrefix(rhs, cr1)
then
b := true;
break;
end if;
end for;
end isBroken;

annotation(__OpenModelica_Interface="frontend");
end ConnectionSets;

Expand Down
17 changes: 14 additions & 3 deletions Compiler/NFFrontEnd/NFConnections.mo
Expand Up @@ -33,10 +33,10 @@ encapsulated uniontype NFConnections
import Connection = NFConnection;
import Connector = NFConnector;
import FlatModel = NFFlatModel;
import ComponentRef = NFComponentRef;
import Equation = NFEquation;

protected
import Equation = NFEquation;
import ComponentRef = NFComponentRef;
import Connections = NFConnections;
import NFComponent.Component;
import NFInstNode.InstNode;
Expand All @@ -47,13 +47,17 @@ protected
import ExpandExp = NFExpandExp;

public
type BrokenEdge = tuple<ComponentRef, ComponentRef, list<Equation>>;
type BrokenEdges = list<BrokenEdge>;

record CONNECTIONS
list<Connection> connections;
list<Connector> flows;
BrokenEdges broken;
end CONNECTIONS;

function new
output Connections conns = CONNECTIONS({}, {});
output Connections conns = CONNECTIONS({}, {}, {});
end new;

function addConnection
Expand All @@ -70,6 +74,13 @@ public
conns.flows := conn :: conns.flows;
end addFlow;

function addBroken
input BrokenEdges broken;
input output Connections conns;
algorithm
conns.broken := broken;
end addBroken;

function collect
input output FlatModel flatModel;
output Connections conns = new();
Expand Down
6 changes: 6 additions & 0 deletions Compiler/NFFrontEnd/NFConnector.mo
Expand Up @@ -129,6 +129,12 @@ public
conn1.face == conn2.face;
end isEqual;

function isPrefix
input Connector conn1;
input Connector conn2;
output Boolean isPrefix = ComponentRef.isPrefix(conn1.name, conn2.name);
end isPrefix;

function isOutside
input Connector conn;
output Boolean isOutside;
Expand Down
20 changes: 18 additions & 2 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -62,6 +62,7 @@ import NFClassTree.ClassTree;
import NFComponent.Component;
import NFModifier.Modifier;
import Sections = NFSections;
import NFOCConnectionGraph;
import Prefixes = NFPrefixes;
import NFPrefixes.Visibility;
import RangeIterator = NFRangeIterator;
Expand Down Expand Up @@ -870,6 +871,7 @@ algorithm
end addElementSourceArrayPrefix;

function resolveConnections
"Generates the connect equations and adds them to the equation list"
input output FlatModel flatModel;
input String name;
protected
Expand All @@ -878,17 +880,31 @@ protected
ConnectionSets.Sets csets;
array<list<Connector>> csets_array;
CardinalityTable.Table ctable;
Connections.BrokenEdges broken = {};
algorithm
// Generate the connect equations and add them to the equation list.
// handle overconstrained connections
// - build the graph
// - evaluate the Connections.* operators
// - generate the equations to replace the broken connects
// - return the broken connects + the equations
if System.getHasOverconstrainedConnectors() then
(flatModel, broken) := NFOCConnectionGraph.handleOverconstrainedConnections(flatModel, name);
end if;
// get the connections from the model
(flatModel, conns) := Connections.collect(flatModel);
// add the broken connections
conns := Connections.addBroken(broken, conns);
// build the sets, check the broken connects
csets := ConnectionSets.fromConnections(conns);
csets_array := ConnectionSets.extractSets(csets);
// generated the equations
conn_eql := ConnectEquations.generateEquations(csets_array);
// add the equations to the flat model
flatModel.equations := listAppend(conn_eql, flatModel.equations);
ctable := CardinalityTable.fromConnections(conns);

// Evaluate any connection operators if they're used.
if System.getHasStreamConnectors() or System.getUsesCardinality() then
if System.getHasStreamConnectors() or System.getUsesCardinality() then
flatModel := evaluateConnectionOperators(flatModel, csets, csets_array, ctable);
end if;

Expand Down
98 changes: 98 additions & 0 deletions Compiler/NFFrontEnd/NFHashTable.mo
@@ -0,0 +1,98 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

encapsulated package NFHashTable

/* Below is the instance specific code. For each hashtable the user must define:
Key - The key used to uniquely define elements in a hashtable
Value - The data to associate with each key
hashFunc - A function that maps a key to a positive integer.
keyEqual - A comparison function between two keys, returns true if equal.
*/

/* NFHashTable instance specific code */

public import BaseHashTable;
import ComponentRef = NFComponentRef;

public type Key = ComponentRef;
public type Value = Integer;

public type HashTableCrefFunctionsType = tuple<FuncHashCref, FuncCrefEqual, FuncCrefStr, FuncExpStr>;
public type HashTable = tuple<array<list<tuple<Key, Integer>>>,
tuple<Integer, Integer, array<Option<tuple<Key, Value>>>>,
Integer,
HashTableCrefFunctionsType>;

partial function FuncHashCref
input Key cr;
input Integer mod;
output Integer res;
end FuncHashCref;

partial function FuncCrefEqual
input Key cr1;
input Key cr2;
output Boolean res;
end FuncCrefEqual;

partial function FuncCrefStr
input Key cr;
output String res;
end FuncCrefStr;

partial function FuncExpStr
input Value exp;
output String res;
end FuncExpStr;

public function emptyHashTable
"
Returns an empty HashTable.
Using the default bucketsize..
"
output HashTable hashTable;
algorithm
hashTable := emptyHashTableSized(BaseHashTable.defaultBucketSize);
end emptyHashTable;

public function emptyHashTableSized
"Returns an empty HashTable.
Using the bucketsize size"
input Integer size;
output HashTable hashTable;
algorithm
hashTable := BaseHashTable.emptyHashTableWork(size,(ComponentRef.hash,ComponentRef.isEqual,ComponentRef.toString,intString));
end emptyHashTableSized;

annotation(__OpenModelica_Interface="frontend");
end NFHashTable;

0 comments on commit 15177bd

Please sign in to comment.