Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
monticore
EmbeddedMontiArc
generators
EMAM2Middleware
Commits
fa77b2a1
Commit
fa77b2a1
authored
Nov 07, 2018
by
Alexander David Hellwig
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added Tag annotating from spectral clustering
parent
7331af39
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
273 additions
and
16 deletions
+273
-16
src/main/java/de/monticore/lang/monticar/generator/middleware/helpers/ClusterHelper.java
.../monticar/generator/middleware/helpers/ClusterHelper.java
+80
-12
src/main/java/de/monticore/lang/monticar/generator/middleware/helpers/ClustererKind.java
.../monticar/generator/middleware/helpers/ClustererKind.java
+5
-0
src/test/java/de/monticore/lang/monticar/generator/middleware/AutomaticClusteringTest.java
...onticar/generator/middleware/AutomaticClusteringTest.java
+141
-4
src/test/resources/clustering/ClustersWithSingleConnection.emam
...st/resources/clustering/ClustersWithSingleConnection.emam
+24
-0
src/test/resources/clustering/InComp.emam
src/test/resources/clustering/InComp.emam
+5
-0
src/test/resources/clustering/OutComp.emam
src/test/resources/clustering/OutComp.emam
+5
-0
src/test/resources/clustering/UnambiguousCluster.emam
src/test/resources/clustering/UnambiguousCluster.emam
+13
-0
No files found.
src/main/java/de/monticore/lang/monticar/generator/middleware/helpers/ClusterHelper.java
View file @
fa77b2a1
package
de.monticore.lang.monticar.generator.middleware.helpers
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.*
;
import
de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosConnectionSymbol
;
import
de.monticore.symboltable.CommonScope
;
import
de.monticore.symboltable.MutableScope
;
import
de.monticore.symboltable.Symbol
;
...
...
@@ -10,6 +11,7 @@ import org.jgrapht.Graph;
import
org.jgrapht.alg.ConnectivityInspector
;
import
org.jgrapht.graph.DefaultEdge
;
import
org.jgrapht.graph.SimpleGraph
;
import
smile.clustering.SpectralClustering
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -146,33 +148,43 @@ public class ClusterHelper {
}
public
static
double
[][]
createAdjacencyMatrix
(
ExpandedComponentInstanceSymbol
component
)
{
// Nodes = subcomponents
// Verts = connectors between subcomponents
Collection
<
ExpandedComponentInstanceSymbol
>
subcomps
=
component
.
getSubComponents
().
stream
()
public
static
List
<
ExpandedComponentInstanceSymbol
>
getSubcompsOrderedByName
(
ExpandedComponentInstanceSymbol
componentInstanceSymbol
){
return
componentInstanceSymbol
.
getSubComponents
().
stream
()
.
sorted
(
Comparator
.
comparing
(
ExpandedComponentInstanceSymbol:
:
getFullName
))
.
collect
(
Collectors
.
toList
());
}
public
static
Collection
<
ConnectorSymbol
>
getInnerConnectors
(
ExpandedComponentInstanceSymbol
componentInstanceSymbol
){
String
superCompName
=
componentInstanceSymbol
.
getFullName
();
return
componentInstanceSymbol
.
getConnectors
().
stream
()
//filter out all connectors to super component
.
filter
(
con
->
!
con
.
getSourcePort
().
getComponentInstance
().
get
().
getFullName
().
equals
(
superCompName
)
&&
!
con
.
getTargetPort
().
getComponentInstance
().
get
().
getFullName
().
equals
(
superCompName
))
.
collect
(
Collectors
.
toList
());
}
public
static
Map
<
String
,
Integer
>
getLabelsForSubcomps
(
List
<
ExpandedComponentInstanceSymbol
>
subcomps
)
{
Map
<
String
,
Integer
>
componentIndecies
=
new
HashMap
<>();
String
superCompName
=
component
.
getFullName
();
int
[]
i
=
{
0
};
subcomps
.
forEach
(
sc
->
componentIndecies
.
put
(
sc
.
getFullName
(),
i
[
0
]++));
return
componentIndecies
;
}
public
static
double
[][]
createAdjacencyMatrix
(
List
<
ExpandedComponentInstanceSymbol
>
subcomps
,
Collection
<
ConnectorSymbol
>
connectors
,
Map
<
String
,
Integer
>
subcompLabels
)
{
// Nodes = subcomponents
// Verts = connectors between subcomponents
double
[][]
res
=
new
double
[
subcomps
.
size
()][
subcomps
.
size
()];
Collection
<
ConnectorSymbol
>
connectors
=
component
.
getConnectors
().
stream
()
//filter out all connectors to super component
.
filter
(
con
->
!
con
.
getSourcePort
().
getComponentInstance
().
get
().
getFullName
().
equals
(
superCompName
)
&&
!
con
.
getTargetPort
().
getComponentInstance
().
get
().
getFullName
().
equals
(
superCompName
))
.
collect
(
Collectors
.
toList
());
connectors
.
forEach
(
con
->
{
Optional
<
ExpandedComponentInstanceSymbol
>
sourceCompOpt
=
con
.
getSourcePort
().
getComponentInstance
();
Optional
<
ExpandedComponentInstanceSymbol
>
targetCompOpt
=
con
.
getTargetPort
().
getComponentInstance
();
if
(
sourceCompOpt
.
isPresent
()
&&
targetCompOpt
.
isPresent
())
{
int
index1
=
comp
onentIndecie
s
.
get
(
sourceCompOpt
.
get
().
getFullName
());
int
index2
=
comp
onentIndecie
s
.
get
(
targetCompOpt
.
get
().
getFullName
());
int
index1
=
sub
comp
Label
s
.
get
(
sourceCompOpt
.
get
().
getFullName
());
int
index2
=
sub
comp
Label
s
.
get
(
targetCompOpt
.
get
().
getFullName
());
res
[
index1
][
index2
]
=
1.0d
;
res
[
index2
][
index1
]
=
1.0d
;
...
...
@@ -185,4 +197,60 @@ public class ClusterHelper {
return
res
;
}
public
static
List
<
Set
<
ExpandedComponentInstanceSymbol
>>
createClusters
(
ExpandedComponentInstanceSymbol
component
,
int
numberOfClusters
,
ClustererKind
clustererKind
){
//TODO: create wrapper for clusterer for easy exchange
List
<
ExpandedComponentInstanceSymbol
>
subcompsOrderedByName
=
ClusterHelper
.
getSubcompsOrderedByName
(
component
);
Map
<
String
,
Integer
>
labelsForSubcomps
=
ClusterHelper
.
getLabelsForSubcomps
(
subcompsOrderedByName
);
double
[][]
adjMatrix
=
ClusterHelper
.
createAdjacencyMatrix
(
subcompsOrderedByName
,
ClusterHelper
.
getInnerConnectors
(
component
),
labelsForSubcomps
);
SpectralClustering
clustering
=
new
SpectralClustering
(
adjMatrix
,
numberOfClusters
);
int
[]
labels
=
clustering
.
getClusterLabel
();
List
<
Set
<
ExpandedComponentInstanceSymbol
>>
res
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
numberOfClusters
;
i
++){
res
.
add
(
new
HashSet
<>());
}
subcompsOrderedByName
.
forEach
(
sc
->
{
int
curClusterLabel
=
labels
[
labelsForSubcomps
.
get
(
sc
.
getFullName
())];
res
.
get
(
curClusterLabel
).
add
(
sc
);
});
return
res
;
}
public
static
void
annotateComponentWithRosTagsForClusters
(
ExpandedComponentInstanceSymbol
componentInstanceSymbol
,
List
<
Set
<
ExpandedComponentInstanceSymbol
>>
clusters
)
{
Collection
<
ConnectorSymbol
>
connectors
=
componentInstanceSymbol
.
getConnectors
();
connectors
.
forEach
(
con
->
{
// -1 = super comp
int
sourceClusterLabel
=
-
1
;
int
targetClusterLabel
=
-
1
;
ExpandedComponentInstanceSymbol
sourceComp
=
con
.
getSourcePort
().
getComponentInstance
().
get
();
ExpandedComponentInstanceSymbol
targetComp
=
con
.
getTargetPort
().
getComponentInstance
().
get
();
for
(
int
i
=
0
;
i
<
clusters
.
size
();
i
++){
if
(
clusters
.
get
(
i
).
contains
(
sourceComp
)){
sourceClusterLabel
=
i
;
}
if
(
clusters
.
get
(
i
).
contains
(
targetComp
)){
targetClusterLabel
=
i
;
}
}
if
(
sourceClusterLabel
!=
targetClusterLabel
){
con
.
getSourcePort
().
setMiddlewareSymbol
(
new
RosConnectionSymbol
());
con
.
getTargetPort
().
setMiddlewareSymbol
(
new
RosConnectionSymbol
());
}
});
}
}
src/main/java/de/monticore/lang/monticar/generator/middleware/helpers/ClustererKind.java
0 → 100644
View file @
fa77b2a1
package
de.monticore.lang.monticar.generator.middleware.helpers
;
public
enum
ClustererKind
{
SPECTRAL_CLUSTERER
}
src/test/java/de/monticore/lang/monticar/generator/middleware/AutomaticClusteringTest.java
View file @
fa77b2a1
package
de.monticore.lang.monticar.generator.middleware
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol
;
import
de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosToEmamTagSchema
;
import
de.monticore.lang.monticar.emadl.generator.EMADLAbstractSymtab
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol
;
import
de.monticore.lang.monticar.generator.middleware.helpers.ClusterHelper
;
import
de.monticore.lang.monticar.generator.roscpp.helper.TagHelper
;
import
de.monticore.lang.monticar.generator.middleware.impls.CPPGenImpl
;
import
de.monticore.lang.monticar.generator.middleware.impls.RosCppGenImpl
;
import
de.monticore.lang.tagging._symboltable.TaggingResolver
;
import
de.monticore.symboltable.CommonSymbol
;
import
org.junit.Test
;
import
smile.clustering.SpectralClustering
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
...
...
@@ -24,7 +33,10 @@ public class AutomaticClusteringTest extends AbstractSymtabTest{
ExpandedComponentInstanceSymbol
componentInstanceSymbol
=
taggingResolver
.<
ExpandedComponentInstanceSymbol
>
resolve
(
"lab.system"
,
ExpandedComponentInstanceSymbol
.
KIND
).
orElse
(
null
);
assertNotNull
(
componentInstanceSymbol
);
double
[][]
matrix
=
ClusterHelper
.
createAdjacencyMatrix
(
componentInstanceSymbol
);
List
<
ExpandedComponentInstanceSymbol
>
subcompsOrderedByName
=
ClusterHelper
.
getSubcompsOrderedByName
(
componentInstanceSymbol
);
double
[][]
matrix
=
ClusterHelper
.
createAdjacencyMatrix
(
subcompsOrderedByName
,
ClusterHelper
.
getInnerConnectors
(
componentInstanceSymbol
),
ClusterHelper
.
getLabelsForSubcomps
(
subcompsOrderedByName
));
//sorted by full name: alex, combine, dinhAn, michael, philipp
...
...
@@ -42,6 +54,131 @@ public class AutomaticClusteringTest extends AbstractSymtabTest{
}
@Test
public
void
testSpectralClustering
(){
// 0 1 0 0
// 1 0 0 0
// 0 0 0 1
// 0 0 1 0
//zu 2 cluster -> (a,b) (c,d)
double
[][]
adjMatrix
=
{{
0
,
1
,
0
,
0
},
{
1
,
0
,
0
,
0
},
{
0
,
0
,
0
,
1
},
{
0
,
0
,
1
,
0
}};
SpectralClustering
clustering
=
new
SpectralClustering
(
adjMatrix
,
2
);
int
[]
labels
=
clustering
.
getClusterLabel
();
for
(
int
label
:
labels
)
{
System
.
out
.
println
(
label
);
}
assertEquals
(
4
,
labels
.
length
);
assertTrue
(
labels
[
0
]
==
labels
[
1
]);
assertTrue
(
labels
[
2
]
==
labels
[
3
]);
assertTrue
(
labels
[
0
]
!=
labels
[
2
]);
assertTrue
(
labels
[
0
]
!=
labels
[
3
]);
assertTrue
(
labels
[
1
]
!=
labels
[
2
]);
assertTrue
(
labels
[
1
]
!=
labels
[
3
]);
}
@Test
public
void
testCreateClusters
(){
//UnambiguousCluster
TaggingResolver
taggingResolver
=
AbstractSymtabTest
.
createSymTabAndTaggingResolver
(
TEST_PATH
);
ExpandedComponentInstanceSymbol
componentInstanceSymbol
=
taggingResolver
.<
ExpandedComponentInstanceSymbol
>
resolve
(
"clustering.unambiguousCluster"
,
ExpandedComponentInstanceSymbol
.
KIND
).
orElse
(
null
);
assertNotNull
(
componentInstanceSymbol
);
List
<
Set
<
ExpandedComponentInstanceSymbol
>>
clusters
=
ClusterHelper
.
createClusters
(
componentInstanceSymbol
,
2
,
null
);
assertTrue
(
clusters
.
size
()
==
2
);
Set
<
ExpandedComponentInstanceSymbol
>
cluster1
=
clusters
.
get
(
0
);
Set
<
ExpandedComponentInstanceSymbol
>
cluster2
=
clusters
.
get
(
1
);
assertTrue
(
cluster1
.
size
()
==
2
);
assertTrue
(
cluster2
.
size
()
==
2
);
List
<
String
>
cluster1Names
=
cluster1
.
stream
()
.
map
(
CommonSymbol:
:
getFullName
)
.
collect
(
Collectors
.
toList
());
List
<
String
>
cluster2Names
=
cluster2
.
stream
()
.
map
(
CommonSymbol:
:
getFullName
)
.
collect
(
Collectors
.
toList
());
if
(
cluster1Names
.
get
(
0
).
endsWith
(
"compA"
)
||
cluster1Names
.
get
(
0
).
endsWith
(
"compB"
)){
assertTrue
(
cluster1Names
.
contains
(
"clustering.unambiguousCluster.compA"
));
assertTrue
(
cluster1Names
.
contains
(
"clustering.unambiguousCluster.compB"
));
assertTrue
(
cluster2Names
.
contains
(
"clustering.unambiguousCluster.compC"
));
assertTrue
(
cluster2Names
.
contains
(
"clustering.unambiguousCluster.compD"
));
}
else
{
assertTrue
(
cluster1Names
.
contains
(
"clustering.unambiguousCluster.compC"
));
assertTrue
(
cluster1Names
.
contains
(
"clustering.unambiguousCluster.compD"
));
assertTrue
(
cluster2Names
.
contains
(
"clustering.unambiguousCluster.compA"
));
assertTrue
(
cluster2Names
.
contains
(
"clustering.unambiguousCluster.compB"
));
}
}
@Test
public
void
testClusterToRosConnections
()
throws
IOException
{
TaggingResolver
taggingResolver
=
AbstractSymtabTest
.
createSymTabAndTaggingResolver
(
TEST_PATH
);
//ClustersWithSingleConnection
ExpandedComponentInstanceSymbol
componentInstanceSymbol
=
taggingResolver
.<
ExpandedComponentInstanceSymbol
>
resolve
(
"clustering.clustersWithSingleConnection"
,
ExpandedComponentInstanceSymbol
.
KIND
).
orElse
(
null
);
assertNotNull
(
componentInstanceSymbol
);
//Force cluster; spectral would not cluster this way!
List
<
Set
<
ExpandedComponentInstanceSymbol
>>
clusters
=
new
ArrayList
<>();
HashSet
<
ExpandedComponentInstanceSymbol
>
cluster1
=
new
HashSet
<>();
cluster1
.
add
(
componentInstanceSymbol
.
getSubComponent
(
"outComp1"
).
get
());
cluster1
.
add
(
componentInstanceSymbol
.
getSubComponent
(
"inOutComp"
).
get
());
clusters
.
add
(
cluster1
);
HashSet
<
ExpandedComponentInstanceSymbol
>
cluster2
=
new
HashSet
<>();
cluster2
.
add
(
componentInstanceSymbol
.
getSubComponent
(
"outComp2"
).
get
());
cluster2
.
add
(
componentInstanceSymbol
.
getSubComponent
(
"doubleInComp"
).
get
());
clusters
.
add
(
cluster2
);
ClusterHelper
.
annotateComponentWithRosTagsForClusters
(
componentInstanceSymbol
,
clusters
);
List
<
String
>
rosPortsSuper
=
componentInstanceSymbol
.
getPortsList
().
stream
()
.
filter
(
PortSymbol:
:
isRosPort
)
.
map
(
PortSymbol:
:
getFullName
)
.
collect
(
Collectors
.
toList
());
List
<
String
>
rosPortsSubComps
=
componentInstanceSymbol
.
getSubComponents
().
stream
()
.
flatMap
(
subc
->
subc
.
getPortsList
().
stream
())
.
filter
(
PortSymbol:
:
isRosPort
)
.
map
(
PortSymbol:
:
getFullName
)
.
collect
(
Collectors
.
toList
());
//No Ports in super comp
assertTrue
(
rosPortsSuper
.
size
()
==
0
);
assertTrue
(
rosPortsSubComps
.
size
()
==
2
);
assertTrue
(
rosPortsSubComps
.
contains
(
"clustering.clustersWithSingleConnection.inOutComp.out1"
));
assertTrue
(
rosPortsSubComps
.
contains
(
"clustering.clustersWithSingleConnection.doubleInComp.in2"
));
DistributedTargetGenerator
distributedTargetGenerator
=
new
DistributedTargetGenerator
();
distributedTargetGenerator
.
setGenerationTargetPath
(
"./target/generated-sources-clustering/ClusterToRosConnections/src/"
);
distributedTargetGenerator
.
add
(
new
CPPGenImpl
(),
"cpp"
);
distributedTargetGenerator
.
add
(
new
RosCppGenImpl
(),
"roscpp"
);
distributedTargetGenerator
.
generate
(
componentInstanceSymbol
,
taggingResolver
);
}
}
src/test/resources/clustering/ClustersWithSingleConnection.emam
0 → 100644
View file @
fa77b2a1
package
clustering
;
component
ClustersWithSingleConnection
{
component
InOutComp
{
ports
in
Q
in1
,
out
Q
out1
;
}
component
DoubleInComp
{
port
in
Q
in1
,
in
Q
in2
;
}
instance
OutComp
outComp1
;
instance
OutComp
outComp2
;
instance
DoubleInComp
doubleInComp
;
instance
InOutComp
inOutComp
;
connect
outComp1
.
out1
->
inOutComp
.
in1
;
connect
outComp2
.
out1
->
doubleInComp
.
in1
;
connect
inOutComp
.
out1
->
doubleInComp
.
in2
;
}
\ No newline at end of file
src/test/resources/clustering/InComp.emam
0 → 100644
View file @
fa77b2a1
package
clustering
;
component
InComp
{
port
in
Q
in1
;
}
\ No newline at end of file
src/test/resources/clustering/OutComp.emam
0 → 100644
View file @
fa77b2a1
package
clustering
;
component
OutComp
{
port
out
Q
out1
;
}
\ No newline at end of file
src/test/resources/clustering/UnambiguousCluster.emam
0 → 100644
View file @
fa77b2a1
package
clustering
;
component
UnambiguousCluster
{
//
compA
->
compB
;
compC
->
compD
instance
OutComp
compA
;
instance
InComp
compB
;
instance
OutComp
compC
;
instance
InComp
compD
;
connect
compA
.
out1
->
compB
.
in1
;
connect
compC
.
out1
->
compD
.
in1
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment