Skip to content

Commit cd764a7

Browse files
committed
Test case for the GDT
1 parent 7861971 commit cd764a7

File tree

9 files changed

+1229
-1
lines changed

9 files changed

+1229
-1
lines changed

src/test/kotlin/no/uio/microobject/test/MicroObjectTest.kt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,37 @@ open class MicroObjectTest : StringSpec() {
8383
val parser = WhileParser(tokens)
8484
return parser.program()
8585
}
86+
protected fun initInterpreter(str : List<String>) : Pair<Interpreter, TypeChecker> {
87+
val path = str.map { this::class.java.classLoader.getResource("$it.smol").file }
88+
val localPath = if(IS_OS_WINDOWS) path.map { it.removePrefix("/")} else path
89+
val stdLib = this::class.java.classLoader.getResource("StdLib.smol").readText() + "\n\n"
90+
val program = localPath.map { File(it).readText(Charsets.UTF_8)}.joinToString("\n")
91+
val lexer = WhileLexer(CharStreams.fromString(stdLib + program))
92+
val tokens = CommonTokenStream(lexer)
93+
val parser = WhileParser(tokens)
94+
val ast = parser.program()
95+
val visitor = Translate()
96+
val pair = visitor.generateStatic(ast)
97+
98+
val tripleManager = TripleManager(settings, pair.second, null)
99+
100+
val tC = TypeChecker(ast, settings, tripleManager)
101+
tC.collect()
102+
103+
104+
val initGlobalStore: GlobalMemory = mutableMapOf(Pair(pair.first.obj, mutableMapOf()))
105+
106+
val initStack = Stack<StackEntry>()
107+
initStack.push(pair.first)
108+
val interpreter = Interpreter(
109+
initStack,
110+
initGlobalStore,
111+
mutableMapOf(),
112+
pair.second,
113+
settings
114+
)
115+
return Pair(interpreter, tC)
116+
}
86117

87118
protected fun initInterpreter(str : String, loadAs : StringLoad = StringLoad.PATH) : Pair<Interpreter, TypeChecker> {
88119
val ast = when(loadAs){
@@ -100,7 +131,6 @@ open class MicroObjectTest : StringSpec() {
100131

101132
val tC = TypeChecker(ast, settings, tripleManager)
102133
tC.collect()
103-
var rules = ""
104134

105135

106136
val initGlobalStore: GlobalMemory = mutableMapOf(Pair(pair.first.obj, mutableMapOf()))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package no.uio.microobject.test.execution
2+
3+
import no.uio.microobject.ast.expr.LiteralExpr
4+
import no.uio.microobject.ast.expr.LocalVar
5+
import no.uio.microobject.test.MicroObjectTest
6+
import no.uio.microobject.type.INTTYPE
7+
import kotlin.test.assertEquals
8+
9+
class AdaptTest : MicroObjectTest() {
10+
11+
init {
12+
"adapt"{
13+
14+
loadBackground("src/test/resources/selfadapt/greenhouse.ttl","urn:")
15+
val (a,_) = initInterpreter(listOf("selfadapt/Greenhouse_data","selfadapt/Greenhouse_health","selfadapt/Greenhouse_plants",
16+
"selfadapt/Greenhouse_pots","selfadapt/Greenhouse_pumps","selfadapt/GreenHouse"))
17+
executeUntilBreak(a)
18+
assertEquals(1, a.stack.size)
19+
assertEquals(LiteralExpr("3", INTTYPE), a.evalTopMost(LocalVar("l1", INTTYPE)))
20+
assertEquals(LiteralExpr("4", INTTYPE), a.evalTopMost(LocalVar("l2", INTTYPE)))
21+
assertEquals(LiteralExpr("4", INTTYPE), a.evalTopMost(LocalVar("l3", INTTYPE)))
22+
assertEquals(LiteralExpr("4", INTTYPE), a.evalTopMost(LocalVar("l4", INTTYPE)))
23+
}
24+
}
25+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
abstract class KindModel (String name)
2+
Unit adapt()
3+
print("RECONFIG> Reconfiguring the "++ this.name);
4+
this.adaptDefect();
5+
this.adaptAddition();
6+
this.adaptRemoval();
7+
end
8+
9+
abstract Unit adaptAddition()
10+
abstract Unit adaptRemoval()
11+
abstract Unit adaptDefect()
12+
end
13+
14+
/*
15+
* This class implements the twinning logic and is responsible to implement decision making
16+
* and the adaptation cycle. The connections between assets remain implicit as they are not used explicitly,
17+
* but twinning is still established w.r.t. having the right assets.
18+
*
19+
* Field this.decisions contains the control decision made by the last cycle.
20+
*/
21+
class AssetModel extends Twin (List<Decision> decisions, List<KindModel> mods)
22+
23+
Unit register(KindModel m)
24+
this.mods = new List<KindModel>(m, this.mods);
25+
end
26+
27+
Unit reconfigure()
28+
print("RECONFIG> Reconfiguring the asset model...");
29+
30+
List<KindModel> ms = this.mods;
31+
while ms != null do
32+
ms.content.adapt();
33+
ms = ms.next;
34+
end
35+
36+
print("RECONFIG> Reconfiguring DONE...");
37+
end
38+
end
39+
40+
main
41+
//MBC Start
42+
// to enable MBC, uncomment the following lines and comment out the line marked with NON-MBC
43+
/*
44+
ModelControl dc = new ModelControl(0.0, null);
45+
dc.reconfigureModel(60.0); //this actually instantiated the FMU
46+
*/
47+
//MBC End
48+
AssetModel assetModel = new AssetModel(null, null);
49+
50+
PotModel m1 = new PotModel("pots");
51+
PlantModel m2 = new PlantModel("plants");
52+
PumpModel m3 = new PumpModel("pumps");
53+
54+
assetModel.register(m1);
55+
assetModel.register(m2);
56+
assetModel.register(m3);
57+
58+
//NDVI START
59+
HealthModel m4 = new HealthModel("health states");
60+
assetModel.register(m4);
61+
//NDVI STOP
62+
63+
64+
assetModel.reconfigure();
65+
List<HealthState> ll1 = access("SELECT ?x {?x a prog:HealthState}");
66+
List<HealthState> ll2 = access("SELECT ?x {?x a prog:Pot}");
67+
List<HealthState> ll3 = access("SELECT ?x {?x a prog:Plant}");
68+
List<HealthState> ll4 = access("SELECT ?x {?x a prog:Pump}");
69+
Int l1 = ll1.length();
70+
Int l2 = ll2.length();
71+
Int l3 = ll3.length();
72+
Int l4 = ll4.length();
73+
breakpoint;
74+
breakpoint;
75+
end
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
abstract class Twin() end
2+
3+
/**
4+
* Models a physical plant. It is initially retrieved by
5+
* the asset model, but it can be reconfigured by the program model.
6+
* Each plant is associated with a pot.
7+
*/
8+
class Plant extends Twin (String plantId, Double idealMoisture, String healthState)
9+
10+
Double getPotMoisture()
11+
Double moisture = 100.0;
12+
List<Double> influxReturn = access(
13+
"from(bucket: \"GreenHouseDemo\")
14+
|> range(start: -30d)
15+
|> filter(fn: (r) => r[\"_measurement\"] == \"ast:pot\")
16+
|> filter(fn: (r) => r[\"_field\"] == \"moisture\")
17+
|> filter(fn: (r) => r[\"plant_id\"] == %1)
18+
|> keep(columns: [\"_value\"])
19+
|> last()",
20+
INFLUXDB("config_local.yml"),
21+
this.plantId);
22+
23+
if influxReturn != null then
24+
moisture = influxReturn.content;
25+
end
26+
27+
return moisture;
28+
end
29+
30+
31+
// NDVI START
32+
Double getNdvi()
33+
Double healthState = 0.0;
34+
List<Double> influxReturn = access(
35+
"from(bucket: \"GreenHouseDemo\")
36+
|> range(start: -30d)
37+
|> filter(fn: (r) => r[\"_measurement\"] == \"ast:plant\")
38+
|> filter(fn: (r) => r[\"_field\"] == \"ndvi\")
39+
|> filter(fn: (r) => r[\"plant_id\"] == %1)
40+
|> keep(columns: [\"_value\"])
41+
|> last()",
42+
INFLUXDB("config_local.yml"),
43+
this.plantId);
44+
45+
if influxReturn != null then
46+
healthState = influxReturn.content;
47+
end
48+
49+
return healthState;
50+
end
51+
// NDVI END
52+
end
53+
54+
55+
/* Models a physical pot. It is initially retrieved by the asset model. Each pot is associated with a moisture sensor. */
56+
class Pot extends Twin (String shelfFloor, String potPosition, String pumpId, String plantId) end
57+
58+
59+
/** The following classes represent instances of assets that we currently not using directly but that are twinned for possible extensions */
60+
/* Models a physical shelf. It is initially retrieved by the asset model. */
61+
class Shelf extends Twin (String shelfFloor) end
62+
63+
/* Models a physical pump. It is initially retrieved by the asset model. */
64+
class Pump extends Twin (Int pumpGpioPin, String pumpId) end
65+
66+
67+
// NDVI START
68+
/* Models the health state of a plant via NDVI */
69+
class HealthState extends Twin (String name, Double minNdvi, Double maxNdvi) end
70+
// NDVI END
71+
72+
/* The following classes are used to store results of CONSTRUCT queries */
73+
class PumpDefect (Pump obj, Int pumpGpioPinNew) end
74+
class PlantDefect (Plant obj, Double idealMoistureNew) end
75+
class PotDefectShelf (Pot obj, String shelfFloorNew) end
76+
class PotDefectPosition (Pot obj, String potPositionNew) end
77+
class PotDefectPump (Pot obj, String pumpIdNew) end
78+
class PotDefectPlant (Pot obj, String plantIdNew) end
79+
80+
/*
81+
* The follow class is used to store results that are read from the simulation driver.
82+
* Every instance is representing on decision to water a specific plant and pump.
83+
*/
84+
class Decision (String plantId, Int pumpGpioPin, String pumpId) end
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//NDVI START
2+
class HealthModel extends KindModel()
3+
override Unit adaptAddition()
4+
List<HealthState> newHealthStates = construct("
5+
PREFIX ast: <http://www.smolang.org/greenhouseDT#>
6+
SELECT ?name ?maxNdvi ?minNdvi {
7+
?healthState a ast:HealthState ;
8+
ast:name ?name ;
9+
ast:maxNdvi ?maxNdvi ;
10+
ast:minNdvi ?minNdvi .
11+
FILTER NOT EXISTS {
12+
?y a prog:HealthState; prog:HealthState_name ?name.
13+
}
14+
}");
15+
16+
if newHealthStates != null then
17+
print("RECONFIG> New Health State(s) detected: repairing the model");
18+
19+
while newHealthStates != null do
20+
HealthState newHealthState = newHealthStates.content;
21+
List<HealthState> lx = newHealthStates;
22+
newHealthStates = newHealthStates.next;
23+
destroy(lx);
24+
25+
print("RECONFIG> New Health State detected: ");
26+
print(" Name: " ++ newHealthState.name);
27+
print(" Max Ndvi: " ++ doubleToString(newHealthState.maxNdvi));
28+
print(" Min Ndvi: " ++ doubleToString(newHealthState.minNdvi));
29+
30+
end
31+
32+
print("RECONFIG> Health State(s) added");
33+
else print("RECONFIG> No Health State(s) added"); end
34+
end
35+
36+
37+
override Unit adaptRemoval()
38+
List<HealthState> wrongHealthStates = access("
39+
PREFIX ast: <http://www.smolang.org/greenhouseDT#>
40+
SELECT DISTINCT ?obj {
41+
?obj a prog:HealthState; prog:HealthState_name ?name.
42+
FILTER NOT EXISTS {
43+
?y a ast:HealthState; ast:name ?name.
44+
}
45+
}");
46+
47+
if wrongHealthStates != null then
48+
print("RECONFIG> Misconfigured Health State(s) detected: repairing the model");
49+
50+
while wrongHealthStates != null do
51+
HealthState wrongHealthState = wrongHealthStates.content;
52+
List<HealthState> lx = wrongHealthStates;
53+
wrongHealthStates = wrongHealthStates.next;
54+
destroy(lx);
55+
56+
print("RECONFIG> Misconfigured plant to remove: ");
57+
print(" Name: " ++ wrongHealthState.name);
58+
print(" Max Ndvi: " ++ doubleToString(wrongHealthState.maxNdvi));
59+
print(" Min Ndvi: " ++ doubleToString(wrongHealthState.minNdvi));
60+
61+
destroy(wrongHealthState);
62+
end
63+
end
64+
end
65+
66+
67+
override Unit adaptDefect() skip; end
68+
end
69+
//NDVI STOP

0 commit comments

Comments
 (0)