bachelorthesis/Bachelorarbeit.tex

840 lines
69 KiB
TeX
Raw Normal View History

2016-07-14 21:52:05 +02:00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016-03-07 12:46:38 +01:00
% Setup des Dokuments
2016-07-14 21:52:05 +02:00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016-03-07 12:46:38 +01:00
\documentclass[12pt,DIV14,BCOR10mm,a4paper,twoside,parskip=half-,headsepline,headinclude]{scrreprt} % Grundgröße 12pt, zweiseitig
2016-04-04 13:07:28 +02:00
% Packages from template
2016-03-07 12:46:38 +01:00
\usepackage[headsepline,automark]{scrpage2} % Seitenköpfe automatisch
\KOMAoptions{headinclude} % Fix
2016-04-23 13:26:48 +02:00
\usepackage[german]{babel} % Sprachpaket für Deutsch (Umlaute, Trennung,deutsche Überschriften)
2016-03-13 11:16:52 +01:00
\usepackage{graphicx,hyperref} % Graphikeinbindung, Hyperref (alles klickbar, Bookmarks)
\usepackage{amssymb} % Math. Symbole aus AmsTeX
2016-03-07 12:46:38 +01:00
\usepackage[utf8]{inputenc} % Umlaute
2016-04-04 13:07:28 +02:00
% Custom packages
\usepackage[autostyle=true,german=quotes]{csquotes} % Anführungszeichen mit \enquote{}
\usepackage{textcomp} % Zusätzliches Package für °C
\usepackage{listings} % Codesnippets
\usepackage{scrhack} % Hack for lstlisting i suspect :-/
2016-07-15 15:10:19 +02:00
\usepackage{xcolor}
\usepackage{float}
2016-09-14 14:36:44 +02:00
\usepackage{soul}
2016-07-25 15:48:24 +02:00
\usepackage{verbatim} % für comment-environment
2016-09-28 11:57:47 +02:00
\usepackage{amsmath}
2016-04-04 13:07:28 +02:00
% Setup für Codeblocks
\lstset{
% Optionen
breaklines=true,
breakatwhitespace=true,
breakautoindent=true,
frame=single,
%framexleftmargin=19pt,
inputencoding=utf8,
%language=awk,
2016-04-04 13:07:28 +02:00
%numbers=left,
%numbersep=8pt,
showspaces=false,
showstringspaces=false,
tabsize=1,
%xleftmargin=19pt,
captionpos=b,
% Styling
basicstyle=\footnotesize\ttfamily,
commentstyle=\footnotesize,
keywordstyle=\footnotesize\ttfamily,
numberstyle=\footnotesize,
stringstyle=\footnotesize\ttfamily,
2016-04-04 13:07:28 +02:00
}
% Hack für Sonderzeichen in Codeblocks
\lstset{literate=%
{Ö}{{\"O}}1
{Ä}{{\"A}}1
{Ü}{{\"U}}1
{ß}{{\ss}}1
{ü}{{\"u}}1
{ä}{{\"a}}1
{ö}{{\"o}}1
{°}{{${^\circ}$}}1
}
2016-03-07 12:17:22 +01:00
2016-04-22 14:12:28 +02:00
% Befehl für TODO-Markierungen
2016-07-15 15:10:19 +02:00
\newcommand{\todo}[1]{\textcolor{blue}{\emph{TODO: #1}}}
% Befehl für Entwürfe und grobe Pläne
\newenvironment{draft}{\par\color{orange}\begin{center}Entwurf / Konzept\end{center}\hrule}{\hrule\par}
2016-04-22 14:12:28 +02:00
2016-05-02 11:33:18 +02:00
% Broken citation needs broken command
\newcommand\mathplus{+}
2016-03-07 12:17:22 +01:00
% Festlegung Kopf- und Fußzeile
\defpagestyle{meinstil}{%
2016-03-07 12:46:38 +01:00
{\headmark \hfill}
{\hfill \headmark}
{\hfill \headmark\hfill}
(\textwidth,.4pt)
2016-03-07 12:17:22 +01:00
}{%
(\textwidth,.4pt)
{\pagemark\hfill Jan Philipp Timme}
2016-08-29 18:28:39 +02:00
{Version 0.4 vom \today \hfill \pagemark}
{Version 0.4 vom \today \hfill \pagemark}
2016-03-07 12:17:22 +01:00
}
\pagestyle{meinstil}
2016-03-07 12:17:22 +01:00
\raggedbottom
2016-03-07 12:17:22 +01:00
\renewcommand{\topfraction}{1}
\renewcommand{\bottomfraction}{1}
2016-07-14 21:52:05 +02:00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Beginn des Dokuments (Titelseite und der ganze Krempel)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016-03-07 12:46:38 +01:00
\begin{document}
% Titelseite
\thispagestyle{empty}
2016-03-07 12:46:38 +01:00
\includegraphics[width=0.2\textwidth]{res/Wortmarke_WI_schwarz.pdf}
{ ~ \sffamily
2016-03-07 12:46:38 +01:00
\vfill
2016-09-27 12:37:34 +02:00
{\Huge\bfseries Complex Event Processing auf RDF-Da\-ten\-strö\-men mit C-SPARQL}
\bigskip
{\Large Jan Philipp Timme
\\[2ex]
Bachelor-Arbeit im Studiengang "`Angewandte Informatik"'
\\[5ex]
\today
}
2016-03-07 12:17:22 +01:00
}
2016-03-07 12:46:38 +01:00
\vfill
~ \hfill
\includegraphics[height=0.3\paperheight]{res/H_WI_Pantone1665.pdf}
2016-03-07 12:17:22 +01:00
\vspace*{-3cm}
% Seite mit Personen und Selbstständigkeitserklärung
2016-03-07 12:46:38 +01:00
\newpage \thispagestyle{empty}
\begin{tabular}{ll}
2016-03-07 12:17:22 +01:00
{\bfseries\sffamily Autor} & Jan Philipp Timme \\
2016-09-12 14:58:45 +02:00
& Matrikelnummer 1271449 \\
& jan-philipp.timme@stud.hs-hannover.de \\[5ex]
2016-05-02 11:16:16 +02:00
{\bfseries\sffamily Erstprüfer} & Prof. Dr. Jürgen Dunkel \\
& Abteilung Informatik, Fakultät IV \\
& Hochschule Hannover \\
& juergen.dunkel@hs-hannover.de \\[5ex]
2016-08-22 15:31:50 +02:00
{\bfseries\sffamily Zweitprüfer} & Jeremias Dötterl, M. Sc. \\
& Abteilung Informatik, Fakultät IV \\
& Hochschule Hannover \\
2016-08-06 14:44:56 +02:00
& jeremias.doetterl@hs-hannover.de
2016-03-07 12:17:22 +01:00
\end{tabular}
\vfill
2016-03-07 12:46:38 +01:00
% fett und zentriert in der Minipage
\begin{center} \sffamily\bfseries Selbständigkeitserklärung \end{center}
2016-03-07 12:17:22 +01:00
Hiermit erkläre ich, dass ich die eingereichte Bachelor-Arbeit
selbständig und ohne fremde Hilfe verfasst, andere als die von mir angegebenen Quellen
und Hilfsmittel nicht benutzt und die den benutzten Werken wörtlich oder
inhaltlich entnommenen Stellen als solche kenntlich gemacht habe.
\vspace*{7ex}
Hannover, den \today \hfill Unterschrift
2016-03-07 12:46:38 +01:00
\pdfbookmark[0]{Inhalt}{contents}
% Inhaltsverzeichnis
\tableofcontents
2016-09-27 12:51:03 +02:00
% Abbildungsverzeichnis
2016-09-27 12:51:03 +02:00
%\listoffigures
2016-04-05 08:29:43 +02:00
% Codeverzeichnis
2016-09-27 12:51:03 +02:00
% \lstlistoflistings
% Tabellenverzeichnis
2016-09-27 12:51:03 +02:00
%\listoftables
2016-03-07 12:17:22 +01:00
\newpage
2016-03-07 12:17:22 +01:00
2016-07-14 21:52:05 +02:00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Hier geht es richtig los mit dem Text!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2016-03-07 12:46:38 +01:00
2016-08-23 15:21:09 +02:00
\chapter{Motivation}\label{cpt:motivation}
2016-09-13 19:34:15 +02:00
Mit der fortschreitenden Digitalisierung von Alltagsgegenständen und ihrer Verbindung mit dem Internet wächst das sogenannte Internet of Things. Dadurch sind auch immer mehr offene Systeme online verfügbar, die ihre Sensordaten und Zustandsinformationen als \emph{RDF}\footnote{Resource Description Framework --- Mehr dazu in Kapitel \ref{cpt:basics}}-Datenstrom anbieten. Diese Ereignisdatenströme liefern durchgehend und hochfrequent Ereignisdaten, sodass innerhalb kurzer Zeit sehr große Datenmengen anfallen, die zwecks Extraktion von Informationen und Auslösen von Reaktionen in kürzester Zeit verarbeitet werden sollen.
2016-08-24 17:17:38 +02:00
2016-08-31 20:13:58 +02:00
Die Ereignisdaten aus diesen Strömen bilden kleine Teile der Realität zumindest nä\-herungs\-wei\-se über die in ihnen enthalten Messdaten und Zustandsinformationen ab, sofern sie nicht bedingt durch technischen Defekt oder Messfehler ungültige Daten enthalten und somit vor der weiteren Verarbeitung herausgefiltert werden sollten. Ein weiteres Problem ist die stark begrenzte Gültigkeit von Ereignisdaten: Oft werden sie schon durch ein neu aufgetretenes Ereignis hinfällig und sind nicht mehr aktuell.
2016-05-03 17:05:04 +02:00
2016-09-13 19:34:15 +02:00
Ereignisse haben für sich alleine betrachtet neben einer begrenzten Gültigkeit eine begrenzte Aussagekraft, daher ist es zum höheren Verständnis der dahinter verborgenen Situation notwendig, sie mit zuvor aufgetretenen Ereignissen in einen Kontext zu setzen. Dadurch können mehrere kleine, hochfrequent auftretende Ereignisse zu einzelnen, niederfrequent auftretenden komplexen Ereignissen aggregiert werden und mittels Mustererkennung höherwertige Informationen aus den Ereignissen extrahiert werden. In Abbildung~\ref{fig:aggregation_patternmatching} wird die Aggregation von Ereignissen sowie die Mustererkennung exemplarisch dargestellt.
2016-07-15 16:02:15 +02:00
2016-09-13 19:34:15 +02:00
Die Integration von \emph{Domänenwissen}\footnote{Hintergrundwissen für den Kontext der Ereignisverarbeitung, verändert sich während der Verarbeitung nur selten} ist ein weiterer Schritt, der die Brücke zwischen den aus komplexen Ereignissen gewonnenen Kenntnissen und bereits bekannten Fakten schlagen soll, um die gewonnenen Kenntnisse in einen eindeutigen Zusammenhang stellen und eine eindeutige Interpretation zu ermöglichen.
Um unter diesen Bedingungen viele Ereignisdatenströme mit hochfrequenten Ereignissen in nahezu Echtzeit zu verarbeiten ist \emph{CEP}\footnote{Complex-Event-Processing} das Mittel der Wahl: Mit CEP werden die Ereignisse der verschiedenen Datenströme für begrenzte Zeiträume im Speicher vorgehalten und innerhalb von sogenannten \emph{Sliding-Windows}\footnote{Mehr dazu in Kapitel~\ref{cpt:cep_intro}} betrachtet. Dabei können Ereignismuster erkannt werden und verschiedene Ereignisse aggregiert werden um neue komplexe Ereignisse zu erzeugen.
2016-09-08 12:02:43 +02:00
Ziel dieser Arbeit ist die Einführung in die Konzepte von CEP und RDF, sowie die Demonstration der praktischen Nutzung der CEP-Engine \enquote{C-SPARQL} zur Verarbeitung von RDF-Datenströmen am Beispiel einer Autoverleihgesellschaft zur Überwachung von Leihfahrzeugen. Auch soll ergründet werden, welche technischen Möglichkeiten existieren, um \emph{Reasoning} auf RDF-Datenströmen zu betreiben --- ein Prozess, durch den eine vorhandene Sammlung von Fakten auf Basis von vorgegebener Terminologie automatisch um daraus ableitbarem Wissen angereichert werden kann.
2016-08-23 16:22:12 +02:00
Diesbezüglich soll ergründet werden, welche CEP-Engines Reasoning bereits implementieren und wie weit ihre technischen Möglichkeiten reichen --- eine große Herausforderung, da die mit einzubeziehenden Ereignisdaten sich kontinuierlich verändern.
2016-07-18 18:30:38 +02:00
2016-07-22 15:36:11 +02:00
2016-08-17 11:51:16 +02:00
\section{Szenario}\label{cpt:scenario}
2016-09-05 13:23:12 +02:00
Das Beispielszenario, welches für diese Arbeit verwendet wird, ist eine Autoverleihgesellschaft, die ihren Fuhrpark überwachen möchte, um ihren Kunden vergünstigte Tarife für verschleißarmes Fahrverhalten anbieten zu können. Weiterhin soll auf plötzlich auftretende Probleme an den Leihwagen möglichst schnell reagiert werden können um Schäden zu begrenzen, gefährliche Situationen zu vermeiden und bei Bedarf dem Kunden unverzüglich einen Ersatzwagen oder weitere Serviceleistungen anbieten zu können.
2016-07-22 15:36:11 +02:00
2016-09-05 13:23:12 +02:00
\paragraph{Anforderungen}
Um die Ziele der Autoverleihgesellschaft erreichen zu können, sollen folgende Situationen erkannt werden:
\begin{itemize}
2016-09-06 15:02:48 +02:00
\item Starker Verschleiß eines Fahrzeugs durch unsachgemäßes Fahrverhalten
\item Wartungsbedarf am Fahrzeug, wie beispielsweise:
2016-09-05 13:23:12 +02:00
\begin{itemize}
\item Schäden an den Reifen
2016-09-06 15:02:48 +02:00
\item Vom Fahrzeug selbst erkannte Probleme
2016-09-05 13:23:12 +02:00
\end{itemize}
\item Eintritt eines Unfalls
\item Unbeabsichtigtes Wegrollen von abgestellten Fahrzeugen
\end{itemize}
2016-09-21 11:53:03 +02:00
Um diese Situationen zu erkennen, sollen zwei RDF-Ereignisdatenströme zur späteren Verarbeitung eingerichtet werden und eine Sammlung von Fakten in lokalem Do\-\-nen\-wis\-sen modelliert werden. Diese werden im Folgenden vorerst nur grob beschrieben.
2016-08-04 17:40:29 +02:00
2016-09-05 16:36:18 +02:00
\paragraph{Statusdatenstrom der PKW}
2016-09-06 15:02:48 +02:00
Über diesen Datenstrom sollen die einzelnen PKW kontinuierlich ihre Statuswerte melden:
2016-08-08 18:51:14 +02:00
\begin{itemize}
2016-09-05 16:36:18 +02:00
\item PKW verschlossen (ja/nein)
2016-08-29 13:46:01 +02:00
\item Status des Motors (an/aus)
2016-08-17 11:42:57 +02:00
\item Status der Handbremse (angezogen/gelöst)
\item Momentangeschwindigkeit in km/h
\item Drehzahl des Motors
\item Reifendrücke der Reifen in bar
2016-08-08 18:51:14 +02:00
\end{itemize}
2016-09-06 15:02:48 +02:00
Besonders wichtige Ereignisse, wie das Aufleuchten der Motorkontrollleuchte oder das Auslösen des Airbags, sollen über diesen Datenstrom separat von den Statusdaten gemeldet werden.
2016-08-08 18:51:14 +02:00
2016-08-18 10:27:32 +02:00
\paragraph{Interaktionsstrom der Kunden}
2016-09-06 15:02:48 +02:00
Wird einem Kunden ein PKW zugewiesen oder gibt ein Kunde einen geliehenen PKW wieder zurück, so soll hierfür ein Ereignis in diesen Datenstrom eingespeist werden. Diese Ereignisse sollen immer die eindeutige Kundennummer und die Nummer des geliehenen Fahrzeugs enthalten, um eine eindeutige Zuordnung vornehmen zu können.
2016-08-08 18:51:14 +02:00
2016-08-17 11:42:57 +02:00
\paragraph{Domänenwissen}
2016-09-21 11:53:03 +02:00
Um die Ereignisdaten aus den beiden beschriebenen Datenströmen bei der Verarbeitung in einen eindeutigen Kontext setzen zu können, wird lokal ver\-füg\-ba\-res Hintergrundwissen benötigt. Es soll die Zuordnung von Kunden zu den von ihnen geliehenen PKW aufbauen, die einzelnen PKW konkreten Automodellen zuordnen und somit eine konkrete Interpretation der von den PKW gemeldeten Daten ermöglichen.
2016-08-29 13:46:01 +02:00
2016-09-06 15:02:48 +02:00
Das Domänenwissen soll in diesem Szenario folgende Informationen enthalten:
2016-08-08 18:51:14 +02:00
\begin{itemize}
2016-08-18 10:27:32 +02:00
\item Eindeutige Zuordnung von Kundennummer zu einem Kunden
\item Kundendaten wie Name und Telefonnummer
2016-08-17 11:42:57 +02:00
\item Eindeutige Zuordnung von Fahrzeugnummer zu Automodell
2016-08-29 13:46:01 +02:00
\item Wissen über Automodelle:
2016-08-17 11:42:57 +02:00
\begin{itemize}
\item Empfohlene Motordrehzahlbereiche für verschleißarmes Fahren
\item Vorgeschriebener Reifendruck
\end{itemize}
2016-08-08 18:51:14 +02:00
\end{itemize}
2016-08-04 17:40:29 +02:00
2016-09-21 11:53:03 +02:00
\todo{GRAFIK: Grobes Informationsnetzwerk zur Veranschaulichung der Zu\-sam\-men\-hän\-ge zwischen den drei Elementen (Ströme + Hintergrundwissen).}
2016-09-05 13:23:12 +02:00
2016-08-04 17:40:29 +02:00
2016-09-06 15:02:48 +02:00
\chapter{Grundlagen}\label{cpt:basics}
Nachdem in Kapitel~\ref{cpt:motivation} das Vorhaben dieser Arbeit grob beschrieben wurde, folgt nun eine Einführung in die dafür benötigten Grundlagen. Da die später zu verarbeitenden Ereignisdatenströme im RDF-Format vorliegen werden, soll zunächst eine Einführung in das semantische Web zeigen, wie RDF zur Modellierung und Beschreibung von Wissen eingesetzt werden kann, und welche Möglichkeiten dadurch geboten werden. Anschließend sollen die grundlegenden Konzepte von CEP erläutert mit Hinblick auf die Verarbeitung von RDF-Datenströmen erläutert werden.
2016-08-04 17:40:29 +02:00
2016-07-15 15:10:19 +02:00
2016-09-06 15:02:48 +02:00
\section{Einführung: RDF im semantischen Web}
Das sogenannte \enquote{semantische Web} ist ein großes Anwendungsgebiet für RDF-Daten und deren Verlinkung. In diesem Abschnitt soll erläutert werden, was RDF ist, wofür es eingesetzt wird, und wie man in RDF vorliegende Daten verwenden und weiter verarbeiten kann.
2016-08-23 19:14:03 +02:00
2016-08-17 11:51:16 +02:00
\subsection{RDF im semantischen Web}\label{cpt:rdf-semantic-web}
2016-09-06 15:02:48 +02:00
Das Resource Description Framework (RDF) wird im semantischen Web zur Modellierung und Repräsentation von Wissen verwendet. RDF-Daten bestehen aus einer Menge von Tripeln, welche sich aus den drei Komponenten Subjekt, Prädikat und Objekt in genau dieser Abfolge zusammensetzen um eine Aussage zu formen. Jeder dieser drei Bestandteile eines Tripels kann durch einen eindeutigen Uniform Resource Identifier (URI\footnote{Der URI wird in RFC 3986 beschrieben. Anstelle eines URI kann auch ein IRI (Internationalized Resource Identifier) verwendet werden --- die internationalisierte Form des URI nach RFC 3987.}) identifiziert werden. Lediglich in der Position \enquote{Objekt} eines Tripels kommen auch sehr häufig sogenannte \emph{Literale} vor um konkrete Datenwerte beispielsweise in Form von Zeichenketten oder Ganzzahlen zu repräsentieren.
2016-08-29 13:46:01 +02:00
\begin{lstlisting}[caption={Ein RDF-Tripel},label={lst:sample_rdf_triple}]
2016-08-18 11:23:49 +02:00
<http://example.org/carSim/objects/Car#23> <http://example.org/carSim/carSimulationOntology#isCarModel> <http://example.org/carSim/objects/CarModel#42> .
\end{lstlisting}
2016-08-23 16:06:15 +02:00
2016-09-27 22:25:16 +02:00
Das in Listing~\ref{lst:sample_rdf_triple} enthaltene Tripel ordnet das Car-Subjekt \texttt{\#23} über das Prädikat \texttt{isCarModel} dem Objekt CarModell \texttt{\#42} zu. Abbildung~\ref{fig:triple_spo} illustriert neben diesem Tripel auch die Verknüpfung des Car-Subjektes über das Prädikat \texttt{hasNickname} zu dem Literalwert \enquote{Alf}.
2016-08-29 13:46:01 +02:00
2016-09-27 22:25:16 +02:00
\begin{figure}[htbp]
\centering
\includegraphics[width=\textwidth]{img/triple-spo.pdf}
\caption{Prädikate verknüpfen ein Subjekt mit Objekt und Literalwert}
\label{fig:triple_spo}
\end{figure}
2016-08-29 15:29:27 +02:00
2016-08-29 13:46:01 +02:00
\paragraph{Turtle-Notation mit Prefixen}
2016-09-08 16:53:18 +02:00
Wie anhand des Beispiels aus Listing~\ref{lst:sample_rdf_triple} erkennbar ist, ist die explizite Notation für Tripel aufgrund der häufigen Nennung von vollständigen URIs wenig platzsparend und für große Datenmengen somit nicht empfehlenswert. Da es neben XML noch andere Repräsentationsformate für RDF-Daten gibt, bietet sich die Nutzung einer Notation an, die eine Nutzung von Prefixen erlaubt. Nach einer einmaligen Definition innerhalb eines Kontextes (zum Beispiel einer Datei) können diese Prefixe dann für den gesamten Kontext verwendet werden und verringern somit erheblich den Bedarf an Speicherplatz.
2016-08-23 16:06:15 +02:00
Listing~\ref{lst:sample_rdf_triple_with_prefix} zeigt die Notation von Tripeln im Turtle\footnote{Siehe auch die Spezifikation der Turtle-Notation nach \cite{w3c:turtle}}-Format unter Verwendung von Prefixen.
2016-08-29 17:43:02 +02:00
\begin{lstlisting}[caption={Das Tripel aus Listing~\ref{lst:sample_rdf_triple} mit Prefixen},label={lst:sample_rdf_triple_with_prefix}]
2016-08-18 11:23:49 +02:00
@prefix car: <http://example.org/carSim/objects/Car#> .
@prefix carModel: <http://example.org/carSim/objects/CarModel#> .
2016-08-23 16:06:15 +02:00
@prefix carOnt: <http://example.org/carSim/carSimulationOntology#> .
2016-08-18 11:23:49 +02:00
2016-08-23 16:06:15 +02:00
car:23 carOnt:isCarModel carModel:42 .
2016-08-18 11:23:49 +02:00
\end{lstlisting}
2016-08-18 14:21:05 +02:00
Aufgrund der Flexibilität dieser Struktur ist es möglich, nahezu jede Art von Informationen auf Tripel abzubilden, wie Listing~\ref{lst:sample_rdf_data} an einem Beispiel zeigt.
2016-09-05 16:36:18 +02:00
\begin{lstlisting}[caption={RDF-Daten beschreiben einen Fahrer, ein PKW und dessen Modell},label={lst:sample_rdf_data}]
2016-08-29 13:46:01 +02:00
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
2016-08-23 19:14:03 +02:00
@prefix car: <http://example.org/carSim/objects/Car#> .
@prefix carModel: <http://example.org/carSim/objects/CarModel#> .
2016-08-29 13:46:01 +02:00
@prefix driver: <http://example.org/carSim/objects/Driver#> .
2016-08-23 19:14:03 +02:00
@prefix carOnt: <http://example.org/carSim/carSimulationOntology#> .
2016-08-29 13:46:01 +02:00
car:0 rdf:type carOnt:Car .
car:0 carOnt:isCarModel carModel:0 .
carModel:0 rdf:type carOnt:CarModel .
carModel:0 carOnt:minimumMotorRPM 2000 .
carModel:0 carOnt:maximumMotorRPM 4300 .
carModel:0 carOnt:minimumTirePressure 2.9 .
carModel:0 carOnt:maximumTirePressure 3.2 .
carModel:0 carOnt:requiresDriverLicense "B"^^xsd:string
2016-07-19 11:54:50 +02:00
2016-08-29 13:46:01 +02:00
driver:0 rdf:type carOnt:Driver .
driver:0 carOnt:hasName "Max Mustermann"^^xsd:string .
driver:0 carOnt:hasPhoneNumber "+49 111 123456789"^^xsd:string .
driver:0 carOnt:hasDriverLicense "B"^^xsd:string .
2016-07-19 11:54:50 +02:00
2016-08-29 13:46:01 +02:00
car:0 carOnt:isDrivenBy driver:0 .
driver:0 carOnt:drives car:0
2016-07-19 11:54:50 +02:00
\end{lstlisting}
2016-08-29 13:46:01 +02:00
2016-09-08 16:59:09 +02:00
\paragraph{Objektklassen und -instanzen}
2016-09-13 11:13:10 +02:00
In RDF kann ein Subjekt grundsätzlich eine Instanz von mehreren Objektklassen sein. Um anzugeben, von welcher Objektklasse ein Tripel-Subjekt eine Instanz ist, wird das Prädikat \texttt{rdf:type} verwendet. Synonym dazu kann anstelle von \texttt{rdf:type} auch das Prädikat \texttt{a} verwendet werden, wie Listing~\ref{lst:sample_rdf_a_predicate} zeigt.
\begin{lstlisting}[caption={Das Prädikat \texttt{a} ist synonym zu \texttt{rdf:type}},label={lst:sample_rdf_a_predicate}]
@prefix car: <http://example.org/carSim/objects/Car#> .
@prefix carOnt: <http://example.org/carSim/carSimulationOntology#> .
car:0 a carOnt:Car .
\end{lstlisting}
Abhängig von den Objektklassen eines Subjektes können Ontologien nun einschränken, wie eine Objektinstanz mit anderen Objektinstanzen oder Werten verbunden werden darf. So kann beispielsweise definiert werden, dass das Prädikat \texttt{carOnt:drives} als Subjekt nur Instanzen der Klasse \texttt{carOnt:Driver} und als Objekt nur Instanzen der Klasse \texttt{carOnt:Car} zulässt, da die umgekehrte Richtung nicht sinnvoll wäre.
2016-09-08 16:59:09 +02:00
2016-08-29 18:21:04 +02:00
\paragraph{Graphen}
Da innerhalb des semantischen Web angestrebt wird, in RDF vorliegende Informationen gemeinsam zu nutzen und miteinander zu vernetzen zu können, werden RDF-Tripel meist als Quadrupel (oder kurz \enquote{Quad}) gehandhabt, in denen als zusätzliche Information der sogenannte Graph genannt wird, in dem die Tripel enthalten sind. Ein Graph wird durch eine URI identifiziert und dient als Namensraum für die Tripel, die er enthält. Dies vereinfacht die gleichzeitige Nutzung von mehreren Datenquellen, da jedes Tripel eindeutig einem Graphen zugeordnet werden kann und innerhalb von Abfragen spezifisch Tripel aus verschiedenen Graphen selektiert werden können.
\todo{GRAFIK: Verbildlichung durch mehrere mit URI gekennzeichneten Container, die ein paar Tripel enthalten, die aufeinander verweisen.}
2016-08-29 15:29:27 +02:00
2016-09-08 12:31:19 +02:00
\paragraph{RDF-Schema für einfache Ontologien}
2016-09-21 11:53:03 +02:00
Das \enquote{RDF-Schema} (kurz RDFS\footnote{Für eine detailreiche Einführung in RDFS siehe auch \cite{hitzler:semanticweb}[Kapitel 3.4]}) dient zur Spezifikation von Schemawissen durch die Definition von Objektklassen und Prädikaten, welche in hierarchischen Verhältnissen zueinander stehen können\footnote{Mittels \texttt{rdfs:subclassOf} und \texttt{rdfs:subpropertyOf} können hierarchische Verhältnisse zwischen verschiedene Properties beziehungsweise Objektklassen definiert werden.}. Betrachtet man beispielsweise die Daten aus Listing~\ref{lst:sample_rdf_data}, so ist in diesem Kontext für die Verwendung des Prädikats \texttt{carOnt:drives} offensichtlich, dass es nur zusammen mit einem Subjekt der Klasse \texttt{Driver} und einem Objekt der Klasse \texttt{Car} verwendet werden sollte um eine sinnvolle Aussage zu ergeben. Eine solche Regel kann mit Hilfe von RDFS definiert werden, wie Listing~\ref{lst:sample_rdfs_data} zeigt.
2016-08-29 17:43:02 +02:00
\begin{lstlisting}[caption={Definition der Klassen \texttt{Car} und \texttt{Driver} sowie des Prädikats \texttt{drives} in RDFS},label={lst:sample_rdfs_data}]
2016-08-29 17:22:12 +02:00
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix carOnt: <http://example.org/carSim/carSimulationOntology#> .
carOnt:Car rdf:type rdfs:class .
carOnt:Driver rdf:type rdfs:class .
carOnt:drives rdf:type rdf:Property .
carOnt:drives rdfs:domain carOnt:Driver .
carOnt:drives rdfs:range carOnt:Car .
\end{lstlisting}
2016-08-29 17:43:02 +02:00
In Listing~\ref{lst:sample_rdfs_data} werden zunächst die beiden Klassen \texttt{carOnt:car} und \texttt{carOnt:Driver} definiert. Im darauf folgenden Absatz wird dann das Merkmal \texttt{carOnt:drives} definiert und über \texttt{rdfs:domain} auf Subjekte der Klasse \texttt{Driver} und mit \texttt{rdfs:range} auf Objekte der Klasse \texttt{Car} eingeschränkt. Trifft man in diesem Kontext nun Tripel mit einem Prädikat \texttt{carOnt:drives} an, so kann man anhand der zugehörigen RDFS-Daten bereits erkennen, womit man es zutun hat.
2016-08-29 15:29:27 +02:00
2016-08-29 18:21:04 +02:00
\paragraph{OWL-Ontologien}
2016-09-27 12:46:12 +02:00
\todo{Mehr Inhalt! Das ist so zu wenig!}
2016-09-27 12:37:34 +02:00
In OWL (Web Ontology Language) formulierte Ontologien werden im semantischen Web neben RDF-Schemata sehr häufig zur Strukturierung von RDF-Daten verwendet. Ähnlich wie RDFS definieren OWL-Ontologien ein Vokabular mit logischen Do\-\-nen\-objekt\-klas\-sen und bestimmt für diese Objektklassen Prädikate und Attribute, um bestimmte Sachverhalte eindeutig abbilden zu können. Allerdings bietet OWL mächtigere Sprachkonstrukte, um feiner granulare Regeln für Objektklassen und Attribute aufzustellen. Eine Ontologie für Listing~\ref{lst:sample_rdf_data} könnte beispielsweise eine Objektklasse \texttt{Driver} definieren, auf welche das eigens hierfür definierte Prädikat \texttt{hasName} mit einem Attribut vom Typ \texttt{xsd:string} angewandt werden kann. Durch die Möglichkeiten dieser Restriktionen können RDF-Daten aus der Welt einer Ontologie --- ähnlich wie bei einem relationalen Datenbankschema --- eindeutig auf inhaltlicher Ebene strukturiert werden.
2016-07-28 10:25:24 +02:00
2016-09-13 11:13:10 +02:00
\paragraph{ABox und TBox}
Bei der Modellierung von Wissen mit Hilfe von Beschreibungslogiken, zu denen auch OWL und RDFS zählen, werden die formulierten Aussagen in zwei Gruppen unterteilt\cite{hitzler:semanticweb}[Kapitel 6.1]: Die Assertion Box (ABox) und die Terminology Box (TBox). Während die TBox Aussagen mit terminologischem Schemawissen wie Definitionen von Objektklassen, Prädikaten und ihren Verhältnissen zueinander enthält, beinhaltet die ABox sogenanntes \emph{assertionales Instanzwissen}\cite{hitzler:semanticweb}[Kapitel 6.1], welches aus Aussagen über konkrete Klasseninstanzen und deren Merkmale und Beziehungen besteht. In diesen Aussagen der ABox wird dabei das in der TBox definierte Vokabular genutzt.
Ein Beispiel für eine TBox ist Listing~\ref{lst:sample_rdfs_data}, in welcher Objektklassen definiert werden, die innerhalb der ABox aus Listing~\ref{lst:sample_rdf_data} verwendet werden, um konkrete Instanzen dieser Objektklassen zu beschreiben.
\todo{GRAFIK: Ein wenig visualisiertes Wissen, welches TBox und ABox-Inhalte getrennt voneinander darstellt. (Eine Ebene mit Klassen und Attributen, eine andere Ebene mit konkreten Klasseninstanzen und deren Merkmalen)}
2016-09-08 16:53:18 +02:00
\paragraph{Kombination verschiedener Ontologien}
2016-09-08 12:31:19 +02:00
Natürlich ist es möglich, mehrere verschiedene Ontologien gleichzeitig zu verwenden. Diese Flexibilität ermöglicht beispielsweise, dass eine bereits in RDF abgebildete Person durch beliebige Informationen über Vokabular aus weiteren Ontologien ergänzt werden kann. Natürlich können die Informationen einer in RDF abgebildeten Person auch in verschiedenen, für andere Parteien geläufigen Strukturen verfügbar gemacht werden können. Innerhalb einer Ontologie auf die Objektklassen und Attribute zurückgegriffen werden, die in anderen Ontologien definiert werden. Dies ermöglicht neben Erweiterungen für spezifische Zwecke auch das Übersetzen von Wissen zwischen verschiedenen Ontologien durch die Definition von äquivalenten Objektklassen und Attributen.
2016-07-28 10:25:24 +02:00
2016-09-08 12:31:19 +02:00
\paragraph{Open World Assumption}
Sollte es nötig sein, für eigene Terminologie eine Ontologie zu erzeugen, so ist es wichtig hervorzuheben, dass für in RDF abgebildete Fakten nahezu immer die Annahme gilt, dass diese Daten nicht vollständig sind und somit nicht alle realen Fakten auch in RDF erfasst sind. Die meisten existierenden Ontologien respektieren diese Annahme und verzichten auf die Definition von expliziten Regeln, die über die konkrete Bedeutung der Abwesenheit von bestimmten Fakten entscheiden würden. (In der Welt der relationalen Datenbanksysteme gibt es eine ähnliche Problematik in Zusammenhang mit der Verwendung des Schlüsselworts \texttt{NULL}.)
2016-07-27 12:55:00 +02:00
2016-07-27 14:49:27 +02:00
2016-09-13 10:05:13 +02:00
\subsection{Anreicherung von RDF-Daten durch Reasoning}\label{cpt:reasoning}
2016-09-13 13:22:08 +02:00
Durch den Einsatz von Terminologiewissen in Form von OWL-Ontologien oder RDF-Schemata ergibt sich die Möglichkeit, die Fakten aus der ABox automatisch um über die Terminologie abgeleitetes Wissen anzureichern. Diesen Prozess bezeichnet man als \emph{Reasoning}.
2016-09-13 10:05:13 +02:00
2016-09-27 12:46:12 +02:00
\todo{Reasoning anhand von RDFS-TBox erklären: transitive und symmetrische Attribute sind leichter zu greifen!}
2016-09-13 10:05:13 +02:00
In diesem Prozess werden aus den in RDF vorliegenden Fakten (Assertion Box) und den in den verwendeten Ontologien definierten Objektklassen, Regeln und Zusammenhängen (Terminology Box) neues Wissen abgeleitet \cite{hitzler:semanticweb} und die lokale Datenbasis damit angereichert. So können beispielsweise implizite Klassentypen errechnet werden (\enquote{Ein PKW ist auch ein Fahrzeug}), oder regelbasierte Zugehörigkeiten zu Objektklassen ermittelt werden: Die Aussagen \enquote{Der PKW x rollt.} und \enquote{Der PKW x ist verriegelt.} können zu der Folgerung \enquote{Der PKW x ist eine Gefahrenquelle.} führen.
2016-09-27 12:46:12 +02:00
\todo{Beispiel zu komplex, muss ersetzt werden!}
2016-09-13 10:05:13 +02:00
2016-09-13 13:22:08 +02:00
Enthält eine Ontologie strukturelle Informationen über Fahrer, PKW und Attribute bezüglich technischer Daten über PKW-Modelle, so ist es beispielsweise möglich auf Basis der Fakten aus Listing~\ref{lst:sample_rdf_data} zusätzliche Attribute der Fahrer wie \enquote{isDrivingCarModel} oder der PKW wie \enquote{hasEmergencyContactNumber} zu errechnen. Dieses funktioniert natürlich nur, falls in den Fakten bekannt ist, dass ein Fahrer ein Fahrzeug fährt und somit zu diesem Fahrzeug verbunden ist. Limitiert werden die Möglichkeiten des Reasoning ebenfalls durch die \emph{Open World Assumption} (OWA), also die Annahme einer offenen Welt, über die nur \emph{unvollständiges Wissen} vorliegt. Deshalb sollten für Reasoning nur explizit bekannte Fakten genutzt werden: Nur weil in Listing~\ref{lst:sample_rdf_data} keine Informationen über weitere PKW oder Fahrer vorhanden sind heißt das nicht, dass diese nicht existieren oder Einfluss auf die bekannten Fakten haben könnten. Weiterführende Beispiele zu den Möglichkeiten von OWL Reasoning finden sich unter \cite{man:owl}.
2016-09-13 10:05:13 +02:00
Da Ontologien auch genutzt werden können, um Wissen aus den Strukturen einer Ontologie in die Struktur einer anderen Ontologie zu übersetzen, kann ein Reasoner die daraus resultierende Übersetzung direkt errechnen und der lokalen Datenbasis hinzufügen. Dadurch steht Abfragen, die schon auf die Ziel-Ontologie zugeschnitten sind, ein viel größerer Informationspool zur Verfügung, aus dem das Abfrageergebnis berechnet werden soll.
Die Vorteile von Reasoning erkauft man sich durch einen nicht unerheblichen Einsatz von Rechenleistung, da im Prozess des Reasoning eine Menge von zusätzlichen Daten entsteht, für die zusätzlich zu den bereits vorhandenen Daten die Regeln aller genutzten Ontologien berücksichtigt werden müssen. Behandelt man lediglich statische Daten, die sich kaum bis garnicht ändern, so ist der nötige Aufwand für Reasoning übersichtlich und liegt auch für große Mengen von Daten und Ontologien in einem akzeptablem Rahmen. Ändern sich jedoch häufig Daten, so muss für das Subset der veränderten Daten der Reasoning-Prozess erneut durchgeführt werden um eine vollständig aktuelle Datenbasis zu erhalten.
2016-08-30 14:06:34 +02:00
2016-07-27 12:55:00 +02:00
2016-09-06 17:17:01 +02:00
\subsection{Abfrage von RDF-Daten via SPARQL}\label{cpt:rdf-sparql}
2016-09-06 15:02:48 +02:00
Die Abfrage von Wissen aus RDF-Daten erfolgt über die Abfragesprache \emph{SPARQL} (\enquote{SPARQL Protocol And RDF Query Language}), welche in diesem Abschnitt grob erläutert wird. Eine detaillierte Beschreibung von SPARQL ist unter \cite{w3c:sparql} nachzulesen.
2016-07-27 12:55:00 +02:00
2016-09-06 15:02:48 +02:00
Im Gegensatz zu Abfragesprachen von relationalen Datenbanksystemen wie SQL ist es mit SPARQL möglich, Daten über verschiedene Datenquellen wie Tripel- oder Quadstores\footnote{Analog zu relationalen Datenbanksystemen für Relationen ein Speicher für RDF-Tripel beziehungsweise RDF-Quads} hinweg miteinander zu verknüpfen. Auch ist im Gegensatz zu SQL keine spezielle Anpassung der Abfragen an ein Datenbankschema notwendig; lediglich die Art und Weise, wie die angeforderten Daten miteinander in Verbindung stehen, ist für SPARQL-Abfragen wichtig. Kenntnisse über das verwendete Vokabular (RDF-Schema oder OWL-Ontologien) können jedoch bei der Formulierung der Abfragen hilfreich sein. Im Folgenden zeigt Listing~\ref{lst:sample_sparql_query} eine einfache Abfrage auf den Daten aus Listing~\ref{lst:sample_rdf_data}.
\begin{lstlisting}[caption={Abfrage der maximal zulässigen Motordrehzahl des Auto-Subjektes Nr. 0 aus Daten von Listing~\ref{lst:sample_rdf_data}},label={lst:sample_sparql_query}]
PREFIX carOnt: <http://example.org/carSim/carSimulationOntology#>
PREFIX car: <http://example.org/carSim/objects/Car#>
2016-07-19 11:54:50 +02:00
2016-09-06 15:02:48 +02:00
SELECT ?maxMotorRPM
2016-07-19 11:54:50 +02:00
WHERE {
2016-09-06 15:02:48 +02:00
car:0 carOnt:isCarModel ?carModel .
?carModel carOnt:maximumMotorRPM ?maxMotorRPM .
2016-07-19 11:54:50 +02:00
}
\end{lstlisting}
2016-09-06 15:02:48 +02:00
\paragraph{Selektion von Daten}
Listing~\ref{lst:sample_sparql_query} zeigt, dass SPARQL in der groben Grundstruktur eine Ähnlichkeit zu SQL aufweist; allerdings sind bedingt durch die Struktur der Daten (Relationen bei SQL gegenüber Tripel und Quadrupel bei SPARQL) große Unterschiede in der Gestaltung der Abfragen zu finden. Zunächst werden analog zur Turtle-Notation Prefixe notiert, die innerhalb der Abfrage verwendet werden sollen. In der \texttt{WHERE}-Klausel werden Tripel mit Platzhaltern verwendet, um aus dem vorhandenen Datenbestand die Tripel zu isolieren, die auf das angegebene Muster passen. So wird in diesem Beispiel zunächst ein Tripel gesucht, welches als Subjekt \texttt{car:0} gesetzt hat und das Prädikat \texttt{carOnt:isCarModel} verwendet, welches auf das zu dem Auto zugehörige Automodell-Subjekt zeigt. Ergibt sich ein Treffer, so wird der Objekt-Teil des gefundenen Tripels in den Platzhalter \texttt{?carModel} eingefügt und für die Suche des zweiten Tripels des SPARQL-Queries verwendet.
2016-07-19 11:54:50 +02:00
2016-09-06 15:02:48 +02:00
Für das gefundene \texttt{?carModel} wird nun ein Tripel gesucht, welches für \texttt{?carModel} das Prädikat \texttt{carOnt:maximumMotorRPM} nutzt, um die Angabe der maximalen Drehzahl für dieses Automodell zu definieren. Wird hierfür ebenfalls ein Treffer gelandet, so wird der Platzhalter \texttt{?maxMotorRPM} mit dem dazugehörigen Wert gefüllt und kann dann in der \texttt{SELECT}-Klausel selektiert werden. Für jede Tripelkombination, die auf die in der \texttt{WHERE}-Klausel formulierten Beschreibung passt, ergibt sich nun ein Ergebnis, für welches die in der \texttt{SELECT}-Klausel angegebenen Felder zurückgegeben werden --- in diesem Fall also lediglich ein Ergebnis mit dem Wert \enquote{4300}.
2016-07-29 10:58:45 +02:00
2016-09-06 15:02:48 +02:00
\paragraph{Konstruktion von Daten durch Abfragen}
2016-09-08 11:07:16 +02:00
Neben \texttt{SELECT} unterstützt SPARQL auch den Befehl \texttt{CONSTRUCT}. Dieses ermöglicht die direkte Konstruktion von neuen Tripeln aus vorgegebenen Tripeln mit Platzhaltern, welche mit den Ergebnissen der Abfrage gefüllt werden. Listing~\ref{lst:sample_sparql_construct} zeigt die beispielhafte Erzeugung von Tripeln auf Basis der Daten aus Listing~\ref{lst:sample_rdf_data}, welche über das Prädikat \texttt{carOnt:motorRPMTolerance} Auskunft über die Größe des akzeptablen Drehzahlbereiches der Automodelle geben sollen.
2016-09-06 15:17:45 +02:00
\begin{lstlisting}[caption={Konstruktion von neuen Tripeln auf Basis des Wissens aus Listing~\ref{lst:sample_rdf_data}},label={lst:sample_sparql_construct}]
PREFIX carOnt: <http://example.org/carSim/carSimulationOntology#>
PREFIX car: <http://example.org/carSim/objects/Car#>
2016-07-29 10:58:45 +02:00
CONSTRUCT {
2016-09-06 15:17:45 +02:00
?carModel carOnt:motorRPMTolerance ?rpmTolerance .
2016-07-29 10:58:45 +02:00
} WHERE {
2016-09-06 15:17:45 +02:00
?carModel rdf:type carOnt:CarModel .
?carModel carOnt:minimumMotorRPM ?minMotorRPM .
?carModel carOnt:maximumMotorRPM ?maxMotorRPM .
BIND(?maxMotorRPM - ?minMotorRPM AS ?rpmTolerance) .
2016-07-29 10:58:45 +02:00
}
\end{lstlisting}
2016-09-06 15:17:45 +02:00
Wie in Listing~\ref{lst:sample_sparql_construct} gezeigt, können einfache Operationen in SPARQL-Abfragen durchgeführt werden, deren Ergebnisse über die \texttt{BIND}-Anweisung in einen vorgegebenen Platzhalter \texttt{?rpmTolerance} eingesetzt werden. In diesem Beispiel wurde die Differenz zwischen der maximalen und der minimalen empfohlenen Motordrehzahl eines Automodells ausgerechnet und ein neues Tripel mit dieser Information generiert.
2016-07-29 10:16:32 +02:00
2016-07-27 17:03:44 +02:00
2016-09-02 14:41:05 +02:00
\section{Einführung in Complex Event Processing}\label{cpt:cep_intro}
2016-09-15 15:12:20 +02:00
Von Transaktionen im Handel über Messereignisse von Sensoren bis hin zu Benutzerinteraktionen auf Webseiten entstehen täglich eine Vielzahl von Ereignisdaten, die für einen begrenzten Zeitraum einen Teil der echten Welt abbilden. Um aus diesen großen Datenmengen durch Erkennung von Mustern oder durch Aggregation von Daten schnellstmöglich höherwertige Informationen gewinnen zu können, ist Complex Event Processing (CEP) das Mittel der Wahl. Wie der Begriff CEP bereits andeutet, geht es dabei um die Verarbeitung von komplexen Ereignissen. Im folgenden Abschnitt wird hierfür ein kurzer Einstieg in die Grundlagen von CEP gegeben. Für eine detailreiche Erläuterung und die beispielhafte Anwendung der CEP-Engine \enquote{Esper} sei auf \cite{hsh:cep} verwiesen.
\paragraph{CEP-Engine}
2016-09-27 14:38:43 +02:00
Um Complex Event Processing durchführen zu können, wird eine CEP-Engine benötigt. Eine CEP-Engine ist eine Software, welche Ereignisdatenströme konsumiert und diese durch die Auswertung benutzerdefinierter CEP-Regeln verarbeitet. Aufgrund der großen Datenvolumen, die eine CEP-Engine verarbeiten muss, werden Ereignisse nur für die Dauer der Verarbeitung\footnote{Dieser Parameter hängt meist von der Größe der verwendeten Sliding Windows ab.} im Speicher gehalten und nicht persistiert.
2016-09-15 15:12:20 +02:00
2016-09-27 15:18:33 +02:00
\paragraph{Ereignisse}
2016-09-27 17:47:12 +02:00
Im Rahmen von Complex Event Processing werden Ereignisdaten als Instanzen von Ereignistypen betrachtet. Während ein Ereignistyp für eine bestimmte Klasse von Vorkommnissen grundlegende Eigenschaften und Attribute definiert, repräsentiert eine Ereignisinstanz ein konkretes Ereignis dieses Ereignistypen\cite{hsh:cep}. Diese trägt neben inhaltlichen Informationen über den Vorgang durch den sie ausgelöst wurde auch eine eindeutige ID sowie einen Zeitstempel mit sich. Während der Zeitstempel den Zeitpunkt der Ereignisauslösung angibt, dient die ID zur eindeutigen Abgrenzung von anderen Ereignissen, die vom selben Ereignistyp sind oder zum selben Zeitpunkt entstanden sind. Da es bedingt durch Übertragunglatenz und weitere technische Randbedingungen möglich ist, dass die Ereignisdaten zeitverzögert bei der CEP-Engine ankommen, wird der Zeitstempel ebenfalls benötigt, um die zeitlichen Beziehungen zwischen den Ereignissen zu erhalten.
2016-09-27 15:18:33 +02:00
2016-09-27 18:21:00 +02:00
Jedes Ereignis trägt abhängig von seinem Ereignistypen eine geringe Menge von Daten mit sich, die für das Ereignis spezifische Informationen enthalten. Dies können beispielsweise Daten von Sensoren, Angaben über eine Benutzersitzung oder Statusdaten eines Systems sein. Diese Daten sind jedoch nur \emph{Momentaufnahmen} und verlieren mit fortschreitender Zeit meist an Gültigkeit. Listing~\ref{lst:sample_abstract_car_status_event} zeigt beispielhaft eine Instanz des Ereignistypen \texttt{CarStatusEvent}.
2016-09-27 15:18:33 +02:00
2016-09-27 15:57:36 +02:00
\begin{lstlisting}[caption={Exemplarische Statusmeldung eines PKW in abstrakter Notation},label={lst:sample_abstract_car_status_event}]
2016-09-27 15:32:57 +02:00
CarStatusEvent(ID=2342, timestamp=1344829400, relatedCarNumber=11, speed=63)
\end{lstlisting}
2016-09-27 16:00:53 +02:00
2016-09-27 15:18:33 +02:00
Dafür treten diese primitiven Ereignisse häufig mit einer sehr hohen Frequenz auf, da ein komplexer Vorgang während seiner Durchführung eine Vielzahl von Ereignissen auslösen kann. Beobachtet man beispielsweise einen aus dem Stand anfahrenden PKW bis zu seiner Erreichung von 30km/h, so würde man zusätzlich zu periodisch gemeldeten Messwerten von Sensoren aus dem Motorraum und Informationen über Gangwechsel des Getriebes eine Flut von Informationen darüber erhalten, wie die Pedale durch den Fahrer bedient wurden oder wie das Lenkrades eingeschlagen wurde.
Natürlich können nicht nur externe Komponenten als Quelle von Ereignissen dienen. Viele CEP-Engines unterstützen die Erzeugung von Ereignisdaten und deren Injektion in die eigene Ereignisverarbeitung. So können durch CEP-Regeln gewonnene Erkenntnisse direkt Einfluss auf die weitere Verarbeitung nehmen, indem sie als neue Ereignisse in die Verarbeitung aufgenommen werden.
2016-09-27 18:43:40 +02:00
\paragraph{CEP-Regeln} \todo{Ggf. nochmal weiter nach hinten schieben, macht ja nix.}
2016-09-27 15:39:47 +02:00
Zur Erläuterung von CEP-Regeln wird für diese hier eine aus Kapitel 3 von \cite{hsh:cep} entlehnte, abstrakte Sprache eingeführt, anhand derer die einzelnen Sprachkonstrukte von CEP-Regeln erläutert werden sollen.
2016-09-27 15:18:33 +02:00
Eine CEP-Regel besteht zunächst aus zwei Teilen: Zuerst definiert der \texttt{CONDITION}-Teil Ereignismuster, die in dem Ereignisdatenstrom gesucht werden sollen, sowie spezifische Bedingungen, die für auf das Muster passende Ereignisse erfüllt sein müssen.
2016-09-27 14:27:58 +02:00
\begin{lstlisting}[mathescape=true,label={},caption={}]
2016-09-27 15:18:33 +02:00
CONDITION (... Ereignismuster ...)
2016-09-27 14:27:58 +02:00
... weitere Bedingungen ...
\end{lstlisting}
2016-09-27 14:59:29 +02:00
Sind alle Bedingungen im \texttt{CONDITION}-Teil erfüllt, so \enquote{matcht} die Regel\cite{hsh:cep}. Im darauffolgenden \texttt{ACTION}-Teil wird eine Reihe von Aktionen definiert, die ausgeführt werden sollen, sobald die Bedingungen der Regel eintreffen. Dies kann beispielsweise die Erzeugung eines neuen Ereignisses oder das Anstoßen eines Dienstes sein. Da die Daten der Ereignisse, auf die der \texttt{CONDITION}-Teil gepasst hat, für die weitere Verarbeitung von Interesse ist, stehen sie im \texttt{ACTION}-Teil zur Verfügung.
2016-09-27 14:27:58 +02:00
\begin{lstlisting}[mathescape=true,label={},caption={}]
ACTION
... auszulösende Aktionen ...
\end{lstlisting}
Matcht eine Regel, so werden die in ihr definierten Aktionen ausgeführt --- die Regel feuert\cite{hsh:cep}. Zusammengefasst sieht eine CEP-Regel wie folgt aus:
2016-09-27 14:59:29 +02:00
\begin{lstlisting}[mathescape=true,label={lst:abstract_cep_rule_basics},caption={Grundgerüst einer CEP-Regel}]
2016-09-27 15:18:33 +02:00
CONDITION (... Ereignismuster ...)
2016-09-27 14:27:58 +02:00
... weitere Bedingungen ...
ACTION
... auszulösende Aktionen ...
\end{lstlisting}
2016-09-12 18:58:46 +02:00
2016-09-27 17:47:12 +02:00
\paragraph{Erkennung von Ereignismustern}
2016-09-28 15:15:01 +02:00
Komplexe Vorgänge kann man durch Muster in den Ereignisfolgen erkennen, die sie bei ihrer Durchführung ausgelöst haben. Hierbei spielen Ereignisfolgen und die zeitlichen Beziehungen zwischen Ereignissen eine Rolle. Um ein \enquote{bedeutungsvolles Ereignismuster} zu erkennen, wird eine CEP-Regel benötigt, die dieses Muster in ihrem \texttt{CONDITION}-Teil beschreibt.
Ein Beispiel für eine Ereignisfolge, welche durch unsachgemäß abgestellte PKW ausgelöst werden kann, könnte so aussehen:
2016-09-27 15:02:17 +02:00
\begin{itemize}
2016-09-28 15:15:01 +02:00
\item Ereignistyp A: Motor wurde abgestellt
\item \st{Ereignistyp B: Handbremse wurde angezogen} (trat \textbf{nicht} auf!)
\item Ereignistyp C: PKW wurde verriegelt
2016-09-27 15:02:17 +02:00
\end{itemize}
2016-09-28 15:49:16 +02:00
Um diese Folge von Ereignistypen mit einer CEP-Regel erkennen zu können, müssen die Bedingungen, die dieses Ereignismuster impliziert, mit Hilfe von \emph{Ereignisalgebra} beschrieben werden. Diese wurde größtenteils an \cite{hsh:cep} angelehnt und beschreibt mit Operatoren und Funktionen Bedingungen für eine Menge von Ereignissen.
2016-09-27 15:02:17 +02:00
2016-09-28 11:20:22 +02:00
Eine Ereignisfolge ist Teilmenge eines Ereignisdatenstromes. Sie kann nach dem Schema $a_1b_1a_2c_1$ notiert werden, wobei $a_i$ die $i$-te Instanz des Ereignistypen A bezeichnet\cite{hsh:cep}. Zur Unterscheidung von Ereignistypen und Instanzen werden für Instanzen kleine Buchstaben, für Ereignistypen Großbuchstaben verwendet. Die Typen von Ereignissen werden zur Beschreibungen von Bedingungen in Ereignismustern verwendet.
2016-09-27 17:47:12 +02:00
2016-09-28 15:15:01 +02:00
Um ein Ereignismuster zu beschreiben werden Operatoren aus der Ereignisalgebra nach \cite{hsh:cep} benötigt:
2016-09-27 18:47:07 +02:00
\begin{itemize}
2016-09-28 15:32:39 +02:00
\item Der \textbf{Sequenzoperator} $X \rightarrow Y$ dient zur Formulierung zeitlicher Ab\-häng\-ig\-kei\-ten zwischen zwei Ereignistypen. So beschreibt der Ausdruck eine Ereignisfolge, in der zuerst ein Ereignis vom Typ X auftritt, gefolgt von einer Ereignisinstanz des Typ Y. Die Ereignisfolge $c_1a_1c_2b_1d_1$ erfüllt diese Bedingung.
\item Die \textbf{boolschen Operatoren} $\wedge$ und $\vee$: Sie definieren \textbf{keine} zeitlichen Ab\-häng\-ig\-kei\-ten zwischen Ereignissen, bestimmen aber, \emph{welche} Ereignisse in einer Folge vorkommen dürfen. So trifft der Ausdruck $(A \vee B)$ auf Ereignisfolgen zu, die entweder ein Ereignis vom Typ A oder ein Ereignis vom Typ B enthalten. Die Folgen $c_1b_1d_1d_2$, $a_1d_1d_2c_1c_2$ und $b_1c_1a_1$ passen auf diesen Ausdruck. Der Ausdruck $(A \wedge B)$ hingegen trifft nur auf Ereignisfolgen wie $d_1c_1a_1b_1c_2$ zu, in denen beide Ereignistypen vorkommen, wobei die zeitliche Reihenfolge keine Rolle spielt.
2016-09-28 15:15:01 +02:00
\item Den \textbf{Negationsoperator} $\neg X$ erlaubt keine Vorkommnisse des Ereignistyps X in der Ereignisfolge und ergibt nur in Kombination mit dem Sequenzoperator oder unter Verwendung von Sliding Windows (siehe nachfolgenden Abschnitt über Sliding Windows) Sinn. So würde der Ausdruck $(\neg A)$ für die Folge $b_1c_1b_2$ zutreffen, nicht jedoch für die Folge $b_1b_2a_1c_1$.
2016-09-27 18:47:07 +02:00
\end{itemize}
2016-09-27 17:47:12 +02:00
2016-09-28 15:32:39 +02:00
Nimmt man nun die oben angegebene Beispielfolge und formuliert daraus ein Muster in Ereignisalgebra, so erhält man: $(A)\rightarrow (\neg B) \rightarrow (C)$. Um auf die für dieses Muster passenden Ereignisinstanzen im Rahmen der weiteren Ereignisverarbeitung zugreifen zu können, müssen diese mit dem \texttt{AS}-Operator einer Variable zugewiesen werden können. Somit sieht dieses Muster nun wie folgt aus:
2016-09-28 11:59:10 +02:00
\[(A\ AS\ a)\rightarrow (\neg B) \rightarrow (C\ AS\ c)\]
2016-09-28 18:23:11 +02:00
Dieses Muster kann man nun in einer CEP-Regel einsetzen, jedoch ist noch nicht garantiert, dass die auf das Muster passenden Ereignisinstanzen sich auf den \emph{selben} PKW beziehen --- es fehlen noch \emph{Kontextbedingungen}. Um diese zu definieren muss innerhalb der CEP-Regel Zugriff auf die Daten der gefundenen Ereignisinstanzen möglich sein. Um dies zu ermöglichen, gibt es drei Hilfsmittel:
2016-09-28 15:15:01 +02:00
\begin{itemize}
\item Die \textbf{Aliasanweisung} \texttt{AS} ermöglicht die Definition eines Variablennamens innerhalb des Ereignismusters, der die für einen Ereignistypen gefundene Ereignisinstanz enthalten soll. So würde das Ereignismuster $(A\ AS\ eventA)$ dafür sorgen, dass die gefundene Ereignisinstanz vom Typ A in der Variable \texttt{eventA} für den Rest der CEP-Regel verfügbar ist.
2016-09-28 15:32:39 +02:00
\item Um nun auf Attribute einer Ereignisinstanz zuzugreifen, wird der \textbf{Attributoperator} \enquote{\texttt{.}} verwendet: Gegeben sei eine Ereignisinstanz, welche das Attribut \texttt{pkwID} enthält und in der Variable \texttt{eventA} enthalten ist, so würde der Ausdruck \[eventA.pkwID\] den Wert dieses Attributs zurückgeben.
2016-09-28 18:23:11 +02:00
\item Kontextbedingungen können auch Bezug auf \emph{Domänenwissen} nehmen, welches von der Anwendung lokal vorgehalten wird. Um aus der CEP-Regel auf dieses Wissen zuzugreifen, kann innerhalb einer CEP-Regel das Konstrukt \texttt{lookup(\emph{key, value})} verwendet werden, wobei \texttt{key} für die aus dem Domänenwissen abzufragende Information steht und \texttt{value} ein Parameter ist, der durch Variablen innerhalb der CEP-Regel bestimmt werden kann. Der Aufruf kann direkt in Kontextbedingungen integriert werden, sodass die Formulierung dieser Bedingungen dadurch nicht erschwert wird. Soll beispielsweise die maximal zulässige Motordrehzahl für ein in \texttt{fooEvent.carModel} hinterlegtes Automodell nachgeschlagen werden, so liefert \texttt{lookup("maxMotorRPMForModel", fooEvent.carModel)} die nötigen Daten.
2016-09-28 15:15:01 +02:00
\end{itemize}
Geht man davon aus, dass die Ereignistypen A und C aus dem obigen Ereignismuster die ID des PKW, von dem das Ereignis ausgelöst wurde, in dem Attribut \texttt{pkwID} enthalten, so kann man mit der Kontextbedingung
\[a.pkwID\ =\ c.pkwID\]
sicherstellen, dass die CEP-Regel nur für Ereignisfolgen matcht, die von dem selben PKW ausgelöst wurden und das Muster erfüllen. Listing~\ref{lst:abstract_cep_rule_two} zeigt diese CEP-Regel.
2016-09-27 16:17:28 +02:00
2016-09-28 15:15:01 +02:00
\begin{lstlisting}[mathescape=true,label={lst:abstract_cep_rule_two},caption={CEP-Regel mit Ereignismuster und Kontextbedingungen}]
2016-09-28 15:32:39 +02:00
CONDITION ($(A\ AS\ a)\rightarrow (\neg B) \rightarrow (C\ AS\ c)$)
2016-09-28 15:15:01 +02:00
$\wedge$ a.pkwID = c.pkwID
2016-09-27 15:02:17 +02:00
ACTION
... auszulösende Aktionen ...
\end{lstlisting}
2016-09-28 16:48:50 +02:00
\todo{GRAFIK: Mustererkennung grob veranschaulichen?}
2016-09-27 15:02:17 +02:00
2016-09-28 16:48:50 +02:00
\todo{Diesen Part eventuell weiter nach vorne schieben?}
2016-09-14 13:49:33 +02:00
\paragraph{Sliding Windows und Tumbling Windows}
2016-09-27 14:27:58 +02:00
Um die großen Mengen von Ereignisdaten aus einem Datenstrom effizient verarbeiten zu können, werden sie in einem Fenster fester Größe betrachtet. Die Größe eines solchen Fensters wird häufig mit Zeiteinheiten wie Sekunden angegeben; selten wird die Größe durch eine Anzahl von Ereignissen angegeben, die das Fenster enthalten kann.
2016-09-07 13:23:11 +02:00
2016-09-27 14:37:23 +02:00
Ein \emph{Sliding Window} wird in regelmäßigen Intervallen um eine festgelegten Größe verschoben um aktuellere Ereignisse zu betrachten, wobei die älteren Ereignisse zugunsten der neuen Ereignisse aus dem Fenster herausfallen. Die Ergebnisse von CEP-Regeln verändern sich somit nach jedem Verschieben des Ereignisfensters. Das \emph{Tumbling Window} ist ein Sonderfall des Sliding Window, bei dem die Fenstergröße und das Intervall, in dem es verschoben wird, gleich sind. Es wird daher \enquote{umgeklappt}, sodass alle zuvor in ihm enthaltenen Ereignisse herausfallen und aktuellere Ereignisse in das nun leere Fenster gefüttert werden. Da somit ein Ereignis nur einmal in einem Tumbling Window Platz findet, kann es auch nur ein einziges Mal Einfluss auf die Auswertung nehmen.
2016-09-14 13:49:33 +02:00
\todo{GRAFIK: Sliding Window vs Tumbling Window}
2016-09-12 14:58:45 +02:00
2016-09-27 14:33:28 +02:00
Da je nach Anforderung einer CEP-Regel ein bestimmtes Ereignisfenster zweckmäßig ist, ist es notwendig, dies in der CEP-Regel festlegen zu können. Dafür werden die Angaben der Fenstergröße (\texttt{WindowSize}) und des Intervalls, in dem das Fenster verschoben wird (\texttt{StepSize}), wie folgt verwendet:
2016-09-27 14:27:58 +02:00
\begin{lstlisting}[mathescape=true,label={},caption={}]
2016-09-27 14:33:28 +02:00
[WindowSize:15min,StepSize:10s]
2016-09-27 14:27:58 +02:00
\end{lstlisting}
2016-09-27 14:33:28 +02:00
Natürlich ist es auch möglich, ein Ereignisfenster auf Basis von Ereignissen zu definieren:
2016-09-27 14:27:58 +02:00
\begin{lstlisting}[mathescape=true,label={},caption={}]
2016-09-27 14:33:28 +02:00
[WindowSize:150events,StepSize:10events]
2016-09-27 14:27:58 +02:00
\end{lstlisting}
2016-09-27 14:33:28 +02:00
Die Definition des verwendeten Ereignisfensters wird am \texttt{CONDITION}-Teil der CEP-Regel platziert, sodass diese nun wie folgt aussieht:
2016-09-27 14:59:29 +02:00
\begin{lstlisting}[mathescape=true,label={lst:abstract_cep_rule_with_window},caption={CEP-Regel mit Definition eines Ereignisfensters}]
2016-09-27 14:33:28 +02:00
CONDITION (Ereignismuster)[WindowSize:15min,StepSize:10s]
2016-09-27 14:27:58 +02:00
... weitere Bedingungen ...
ACTION
... auszulösende Aktionen ...
\end{lstlisting}
2016-09-27 12:46:12 +02:00
\paragraph{Aggregation von Ereignissen}
2016-09-28 18:31:35 +02:00
Eine weitere Möglichkeit zur Auswertung von Ereignisdaten ist die Aggregation der Attributdaten von Ereignissen zu höherwertigeren Ereignissen. Hierbei werden Ereignisse gleichen Typs innerhalb eines Sliding Windows betrachtet, mit Ereignismustern und Kontextbedingungen vorgefiltert. Dann können sie nach ihren Attributwerten gruppiert werden und diese dann mittels Aggregationsfunktionen zusammengefasst werden. So können Trends oder Kennzahlen aus Ereignisdaten gewonnen werden, die zur Interpretation der Ereignisdaten beitragen können.
2016-09-28 16:48:50 +02:00
\todo{GRAFIK: Aggregation visuell zeigen?}
2016-09-28 18:49:35 +02:00
2016-09-28 20:17:52 +02:00
In einer CEP-Regel kann die Aggregation von Ereignisinstanzen mit dem Konstrukt \begin{lstlisting}
AGGREGATE(event, "attribute", function)
\end{lstlisting}
notiert werden, wobei \texttt{event} eine Ereignisinstanz enthält, \texttt{'attribute'} den Namen des zu aggregierenden Attributs nennt, und \texttt{function} die Funktion nennt, mit der die Daten aggregiert werden sollen. Folgende Funktionen stehen zur Verfügung:
2016-09-28 18:31:35 +02:00
\begin{itemize}
2016-09-28 18:39:25 +02:00
\item COUNT: Zählt alle Ereignisinstanzen; die Angabe des Attributnamen wird nicht berücksichtigt.
2016-09-28 18:49:35 +02:00
\item SUM: Bildet die Summe über die Attributwerte aller Ereignisinstanzen
\item AVG: Bildet den Mittelwert des Attributwerts aller Ereignisinstanzen
\item MIN: Ermittelt das Minimum des Attributwerts aller Ereignisinstanzen
\item MAX: Ermittelt das Maximum des Attributwerts aller Ereignisinstanzen
2016-09-28 18:31:35 +02:00
\end{itemize}
2016-09-28 15:49:16 +02:00
2016-09-28 18:49:35 +02:00
Beispiel: Innerhalb eines 15 Minuten Zeitfensters soll die durchschnittliche Geschwindigkeit von PKW bestimmt werden, die einen Messpunkt an einer Straße passieren. Unterschreitet die Durchschnittsgeschwindigkeit den Wert von 60km/h, so soll die Regel feuern.
\begin{lstlisting}[mathescape=true,label={lst:abstract_cep_rule_four},caption={Beispiel zur Nutzung von \texttt{AGGREGATE()}}]
CONDITION ($MeasureEvent\ AS\ m$)
$\wedge$ AGGREGATE(m, "speed", AVG) < 60
ACTION
... auszulösende Aktionen ...
\end{lstlisting}
2016-09-28 16:48:50 +02:00
\todo{Weitermachen, CEP-Regelnotation!}
2016-09-28 15:49:16 +02:00
2016-09-12 14:58:45 +02:00
\paragraph{Integration von Domänenwissen}
2016-09-15 15:12:20 +02:00
Hat man in der Verarbeitung der Ereignisse durch CEP-Regeln alle Register gezogen, so kommt die Integration des Domänenwissens ins Spiel. Alle Fakten, die über die auszuwertenden Ereignisse bekannt sind, liegen hier vor. Beispiele dafür wären:
2016-09-14 14:14:35 +02:00
\begin{itemize}
\item Wo ein Sensor positioniert ist und was er misst
\item Von welchem Modell ein zu überwachendes Fahrzeug ist und welche bekannten Grenzwerte für den Betrieb eingehalten werden müssen
\item Wer ein überwachtes Fahrzeug gerade verwendet
\end{itemize}
2016-09-21 11:47:38 +02:00
Das Domänenwissen kann somit verwendet werden, um einer durch Ereignisdaten beschriebenen Situation einen eindeutigen Kontext zuzuordnen und somit die Interpretation der Daten stark zu erleichtern. Hat die Ereignisverarbeitung beispielsweise festgestellt, dass die durchschnittliche Drehzahl eines Motors bei 4200 Umdrehungen pro Minute liegt, so kann über das Domänenwissen nachgeschlagen werden, in welchem Fahrzeug der betroffene Motor montiert ist, von welchem Typen das Fahrzeug ist, und ob die Motordrehzahl für diesen Fahrzeugtypen zulässig ist.
2016-09-28 16:48:50 +02:00
\todo{Weitermachen, CEP-Regelnotation!}
2016-09-28 16:17:57 +02:00
\paragraph{Auslösen von Aktionen}
Um mit einer CEP-Regel nun auf die durch sie erkannten Sachverhalte reagieren zu können, können nahezu beliebige Aktionen im \texttt{ACTION}-Teil der Regel definiert werden. Diese lassen sich hauptsächlich in zwei Kategorien einteilen:
\begin{itemize}
\item Erzeugung eines höherwertigen Ereignis mit den gewonnen Erkenntnissen und Wiedereinspeisung dessen in den Verarbeitungsprozess
\item Anstoßen eines externen Dienstes beziehungsweise Ausführen von Programmcode
\end{itemize}
Sehr häufig werden die Auswertungsergebnisse einer CEP-Regel als höherwertiges Ereignis wieder in den Verarbeitungsprozess injiziert. Dies ist gerade dann nützlich, wenn durch eine mehrstufige Verarbeitung mit weiteren CEP-Regeln detailliertere Ergebnisse erzielt werden können. Um in dem \texttt{ACTION}-Teil einer CEP-Regel ein neues Ereignis auszulösen, wird ein mit dem Schlüsselwort \texttt{new} ein Ereignistyp wie zum Beispiel \texttt{CarAccelerationEvent} wie folgt instanziiert, wobei seine Attributwerte als Parameter übergeben werden:
\begin{lstlisting}
new CarAccelerationEvent(carID=eventA.pkwID, speed=eventC.speed-eventB.speed)
\end{lstlisting}
Um den Anstoß eines externen Dienstes beziehungsweise das Ausführen von Programmcode zu notieren, wird ein Methodenaufruf notiert, der zur Verdeutlichung mit \texttt{call} beginnt und Parameter übergeben bekommen kann. Der Aufruf eines \texttt{PushMessageService}, der einen Parameter \texttt{msg} erwartet, könnte wie folgt aussehen:
\begin{lstlisting}
callPushMessageService(msg="PKW mit ID"+eventA.pkwID+" hat ein Problem gemeldet.")
\end{lstlisting}
Erweitert man nun die CEP-Regel aus Listing~\ref{lst:abstract_cep_rule_two} mit einem Dienstaufruf, der den Fahrer des PKW auf Basis der \texttt{pkwID} benachrichtigen würde, so könnte dies so aussehen:
\begin{lstlisting}[mathescape=true,label={lst:abstract_cep_rule_three},caption={CEP-Regel benachrichtigt Fahrer des PKW im Notfall}]
CONDITION ($(A\ AS\ a)\rightarrow (\neg B) \rightarrow (C\ AS\ c)$)
$\wedge$ a.pkwID = c.pkwID
ACTION
callNotifyCarDriver(pkwID=a.pkwID)
\end{lstlisting}
Mit den in diesem Kapitel vorgestellten Werkzeugen können abstrakte CEP-Regeln formuliert werden, die später zur Implementierung in die CEP-Sprache einer CEP-Engine übersetzt werden können.
Insgesamt liegt die Herausforderung von CEP darin, in kürzester Zeit große Datenströme von Ereignissen mit Hintergrundwissen anzureichern, diese zu höherwertigen Ereignissen zu kombinieren und bestimmte Muster zu finden, sowie die Ergebnisse mit möglichst geringer Verzögerung in Echtzeit ausgeben zu können oder Reaktionen einzuleiten.
2016-07-29 13:04:07 +02:00
2016-07-27 17:03:44 +02:00
2016-09-08 11:07:16 +02:00
\chapter{Vergleich aktueller RDF-fähiger CEP-Engines}\label{cpt:engine_comparison}
2016-09-27 13:29:22 +02:00
Nachdem ein kurzer Einstieg in die Welt von RDF und CEP gegeben wurde, soll nun eine CEP-Engine ausgewählt werden, mit der RDF-Ereignisdatenströme verarbeitet werden können, um das Beispielszenario aus Kapitel~\ref{cpt:scenario} im weiteren Verlauf der Arbeit umsetzen zu können. In diesem Kapitel werden drei CEP-Engines vorgestellt, die einen C-SPARQL-Dialekt implementieren --- eine Form der Abfagesprache SPARQL, welche um Sprachkonstrukte erweitert wurde, die speziell auf die Verarbeitung von RDF-Datenströmen zugeschnitten sind. Eine der Engines soll in diesem Kapitel zur Umsetzung des Beispielszenarios aus Kapitel~\ref{cpt:scenario} ausgewählt werden.
2016-09-20 13:14:15 +02:00
\section{EP-SPARQL mit der ETALIS-Engine}
Die ETALIS-Engine stellt zur Formulierung von CEP-Regeln neben der eigenen Sprache ELE (\enquote{Etalis Language for Events}) die Sprache EP-SPARQL (\enquote{Event Processing SPARQL}) zur Verfügung\cite{ep:etalis}. Ein erstes Paper\cite{ep:etalis} über die Engine erschien 2009; die Autoren lassen darauf schließen, dass die Engine vom FZI Forschungszentrum Informatik (Karlsruhe, Deutschland), dem Karlsruher Institut für Technologie (Karlsruhe, Deutschland), und der Stony Brook University (New York, USA) entwickelt wurde.
2016-09-21 11:24:09 +02:00
Bei der Engine handelt es sich um einen in Prolog implementierten Prototyp\cite{ep:unified}, der neben der Integration von lokalem Domänenwissen auch Reasoning auf Basis von gegebenem RDFS-Vokabular auf den Ereignisdaten unterstützt\cite{ep:etalis}. Dabei werden Fakten und CEP-Regeln direkt übersetzt um die vorhandene Prolog-Umgebung zur Auswertung nutzen zu können\cite{hsh:integrating}. Neben einer Schnittstelle für die Sprache Prolog stehen auch Schnittstellen für Java, C und C\# zur Verfügung\cite{ep:etalis}, jedoch wird für den Betrieb der Engine zusätzlich immer eine Prolog-Laufzeitumgebung benötigt.
2016-07-15 16:02:15 +02:00
2016-07-25 12:29:39 +02:00
2016-09-20 14:46:04 +02:00
\section{Das CQELS-Framework}
2016-09-20 14:31:00 +02:00
Das CQELS-Framework (Continuous Query Evaluation over Linked Stream) wurde in Zusammenarbeit von dem Insight Centre for Data Analytics an der National University of Ireland (Galway, Irland), dem Institute of Information Systems an der Vienna University of Technology (Wien, Österreich) und dem Institut für Telekommunikationssysteme an der TU-Berlin (Berlin, Deutschland) entwickelt; ein erstes Paper über CQELS erschien 2011\cite{cqels:native}. Es wurde in Java implementiert und unterstützt die Einbindung von lokalem Domänenwissen in die Ereignisverarbeitung\cite{cqels:stream}. Über Reasoning-Fähigkeiten konnten bisher keine Angaben gefunden werden, jedoch kann nicht ausgeschlossen werden, dass Reasoning mit CQELS möglich ist.
2016-04-22 14:12:28 +02:00
2016-09-20 14:31:00 +02:00
Es kann als Grundlage zum Aufbau einer sehr leistungsfähigen RDF-fähigen CEP-Engine verwendet werden\cite{cqels:stream}, da es im Gegensatz zu vielen anderen RDF-fähigen CEP-Engines die eigentliche Datenverarbeitung nicht eine externe Engine delegieren, sondern eine eigene Implementierung verwendet. Dadurch reduziert sich die benötigte Rechenleistung, da so keine übersetzende Schnittstelle zu einer externen Engine benötigt wird \cite{cqels:native}.
2016-09-27 13:29:22 +02:00
Eine im Paper \cite{cqels:stream} vorgestellte Lösung\footnote{Unter \url{http://graphofthings.org/debs2015/cqels.zip} ist ein VirtualBox-Image mit der Lösung zum Ausprobieren erhältlich. (Größe ca. 1,1 GiB)} zur Verarbeitung von RDF-Er\-eig\-nis\-da\-ten\-strö\-men mit einem C-SPARQL-Dialekt konsumiert die Ereignisdaten über einen aus einer Datei lesenden CSV-Reader und schreibt die Ergebnisse der Verarbeitung über einen CSV-Writer in eine Datei, wobei die Engine intern mit RDF-Daten arbeitet, die von Reader und Writer jeweils konvertiert werden. Da es sich bei CQELS um ein Framework handelt\cite{cqels:native} ist im Gegensatz zu einer fertigen CEP-Engine zur Umsetzung eines Szenarios mit einem erhöhten Aufwand zu rechnen. Dafür punktet es im Vergleich zu klassischen, nicht RDF-fähigen CEP-Engines wie beispielsweise Esper mit einer hohen Performance\cite{cqels:stream}.
2016-04-22 14:12:28 +02:00
2016-09-20 14:46:04 +02:00
\section{C-SPARQL-Engine}
2016-09-27 13:29:22 +02:00
Die C-SPARQL-Engine wurde vom Polytechnikum Mailand (Italien) entwickelt; ein erstes Paper erschien im Jahr 2009\cite{barbieri:csparql}. Sie wurde zur Verarbeitung von RDF-Datenströmen im Rahmen eines Forschungsprojektes\cite{barbieri:csparql} in der Sprache Java entwickelt und bietet einen eigenen \emph{C-SPARQL-Dialekt} zur Formulierung von CEP-Regeln an, in denen direkt Bezug auf lokal vorhandenes Domänenwissen genommen werden kann. Weiterhin beinhaltet sie eine Implementierung von Reasoning auf RDFS-Vokabular, wie \cite{barbieri:reasoning} beschreibt.
2016-04-22 14:12:28 +02:00
2016-09-21 11:47:38 +02:00
Ein \enquote{Hello World}-Softwarepaket zur Demonstration der Engine, welches unter \url{http://streamreasoning.org/resources/c-sparql} zum Download angeboten wird, beinhaltet ein Eclipse/Maven-Projekt, welches Einsteigern einen ersten Überblick verschafft und leicht für eigene Zwecke angepasst werden kann. Da die Engine auf Software wie Apache Jena zum Speichern von RDF-Daten, Sesame zur Analyse und Abfrage von RDF-Daten via SPARQL, und die bekannte CEP-Engine Esper aufbaut, sind für die verwendeten Basistechnologien bereits gute Dokumentationen erhältlich.
2016-07-19 17:42:30 +02:00
2016-08-25 17:33:18 +02:00
2016-08-23 19:14:03 +02:00
\section{Auswahl der Engine für die Arbeit}
2016-09-21 11:47:38 +02:00
Da in dieser Arbeit die Verarbeitung von RDF-Ereignisdatenströmen anhand einer konkreten CEP-Engine erläutert werden soll, muss nun eine Entscheidung für eine CEP-Engine gefällt werden. Um einen möglichst einfachen Einstieg in die Thematik zu bekommen, soll die vorgestellte Engine möglichst wenig zusätzlichen Aufwand hervorrufen. Somit sind folgende Kriterien für die Auswahl der Engine verwendet worden:
\begin{itemize}
2016-09-27 12:46:12 +02:00
\item Verwendung einer einzigen Programmiersprache
2016-09-21 11:47:38 +02:00
\item Verwendung sehr verbreiteter Programmiersprachen
\item Transparente Implementierung der Engine durch Verwendung bekannter Technologien
\end{itemize}
2016-09-27 12:46:12 +02:00
\todo{Tabelle o.Ä. zum direkten Vergleich der Kriterien!}
2016-09-21 11:47:38 +02:00
Unter Berücksichtigung dieser Kriterien fiel die Wahl auf die CEP-Engine C-SPARQL; sie wird im weiteren Lauf der Arbeit vorgestellt, um die Verarbeitung von RDF-Er\-eig\-nis\-da\-ten\-strö\-men durchzuführen und das Beispielszenario aus Kapitel~\ref{cpt:scenario} umzusetzen.
2016-08-23 19:14:03 +02:00
2016-08-25 17:33:18 +02:00
2016-09-13 19:34:15 +02:00
\chapter{CEP auf RDF-Datenströmen anhand der C-SPARQL Engine}
2016-09-21 15:49:45 +02:00
Nachdem die Wahl der CEP-Engine auf die C-SPARQL-Engine gefallen ist, sollen in diesem Kapitel nun ihre Möglichkeiten zur Verarbeitung von RDF-Datenströmen beleuchtet werden.
2016-09-13 10:05:13 +02:00
2016-09-26 14:06:25 +02:00
\section{Ereignisse in RDF-Datenströmen}
2016-09-21 15:49:45 +02:00
Ereignisse werden aufgrund der Nutzung von RDF-Datenströmen als Transportmedium nun durch RDF-Tupel beschrieben. Diese tragen neben den typischen Inhalten von Tripeln (Subjekt, Prädikat und Objekt) nun eine vierte Information mit sich: den Zeitstempel, zu dem das Ereignis ausgelöst wurde. Da die Tupel nun mit dem Zeitstempel insgesamt vier Angaben enthalten, werden sie als \emph{Quadrupel} bezeichnet.
2016-09-13 10:05:13 +02:00
2016-09-21 15:49:45 +02:00
Um die Ereignisquadrupel trotz identischer Ereignistypen oder Zeitstempel voneinander unterscheiden zu können, ist es nötig, die Ereignisse mit einer eindeutigen ID zu versehen. Um dies zu erreichen, werden die einzelnen Ereignisse als eigene, separate Subjekte in RDF repräsentiert. Dadurch erhalten alle Quadrupel eines Ereignisses eine eindeutige Zuordnung zu ihrem Ereignissubjekt.
2016-09-20 10:43:47 +02:00
Um dies zu verdeutlichen folgt nun ein kleines Beispiel. Gegeben seien zwei beispielhafte Ereignisse mit Statusdaten über einen PKW. Listing~\ref{lst:sample_abstract_event_data} zeigt diese beiden Ereignisse in abstrakter Notation.
\begin{lstlisting}[caption={Zwei Statusereignisse eines PKW in abstrakter Notation},label={lst:sample_abstract_event_data}]
CarStatusEvent {
ID: 324,
timestamp: 1344829400,
2016-09-20 11:16:17 +02:00
relatedCar: ->[Car(ID: 0)],
2016-09-20 10:43:47 +02:00
speed: 63
}
CarStatusEvent {
ID: 325,
timestamp: 1344829405,
2016-09-20 11:16:17 +02:00
relatedCar: ->[Car(ID: 0)],
2016-09-20 10:43:47 +02:00
speed: 75
}
\end{lstlisting}
Wie aus Listing~\ref{lst:sample_abstract_event_data} zu erkennen ist, ist jedes Ereignis ein eigenes Objekt, welches alle für sich relevanten Daten entweder direkt oder als Zeiger auf andere Objekte enthalten kann. Um diese über RDF-Datenströme zu transportieren, müssen diese Ereignisse mit RDF-Quadrupeln beschrieben werden. Listing~\ref{lst:sample_event_rdf_quads} zeigt die Beschreibung der Ereignisse aus Listing~\ref{lst:sample_abstract_event_data} mit RDF-Quadrupeln.
2016-09-19 12:23:59 +02:00
\begin{lstlisting}[caption={RDF-Quadrupel mit Zeitstempeln beschreiben zwei Ereignisse eines PKW},label={lst:sample_event_rdf_quads}]
2016-09-19 12:18:03 +02:00
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix carOnt: <http://example.org/carSim/carSimulationOntology#> .
@prefix event: <http://example.org/carSim/objects/event#> .
2016-09-21 15:49:45 +02:00
(1344829400) event:324 rdf:type carOnt:CarStatusEvent .
2016-09-20 11:16:17 +02:00
(1344829400) event:324 carOnt:relatedCar car:0 .
(1344829400) event:324 carOnt:speed 63 .
2016-09-19 12:18:03 +02:00
2016-09-21 15:49:45 +02:00
(1344829405) event:325 rdf:type carOnt:CarStatusEvent .
2016-09-20 11:16:17 +02:00
(1344829405) event:325 carOnt:relatedCar car:0 .
(1344829405) event:325 carOnt:speed 75 .
2016-09-19 12:18:03 +02:00
\end{lstlisting}
2016-09-21 15:49:45 +02:00
Über RDF-Ereignisdatenströme ausgelieferte Ereignisdaten, die zur Verarbeitung einer RDF-fähigen CEP-Engine zugeführt werden, sind von der Struktur her angelehnt an die Beispielereignisse aus Listing~\ref{lst:sample_abstract_event_data} aufgebaut.
2016-09-13 10:05:13 +02:00
2016-09-27 13:29:22 +02:00
\section{Sprachkonzepte für C-SPARQL}
Um die Ereignisdatenströme von RDF-Quadrupeln nun in der C-SPARQL-Engine verarbeiten zu können, werden im Verarbeitungsprozess CEP-Regeln benötigt, um die Ereignisdaten auszuwerten. Im Fall der C-SPARQL-Engine sind CEP-Regeln als C-SPARQL-Queries zu formulieren. Anhand einer abstrakten CEP-Regelsprache soll dieses Kapitel veranschaulichen, wie die einzelnen Aspekte eines C-SPARQL-Queries zur Verarbeitung von Ereignisdaten verwendet werden können.
2016-09-26 12:24:01 +02:00
2016-09-27 10:57:42 +02:00
\begin{lstlisting}[mathescape=true,label={lst:sample_abstract_cep_rule},caption={Beispiel für abstrakte CEP-Regelsprache}]
CONDITION (SomeEvent AS e $\longrightarrow$ AnotherEvent AS a $\longrightarrow \neg$NoEvent)[Window:15min,SlideInterval:15s]
$\wedge$ e.foo = a.foo
$\wedge$ e.threshold > 42
2016-09-26 22:38:30 +02:00
ACTION
2016-09-27 10:57:42 +02:00
new FooEvent(Bla=42, Blubber=5)
2016-09-26 20:24:59 +02:00
\end{lstlisting}
2016-09-13 10:05:13 +02:00
2016-09-27 17:47:12 +02:00
\section{C-SPARQL als Sprache für CEP-Regeln}
2016-09-26 15:17:14 +02:00
2016-09-27 10:30:57 +02:00
\begin{lstlisting}[label={},caption={}]
2016-09-26 22:38:30 +02:00
CONDITION
...
ACTION
...
2016-09-26 20:24:59 +02:00
\end{lstlisting}
2016-09-26 14:06:25 +02:00
2016-09-20 11:16:17 +02:00
\paragraph{Sliding Windows}
2016-09-26 15:17:14 +02:00
Um mit der Verarbeitung von Ereignisdatenströmen beginnen zu können, müssen die kontinuierlich einströmenden Ereignisdaten auf eine endliche Menge an Daten reduziert werden. Da je nach Anforderungen ältere Ereignisse in die Verarbeitung mit eingebezogen werden sollen, muss eine CEP-Regel in der Lage sein, Einfluss auf das Sliding Window zu nehmen, indem sie dessen Größe definiert.
2016-09-26 14:06:25 +02:00
2016-09-26 15:17:14 +02:00
\begin{lstlisting}
SELECT ...
FROM STREAM <http://example.org/carSim/stream/carStream> [RANGE 10 MIN STEP 30 SEC]
FROM STREAM <> [RANGE 10 MIN TUMBLING]
WHERE {
...
}
\end{lstlisting}
2016-09-13 10:05:13 +02:00
2016-09-26 14:06:25 +02:00
2016-09-26 15:17:14 +02:00
\paragraph{Aggregation von Ereignissen}
2016-09-26 20:24:59 +02:00
\dots
2016-09-26 15:17:14 +02:00
\begin{lstlisting}
WHERE { ... }
AGGREGATE {
(?zielVariable, COUNT, { ?groupByVariableA, ?groupByVariableB } )
FILTER ( ?zielVariable > 5 )
}
\end{lstlisting}
Mögliche Aggregationsfunktionen laut \cite{barbieri:csparql} sind:
\begin{itemize}
\item COUNT
\item SUM
\item AVG
\item MIN
\item MAX
\end{itemize}
2016-09-20 10:43:47 +02:00
2016-09-20 11:16:17 +02:00
\paragraph{Mustererkennung}
2016-09-26 15:29:21 +02:00
\todo{\dots} Ereignismuster lassen sich durch Sequenzen von auftretenden bzw. nicht auftretenden Ereignissen definieren. Um diese zu finden, müssen Tripel selektiert werden, die zu den benötigten Ereignistypen korrespondieren, wobei diese später über \texttt{FILTER}-Anweisungen in ihrer Reihenfolge festgelegt werden. Über Differenzen der durch \texttt{f:timestamp(?s,?p,?o)} angegebenen Zeitstempel von gegebenen Tripeln lassen sich auch zeitliche Beziehungen eingrenzen und festlegen.
2016-09-13 10:05:13 +02:00
2016-09-27 17:47:12 +02:00
\section{Auslösen von Aktionen}
2016-09-27 13:29:22 +02:00
Erzeugen von Ereignissen innerhalb von C-SPARQL-Queries (durch Registrierung der C-SPARQL-Queries als neue Ereignisströme an der Engine). Hinweise auf Möglichkeit der Auslösung von Reaktionen beim Beobachten der Abfrageergebnisse.
2016-09-13 10:05:13 +02:00
\section{Einbindung von Domänenwissen}
2016-09-27 13:29:22 +02:00
Integration von Hintergrundwissen findet live im Query statt ohne extra Klimmzüge, da alles innerhalb der C-SPARQL-Queries abzufragen ist. Lediglich der lokale Graph muss gegebenenfalls genannt werden.
2016-09-13 10:05:13 +02:00
\section{Reasoning auf RDF-Datenströmen}
\begin{itemize}
2016-09-26 15:33:10 +02:00
\item Reasoning auf RDFS-Level kann die C-SPARQL-Engine laut Quellen definitiv; man braucht es sozusagen nur noch einzuschalten und ein RDFS-Vokabular + RDFS-Entailment-Regeln füttern \dots
2016-09-27 10:30:57 +02:00
\item Auf Masterarbeit von Stefan Lier referenzieren
2016-09-13 10:05:13 +02:00
\end{itemize}
2016-09-08 11:07:16 +02:00
\chapter{Umsetzung des Beispielszenarios}
2016-04-22 14:33:00 +02:00
2016-08-23 15:21:09 +02:00
\todo{Zusammenfassungsüberleitung über das Kapitel}
2016-08-31 15:28:33 +02:00
\todo{In diesem Kapitel wird die Engine konkret ausgepackt und mit Java-Code benutzt. Es werden Datenstromgeneratoren gezeigt, Queries registriert und vielleicht etwas Reasoning eingeschaltet und dessen Ergebnisse begutachtet.}
2016-08-23 15:21:09 +02:00
2016-09-08 11:07:16 +02:00
In diesem Kapitel wird die C-SPARQL-Engine konkret vorgestellt und verwendet um das Beispielszenario aus Kapitel~\ref{cpt:scenario} umzusetzen. Dafür werden die Anforderungen des Szenarios einzeln betrachtet, die Ereignisdatenströme und der ganze Kram, der da mit dranhängt um dann eine Lösung zu konzipieren und implementieren.
2016-09-07 18:23:45 +02:00
2016-07-15 16:02:15 +02:00
\begin{itemize}
\item RDF-Datenströme
\item Beispielszenario
\item Umsetzung mit C-SPARQL
\item Nötiger Code für das Grundsetup der Engine, Generatoren und co
\item Konkreter Blick auf die CSPARQL-Queries
\item Ergebnisse der Abfragen
\end{itemize}
2016-04-22 14:12:28 +02:00
2016-08-03 14:47:53 +02:00
\section{Nutzung der C-SPARQL Engine in Java}
2016-07-25 15:48:24 +02:00
2016-08-31 15:28:33 +02:00
\todo{TBD}
Im Folgenden wird auf die praktische Anwendung der C-SPARQL-Engine in einem Java-Projekt eingegangen.
2016-08-03 14:35:30 +02:00
2016-08-03 17:55:48 +02:00
\begin{itemize}
2016-08-31 15:28:33 +02:00
\item Welche technischen Strukturen sieht die Engine vor,
\item wie werden Datenströme zugeführt,
\item wie werden Queries erzeugt, registriert und beobachtet,
\item was muss dabei beachtet werden, welche Fallstricke gibt es (zur Zeit)
\item wie wird Hintergrundwissen eingespeist und zur Laufzeit aktualisiert,
\item welche Schritte sind nötig um RDFS-Reasoning zu nutzen?
\item Und natürlich immer wieder mittendrin: Wie sehen die Ergebnisse aus, die dabei entstehen?
2016-08-03 17:55:48 +02:00
\end{itemize}
2016-08-31 15:28:33 +02:00
\todo{Die einzelnen Sections entstehen beim Schreiben der Texte.}
2016-07-25 15:48:24 +02:00
2016-07-15 16:02:15 +02:00
\section{Bewertung/Ergebnis}
2016-04-22 14:12:28 +02:00
2016-07-15 16:02:15 +02:00
\begin{itemize}
2016-07-29 13:39:42 +02:00
\item (Konnten die gestellten Anforderungen erfüllt werden?)
2016-07-15 16:02:15 +02:00
\item Was konnte erreicht werden?
\item Was konnte nicht erreicht werden?
2016-08-03 18:11:49 +02:00
\item Gab es Schwierigkeiten? [Guter Zeitpunkt, um hier f:timestamp() vs Tripel mit Literals zu erwähnen]
2016-07-15 16:02:15 +02:00
\item Wie hoch war der Aufwand?
\item Wie steht es um die Qualität der Ergebnisse?
\item Eventuell ein Blick auf die Performance?
\end{itemize}
2016-04-22 14:12:28 +02:00
2016-07-15 16:02:15 +02:00
\chapter{Fazit}
2016-04-22 14:39:52 +02:00
2016-08-23 15:21:09 +02:00
\todo{Zusammenfassungsüberleitung über das Kapitel}
2016-07-15 16:02:15 +02:00
\begin{itemize}
\item Bewertung der Ergebnisse im Abgleich mit den Anforderungen und dem Aufwand?
\item Ist es für die Anforderungen (und mehr) praxistauglich?
\item Oder gibt es zur Zeit bessere Alternativen?
\end{itemize}
2016-04-22 14:33:00 +02:00
2016-04-23 13:26:48 +02:00
2016-09-27 12:51:03 +02:00
\section{Ausblick}
2016-04-22 14:33:00 +02:00
2016-08-31 15:28:33 +02:00
\todo{Eventuell mit Fazit zusammenführen, wenn es nicht zu groß wird.}
2016-08-23 15:21:09 +02:00
2016-07-15 16:02:15 +02:00
\begin{itemize}
\item Kann man mit der Engine in Zukunft noch mehr schaffen?
2016-09-26 15:33:10 +02:00
\item Wie steht es um Reasoning auf RDF-Ereignisdatenströmen? Geht das? Wenn ja, nur RDFS oder auch OWL? \todo{Ist der Unterschied zwischen den Beiden fürs erste sehr wichtig oder führt das zu weit?}
2016-07-15 16:02:15 +02:00
\end{itemize}
2016-04-23 13:26:48 +02:00
2016-07-15 16:02:15 +02:00
Vielleicht geht das mit dem Reasoning später ja noch besser --- aktueller Stand ist noch limitiert, aber es wird fleißig daran geforscht \dots
2016-04-22 14:33:00 +02:00
2016-09-27 15:18:33 +02:00
\begin{comment}
2016-08-31 15:28:33 +02:00
\chapter*{Dummy-Kapitel für Tests und Notizen}
2016-07-15 16:02:15 +02:00
\textcolor{red}{Dieses Kapitel fliegt am Ende natürlich raus.}
2016-04-22 14:33:00 +02:00
2016-07-15 16:02:15 +02:00
Sil-ben ge-trenn-t mit ei-nem Strich
2016-04-22 14:33:00 +02:00
2016-07-15 16:02:15 +02:00
C--SPARQL (Zwei Striche ergeben einen Bindestrich)
2016-04-22 14:33:00 +02:00
2016-07-15 16:02:15 +02:00
Und dann --- neben vielen anderen Zeichen --- gibt es mit drei Strichen den Gedankenstrich.
2016-07-28 13:08:43 +02:00
Mit \enquote{enquote} wird Text in Anführungszeichen gesetzt, aber manchmal ist vielleicht der Einsatz von \texttt{texttt} sinnvoll. Im \textbf{Notfall} kann auch \textbf{textbf} genutzt werden. Dann gibt es noch \textit{textit}, \textsc{textsc}, \textsf{textsf} und \textsl{textsl}.
2016-09-27 12:37:34 +02:00
\begin{figure}[htbp]
\centering
\includegraphics[width=\textwidth]{img/aggregation-patternmatching.pdf}
\caption{Aggregation und Mustererkennung auf einem Ereignisstrom}
\label{fig:aggregation_patternmatching}
\end{figure}
2016-07-25 12:29:39 +02:00
Quellenreferenzen
2016-07-15 16:02:15 +02:00
\begin{itemize}
2016-07-25 12:29:39 +02:00
\item \cite{hsh:cep}[Einstieg in CEP mit Beispielen aus Esper-Welt]
\item \cite{hsh:integrating}[Esper vs C-SPARQL CEP ohne Reasoning]
\item \cite{barbieri:reasoning}[Ansatz für Reasoning auf RDF-Strömen mit C-SPARQL]
2016-09-27 15:18:33 +02:00
\item \cite{barbieri:querying}[Grundlagen C-SPARQL für CEP] <--- NOT CITED YET
2016-07-25 12:29:39 +02:00
\item \cite{cqels:stream}[CQELS-Paper]
\item \cite{ep:etalis}[ETALIS-Paper]
\item \cite{ep:unified}[EP-SPARQL-Paper]
2016-07-28 13:08:43 +02:00
\item \cite{man:owl}[Owl Reasoning Examples]
\item \cite{w3c:sparql}[W3C zu SPARQL]
2016-09-27 15:18:33 +02:00
\item \cite{iao:esper}[Marktübersicht Real-Time Monitoring Software] <--- NOT CITED YET
2016-08-22 17:57:35 +02:00
\item \cite{w3c:turtle}[Die Turtle-Notation]
2016-08-22 15:31:50 +02:00
\item \cite{hitzler:semanticweb}[Grundlagen Semantic Web]
2016-09-20 13:57:55 +02:00
\item \cite{cqels:native}[Mehr CQELS]
2016-09-20 15:01:08 +02:00
\item \cite{barbieri:csparql}[Erstes C-SPARQL Proposal]
2016-07-15 16:02:15 +02:00
\end{itemize}
2016-09-27 15:18:33 +02:00
\end{comment}
2016-08-31 15:28:33 +02:00
%%% Ende inhaltlicher Inhalt! %%%
% Literaturverzeichnis
2016-09-27 15:18:33 +02:00
\clearpage
2016-08-31 15:28:33 +02:00
% Schlüssel als Buchstaben
\bibliographystyle{alpha}
\bibliography{Literaturverweise}
2016-09-27 15:18:33 +02:00
% Und JETZT zum Inhaltsverzeichnis hinzufügen. Geil!
\addcontentsline{toc}{chapter}{Literaturverweise}
2016-08-31 15:28:33 +02:00
\end{document}
% Nothing beyond this line!
2016-04-04 13:07:28 +02:00
% Referenz auf Bibtex mit Kommentar
% \cite{robbins:gawk}[Siehe ab S.95]
2016-03-07 12:46:38 +01:00
% Einbinden von Tex-Files
%\input{abkuerz.tex}
2016-03-07 12:17:22 +01:00
%\input{einfuehrung.tex}
2016-03-07 12:46:38 +01:00
% Einbinden von größeren Tex-Files, z.B. Kapiteln
2016-04-04 13:07:28 +02:00
%\include{normen}
2016-03-07 12:17:22 +01:00
%\include{aufbau}
%\include{zitieren}
%\include{form}
%\include{allgtips}