[TASK] Generic commit.

This commit is contained in:
Jan Philipp Timme 2016-10-10 16:32:44 +02:00
parent cd83481da3
commit 804d6b219c

View File

@ -1099,7 +1099,7 @@ WHERE {
FILTER(?deltaSpeed > 25)
}
\end{lstlisting}
Diese muss nun lediglich als Ereignisdatenstrom an der Engine registriert werden, und kann dann innerhalb von weiteren C-SPARQL-Queries verwendet werden.
Diese Abfrage wird nun als Ereignisdatenstrom mit der URI \texttt{http://example.org/carSim/stream/getStronglyAcceleratingCars} an der Engine registriert, und kann dann innerhalb von weiteren C-SPARQL-Queries verwendet werden.
\item \textbf{Verschleiß der Bremsen durch sehr starke Bremsmanöver:}
Die Umsetzung hier ist sehr ähnlich zu dem Query aus Listing~\ref{lst:scenario_strong_acceleration}, da der einzige Unterschied die Beschleunigungsrichtung ist. Somit ist für die Erkennung lediglich die Vertauschung der beiden Geschwindigkeitsparameter bei der Differenzbildung notwendig. Am Ende der Auswertung wird dann ein Ereignis vom Typ \texttt{CarStrongBrakeEvent} gefeuert.
@ -1145,7 +1145,7 @@ WHERE {
FILTER(?avgMotorRPM > ?maxMotorRPM)
}
\end{lstlisting}
Auch diese Abfrage muss später in der Engine als Datenstrom registriert werden, um innerhalb von weiteren Abfragen auf die Ergebnisse dieses Queries zugreifen zu können.
Auch diese Abfrage muss später in der Engine als Datenstrom registriert werden, um innerhalb von weiteren Abfragen auf die Ergebnisse dieses Queries zugreifen zu können. Hierfür wird die URI \texttt{http://example.org/carSim/stream/getEngineWear} verwendet.
\item \textbf{Verschleiß der Handbremse durch Fahren mit angezogener Handbremse:}
Da das \texttt{CarStatusEvent} Informationen zur Momentangeschwindigkeit eines PKW und zum Status dessen Handbremse liefert, ist es völlig ausreichend, für alle Statusereignisse ein neues Verschleißereignis auszulösen, in denen die Geschwindigkeit bei angezogener Handbremse größer als null ist. Abstrakt formuliert sieht dies so aus:
@ -1156,7 +1156,7 @@ CONDITION ($(CarStatusEvent\ AS\ statusEvent)$)[WindowSize:3s,StepSize:1s]
ACTION
new CarHandbrakeWearEvent(relatedCar=statusEvent.relatedCar)
\end{lstlisting}
In einem C-SPARQL-Query sieht dies wie folgt aus:
In einem C-SPARQL-Query sieht dies dann wie folgt aus:
\begin{lstlisting}[label={},caption={Erkennung von Verschleiß der Handbremse}]
REGISTER STREAM getHandbrakeWear AS
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
@ -1177,12 +1177,140 @@ WHERE {
FILTER(?handbrakeEngaged = true)
}
\end{lstlisting}
Registriert man diese Abfrage ebenfalls als Datenstrom an der Engine, so kann man auch auf die Ergebnisse dieser Abfrage aus anderen C-SPARQL-Queries heraus zugreifen, um diese weiter zu verarbeiten. Für diesen Datenstrom wird die URI \texttt{http://example.org/carSim/stream/getHandbrakeWear} verwendet.
\item \textbf{Verschleiß der Reifen durch Fahren mit zu niedrigem Reifendruck:}
\item \textbf{Verschleiß der Reifen durch Fahren mit zu niedrigem Reifendruck:} Das Verfahren hierfür ist vergleichsweise ähnlich zu der Erkennung von Verschleiß an der Handbremse. Allerdings muss hier zusätzlich auf das lokale Domänenwissen zugegriffen werden, um den aktuellen Druck der Reifen mit dem empfohlenen Reifendruckbereich zu vergleichen. Liegt der Druck eines Reifen nicht im empfohlenen Bereich, so soll ein \texttt{CarTireWearEvent} ausgelöst werden.
Als CEP-Regel sieht dies so aus:
\begin{lstlisting}[mathescape=true,label={},caption={}]
CONDITION ($(CarStatusEvent\ AS\ statusEvent)$)[WindowSize:15s,StepSize:5s]
$\wedge$ statusEvent.speed > 0
$\wedge$ lookup("minimumTirePressure", statusEvent.relatedCar) AS minTirePressure
$\wedge$ (
(statusEvent.tirePressure1 < minTirePressure)
$\vee$ (statusEvent.tirePressure2 < minTirePressure)
$\vee$ (statusEvent.tirePressure3 < minTirePressure)
$\vee$ (statusEvent.tirePressure4 < minTirePressure)
)
ACTION
new CarTireWearEvent(relatedCar=c.relatedCar)
\end{lstlisting}
In einem C-SPARQL-Query führt der Abgleich der einzelnen Reifendruckwerte zu einem sehr langen Query:
\begin{lstlisting}[label={lst:scenario_tire_wear},caption={Erkennung von Verschleiß am Reifen}]
REGISTER STREAM getTireWear AS
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX f: <http://larkc.eu/csparql/sparql/jena/ext#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX car: <http://example.org/carSim/carSimulationOntology#>
CONSTRUCT {
[] rdf:type car:CarTireWearEvent
; car:relatedCar ?car .
}
FROM STREAM <http://example.org/carSim/stream/carStream> [RANGE 3s STEP 1s]
FROM <http://example.org/carSim/localDomainKnowledge>
WHERE {
?e rdf:type car:CarStatusEvent .
?e car:speed ?speed .
?e car:relatedCar ?car .
?car car:isCarModel ?carModel .
?carModel car:minimumTirePressure ?minTirePressure .
?e car:tirePressure1 ?tpress1 .
?e car:tirePressure2 ?tpress2 .
?e car:tirePressure3 ?tpress3 .
?e car:tirePressure4 ?tpress4 .
FILTER(?speed > 0)
FILTER(?tpress1 < ?minTirePressure || ?tpress2 < ?minTirePressure
|| ?tpress3 < ?minTirePressure || ?tpress4 < ?minTirePressure)
}
\end{lstlisting}
Auch dieser Query wird als Ereignisdatenstrom unter der URI \texttt{http://example.org/carSim/stream/getTireWear} zur weiteren Verarbeitung an der Engine registriert.
\end{itemize}
\paragraph{Tracking der Fahrer eines PKW}
Bevor nun die Ereignisdaten über Verschleiß an den PKW den Fahrern zugeordnet werden können, muss zunächst für die Pflege der Zuordnungsinformationen zwischen Fahrern und PKW gesorgt werden. Da ein Fahrzeug nur in einem bestimmten Zeitraum von einem bestimmten Fahrer geführt wird, müssen diese Informationen durchgehend aktualisiert werden, wenn sie im lokalen Domänenwissen vorgehalten werden sollen.
Um dies zu realisieren, werden zwei C-SPARQL-Queries geschrieben, die jeweils die einzelnen Ereignisse vom Typ \texttt{CarTakenEvent} und \texttt{CarReturnedEvent} aus dem Ereignisdatenstrom mit den Kundenereignissen extrahieren. Hierbei ist es zur Erhaltung der Datenkonsistenz wichtig, dass jedes dieser Ereignisse nur einmal zu einer Aktualisierung der lokalen Wissensbasis führt. Dafür wird in der entsprechenden Abfrage auf ein Tumbling Window gesetzt:
\begin{lstlisting}[label={lst:scenario_get_car_taken_events},caption={Selektion von Fahrerereignissen zur Aktualisierung der Wissensbasis}]
REGISTER QUERY getCarTakenEvents AS
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX f: <http://larkc.eu/csparql/sparql/jena/ext#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX car: <http://example.org/carSim/carSimulationOntology#>
SELECT ?driver ?car
FROM STREAM <http://example.org/carSim/stream/driverStream> [RANGE 2s TUMBLING]
WHERE {
?e rdf:type car:CarTakenEvent .
?e car:relatedCar ?car .
?e car:relatedUser ?driver .
}
\end{lstlisting}
Registriert man diesen Query an der Engine, so kann man mit Hilfe eines in Java geschriebenen Observers die lokale Wissensbasis um Einträge aktualisieren, in denen der Fahrer eines PKW entsprechend eingetragen oder --- wenn man dieses Verfahren für Ereignisse vom Typ \texttt{CarReturnedEvent} umsetzt --- ausgetragen werden. Der folgende Abschnitt zeigt den Code eines solchen Observers:
\begin{lstlisting}[label={scenario_observer_sparql_update},caption={Aktualisierung von lokalem Domänenwissen via SPARQL UPDATE}]
Observer resultObserver = new Observer() {
@Override
public void update(Observable o, Object arg) {
RDFTable results = (RDFTable) arg;
Collection<RDFTuple> tuples = results.getTuples();
for(RDFTuple tuple : tuples) {
String driverUri = tuple.get(0);
String carUri = tuple.get(1);
String updateQuery = "PREFIX car: <http://example.org/carSim/carSimulationOntology#>"
+ "INSERT DATA { " // Use "DELETE DATA" to remove the entry again
+ " GRAPH <http://example.org/carSim/localDomainKnowledge> { "
+ " <"+driverUri+"> car:drives <"+carUri+"> . "
+ " <"+carUri+"> car:isDrivenBy <"+driverUri+"> . "
+ " } "
+ "}";
RentACarSimulation.logger.debug(updateQuery);
engine.execUpdateQueryOverDatasource(updateQuery);
}
}
};
\end{lstlisting}
\paragraph{Zusammenfassung der Verschleißereignisse}
Um die einzelnen Ergebnisse aus den vorherigen Abfragen zusammenfassen zu können, ist zunächst erforderlich für die vier verschiedenen Ereignistypen eine gemeinsame Oberklasse \texttt{CarWearEvent} zu definieren. Hierzu werden der lokal vorliegenden TBox folgende RDFS-Daten hinzugefügt:
\begin{lstlisting}[label={lst:scenario_wear_event_tbox},caption={Klassenhierarchie für \texttt{CarWearEvent}s in RDFS}]
car:CarWearEvent rdf:type rdfs:Class .
car:CarWearEvent rdfs:subClassOf car:CarEvent .
car:CarEngineWearEvent rdf:type rdfs:Class .
car:CarEngineWearEvent rdfs:subClassOf car:CarWearEvent .
car:CarBrakeWearEvent rdf:type rdfs:Class .
car:CarBrakeWearEvent rdfs:subClassOf car:CarWearEvent .
car:CarHandbrakeWearEvent rdf:type rdfs:Class .
car:CarHandbrakeWearEvent rdfs:subClassOf car:CarWearEvent .
car:CarTireWearEvent rdf:type rdfs:Class .
car:CarTireWearEvent rdfs:subClassOf car:CarWearEvent .
\end{lstlisting}
Durch diese TBox ist es nun möglich, mit Hilfe von aktiviertem Reasoning alle Verschleißereignisse aus den vier erzeugten Ereignisdatenströmen zu extrahieren, ohne die einzelnen Verschleißereignistypen direkt nennen zu müssen. Um den jeweiligen Fahrer eines PKW den Verschleißereignissen zuordnen zu können, wird dieser über das lokale Domänenwissen unte Nutzung des Prädikats \texttt{car:isDrivenBy} ermittelt. Der folgende Query demonstriert dies:
\begin{lstlisting}
REGISTER QUERY getWearEvents AS
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX f: <http://larkc.eu/csparql/sparql/jena/ext#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX car: <http://example.org/carSim/carSimulationOntology#>
SELECT ?e ?type ?car ?driverName ?driverPhone
FROM STREAM <http://example.org/carSim/stream/getEngineWear> [RANGE 1s TUMBLING]
FROM STREAM <http://example.org/carSim/stream/getBrakeWear> [RANGE 1s TUMBLING]
FROM STREAM <http://example.org/carSim/stream/getHandbrakeWear> [RANGE 1s TUMBLING]
FROM STREAM <http://example.org/carSim/stream/getTireWear> [RANGE 1s TUMBLING]
FROM <http://example.org/carSim/localDomainKnowledge>
WHERE {
?e rdf:type car:CarWearEvent .
?e rdf:type ?type .
?e car:relatedCar ?car .
OPTIONAL {
?car car:isDrivenBy ?driver .
?driver car:hasName ?driverName .
?driver car:hasPhoneNumber ?driverPhone .
}
}
\end{lstlisting}
\section{Nutzung der C-SPARQL Engine in Java}