{"id":2697,"date":"2021-02-02T05:03:06","date_gmt":"2021-02-02T10:03:06","guid":{"rendered":"http:\/\/inova8.com\/bg_inova8.com\/?p=2697"},"modified":"2021-09-18T03:42:41","modified_gmt":"2021-09-18T08:42:41","slug":"intelligent-graph-knowledge-graph-embedded-analysis","status":"publish","type":"post","link":"https:\/\/inova8.com\/bg_inova8.com\/intelligent-graph-knowledge-graph-embedded-analysis\/","title":{"rendered":"Intelligent Graph = Knowledge Graph + Embedded Analysis"},"content":{"rendered":"<div class=\"boldgrid-section\">\n<div class=\"container\">\n<div class=\"row\">\n<div class=\"col-md-12 col-xs-12 col-sm-12\" style=\"text-align: left;\">\n<p class=\"\"><span style=\"font-weight: 400;\">IntelligentGraph embeds calculation and analysis capability within RDF knowledge graphs, rather than forcing analysis to be undertaken by exporting query results to external analysis applications such as Excel.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\"> IntelligentGraph achieves this by embedding scripts into the RDF knowledge graph which are evaluated when queried with SPARQL.<\/span><\/p>\n<p class=\"\">Scripts, written in a variety of languages such as JavaScript, Java, and Python, access the underlying graph using simple pathPatternQL navigation.<\/p>\n<p class=\"\"><p><span class=\"gdm-drivefile-embed\"><img src=\"https:\/\/drive-thirdparty.googleusercontent.com\/16\/type\/application\/pdf\" width=\"16\" height=\"16\" \/> <a href=\"https:\/\/drive.google.com\/file\/d\/1XreFF6QQUJH_pAen8zOqg3HNIyySV1o1\/view?usp=drivesdk\" target=\"&quot;_blank&quot;\">IntelligentGraph=KnowledgeGraph+Embedded Analysis.pdf<\/a><\/span><\/p><\/p>\n<h1 class=\"\">Why IntelligentGraph?<\/h1>\n<p class=\"\"><span style=\"font-weight: 400;\">At present calculations over stored data are either delivered by custom code or exporting the stored data to spreadsheets. The data behind these tools is inevitably tabular. In fact, so dominant are spreadsheets for analysis that the spreadsheet itself becomes the \u2018database\u2019 with the inherent difficulties of syncing that data with the source system of record.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">The real-world is better represented as a network or graph of interconnected things Therefore a knowledge graph is a far better storage organization than tables or objects. However, there is still the need to perform ad hoc numerical analysis over this data.&nbsp;<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">RDF DataCube can help organize data for analysis, but still the analysis has to be performed externally. Confronted with this dilemma, knowledge graph data would typically be exported in tabular form to a datamart or directly into, yet again, a spreadsheet where the analysis could be performed.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">IntelligentGraph turns this approach on its head by embedding the calculations as scripts within the knowledge graph. These scripts are evaluated on query, and utilise the data in situ: no concurrency issues.. This allows the calculations to have knowledge of its neighbouring nodes and edges, just like Excel cells can access other cells in the spreadsheet. Access to other nodes within the graph uses pathPatternQL navigation.<\/span><\/p>\n<h1 class=\"\">Example Data and Analysis<\/h1>\n<p class=\"\"><span style=\"font-weight: 400;\">An Industrial Internet of Things (IIoT) application is connecting all the measurements about a process plant, such as an oil refinery, into a knowledge graph that relates the measurements to the material flows through the process equipment.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">Although there is an abundance of measurements and laboratory analyses available, the values required for operating and performance monitoring are not (and mostly cannot) be directly measured.&nbsp;<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">For example:<\/span><\/p>\n<ul class=\"\">\n<li><b>Stream Mass-Flow:<\/b><span style=\"font-weight: 400;\"> direct mass flow measurements are rare. Instead, a volume flow measurement is used in conjunction with a measured material density to calculate the mass-flow<\/span><\/li>\n<li><b>Unit Mass Flow Throughput:<\/b><span style=\"font-weight: 400;\"> this is calculated by summing either all feed stream mass flows or product stream mass flows.<\/span><\/li>\n<li><b>Unit Mass Balance:<\/b><span style=\"font-weight: 400;\"> this is calculated by differencing the feed from product mass flows<\/span><\/li>\n<li><b>Product Stream Yield:<\/b><span style=\"font-weight: 400;\"> this is the ratio of a stream\u2019s mass-flow to the unit to which the stream is connected throughput.<\/span><\/li>\n<\/ul>\n<p class=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-2707\" src=\"http:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/ProcessFlowSheet.png\" alt=\"\" width=\"1023\" height=\"529\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/ProcessFlowSheet.png 1023w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/ProcessFlowSheet-300x155.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/ProcessFlowSheet-768x397.png 768w\" sizes=\"(max-width: 1023px) 100vw, 1023px\" \/><\/p>\n<p class=\"\" style=\"text-align: center;\"><strong>Figure 1: Typical Process Flow Sheet<\/strong><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">These are simple examples; however, they show the reliance on the knowledge graph structure to perform the analysis.<\/span><\/p>\n<h2 class=\"\">Solving data analysis, the traditional way<\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">Data is in the database, analysis is done by the analysis engine (aka Excel), right?<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\"> <img loading=\"lazy\" class=\"alignnone size-full wp-image-2704\" src=\"http:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell.png\" alt=\"\" width=\"1692\" height=\"782\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell.png 1692w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell-300x139.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell-1024x473.png 1024w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell-768x355.png 768w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Excel-hell-1536x710.png 1536w\" sizes=\"(max-width: 1692px) 100vw, 1692px\" \/><\/span><\/p>\n<p class=\"\" style=\"text-align: center;\"><strong>Figure 2: Data analysis the traditional way<\/strong><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">In this scenario, the local power user sets up a query to export data from the database and converts to a format that can be imported into Excel. Ever increasingly complex formulae are then written to wrangle the data into the results that are required.<\/span><\/p>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Why is the spreadsheet approach risky?<\/span><\/h2>\n<ul class=\"\">\n<li><span style=\"font-weight: 400;\">The analysis is now separated from the data. Data changes will not be reflected in the analysis. Worse still, changes to the analysis might not be propagated to all the spawned copies of the spreadsheet.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">The data is separated from the analysis. The analysis results are rarely re-imported into the data store where data vs analysis could be performed. Instead, even more data is extracted into the spreadsheet.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">The difficultly of managing the separation of data from analysis becomes so great that in many cases the database is dispensed with entirely and the spreadsheet becomes the de-facto database.<\/span><\/li>\n<\/ul>\n<h2 class=\"\">Solving data analysis with an IntelligentGraph<\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">The beauty of Excel is that a cell can contain either a value or a formula that can reference other cell\u2019s values. Why not do the same with a graph: a node can have edges that terminate with a literal value, or a formula that can reference other node\u2019s values.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">This is illustrated in the diagram below:<\/span><\/p>\n<ul class=\"\">\n<li><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">:massFlow<\/span><span style=\"font-weight: 400;\"> property is not measured directly, so a formula is used for its value instead. This formula references <\/span><span style=\"font-weight: 400;\">$this<\/span><span style=\"font-weight: 400;\">, the node to which the calculation is attached, and uses the method <\/span><span style=\"font-weight: 400;\">getFact()<\/span><span style=\"font-weight: 400;\"> to retrieve related values. The argument of getFact() is a pathPatternQL expression.<\/span><\/li>\n<\/ul>\n<ul class=\"\">\n<li><span style=\"font-weight: 400;\">The <\/span><span style=\"font-weight: 400;\">:totalProduction<\/span><span style=\"font-weight: 400;\"> property is not measured directly, so a formula is used instead which iterates over all of the \u2018stream out\u2019 nodes, retrieving the value of the <\/span><span style=\"font-weight: 400;\">:massFlow <\/span><span style=\"font-weight: 400;\">for each stream. The <\/span><span style=\"font-weight: 400;\">:massFlow<\/span><span style=\"font-weight: 400;\"> value is, of course, in turn a calculation.<\/span><\/li>\n<\/ul>\n<p class=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-3635\" src=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/09\/Example-Calculations-Graph.png\" alt=\"\" width=\"1123\" height=\"368\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/09\/Example-Calculations-Graph.png 1123w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/09\/Example-Calculations-Graph-300x98.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/09\/Example-Calculations-Graph-1024x336.png 1024w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/09\/Example-Calculations-Graph-768x252.png 768w\" sizes=\"(max-width: 1123px) 100vw, 1123px\" \/><\/p>\n<p class=\"\" style=\"text-align: center;\"><strong>Figure 3: Intelligent Graph Data Analysis<\/strong><\/p>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Why is the IntelligentGraph approach so advantageous?<\/span><\/h2>\n<ul class=\"\">\n<li><span style=\"font-weight: 400;\">There is no separation between data and analysis, removing the risk of stale and inaccurate data and calculations.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">The calculations embedded within the graph can take advantage of the knowledge that is contained within that graph. This makes the calculations far simpler than those that need to be embedded in spreadsheets.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">The calculations will automatically utilize on the fly the changing knowledge.<\/span><\/li>\n<\/ul>\n<h1 class=\"\">How does IntelligentGraph Work?<\/h1>\n<p class=\"\"><span style=\"font-weight: 400;\">Analysis is embedded in an IntelligentGraph simply by adding script literals as object values of subjects with datatype of the scripting language (groovy, javascript, python etc).<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">The IntelligentGraph engine is provided as an <\/span><a href=\"https:\/\/rdf4j.org\/documentation\/reference\/sail\/\"><span style=\"font-weight: 400;\">RDF4J Stackable SAIL<\/span><\/a><span style=\"font-weight: 400;\">. This means that its capabilities can be combined with any other RDF4J capabilities. The choice of <\/span><a href=\"https:\/\/rdf4j.org\/about\/\"><span style=\"font-weight: 400;\">RDF storage<\/span><\/a><span style=\"font-weight: 400;\"> remains the same as for any other RDF4J compliant framework.<\/span><\/p>\n<h2 class=\"\">Modeling with Scripts<\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">Typically, a graph node will have associated attributes with values, such as a stream with volumeFlow and density values:<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">Stream Attributes:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">:Stream_1<\/span>\r\n<span style=\"font-weight: 400;\">   :density \".36\"^^xsd:float ;<\/span>\r\n<span style=\"font-weight: 400;\">   :volumeFlow \"40\"^^xsd:float .<\/span><\/pre>\n<p><i><span style=\"font-weight: 400;\">Of course, in the \u2018real-world\u2019 these measured values are sourced from outside the KnowledgeGraph and change over time. IntelligentGraph can deal with both of these requirements.<\/span><\/i><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">The \u2018model\u2019 of the streams can be captured as edges associated with the Unit:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">:Unit_1<\/span>\r\n<span style=\"font-weight: 400;\">   :hasProductStream :Stream_1 ;<\/span>\r\n<span style=\"font-weight: 400;\">   :hasProductStream :Stream_2 ;<\/span>\r\n<span style=\"font-weight: 400;\">.<\/span><\/pre>\n<h3><span style=\"font-weight: 400;\">Calculate Mass Flow<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">The calculations are declared as literals[1] with a datatype whose local name corresponds to one of the installed script languages:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">:Stream_1 :massFlow<\/span> <span style=\"font-weight: 400;\">&nbsp; &nbsp; \r\n    \"_this.getFact(':density')*<\/span> <span style=\"font-weight: 400;\">&nbsp; &nbsp;\r\n     _this.getFact(':volumeFlow');\"^^:groovy .<\/span><\/pre>\n<h3><span style=\"font-weight: 400;\">Calculate Total Production<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">A typical performance metric is to understand the total production from a unit, which is not of course directly measured. However, it can be easily expressed using existing calculated values:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">:Unit_1 &nbsp; :totalProduction<\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; \"var totalProduction =0.0;<\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; for(Resource stream : _this.getFacts(':hasProductStream'))<\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; {<\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; &nbsp; &nbsp; totalProduction += stream.getFact(':massFlow');<\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; }<\/span>\r\n<span style=\"font-weight: 400;\">  &nbsp; return totalProduction; \"^^:groovy .<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">Instead of returning the object literal value (aka the script), the IntelligentGraph will return the result value for the script.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">We can write this script even more succinctly using the expressive power PathQL:<\/span><\/p>\n<pre style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">:Unit_1&nbsp; :totalProduction<\/span><span style=\"font-weight: 400;\">&nbsp; <\/span>\r\n<span style=\"font-weight: 400;\">&nbsp; &nbsp; \"return _this.getFacts(':hasProductStream\/:massFlow').total(); \"^^:groovy<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">However, IntelligentGraph allows us to build upon existing calculations to simply express what would normally be difficult-to-calculate metrics, such as product yield or mass balance.<\/span><\/p>\n<p class=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-3653\" src=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended.png\" alt=\"\" width=\"1943\" height=\"831\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended.png 1943w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended-300x128.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended-1024x438.png 1024w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended-768x328.png 768w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/Example-Calculations-Graph-extended-1536x657.png 1536w\" sizes=\"(max-width: 1943px) 100vw, 1943px\" \/><\/p>\n<h3 class=\"\"><span style=\"font-weight: 400;\">Calculate Mass Yield<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Any production unit has different valued products. So a key metric is the yield of individual streams. This can easily be calculated as follows, using values that are themselves calculations.<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">var<\/span> <span style=\"font-weight: 400;\">result<\/span><span style=\"font-weight: 400;\">= _this.getFact(<\/span><span style=\"font-weight: 400;\">\":massFlow\"<\/span><span style=\"font-weight: 400;\">).floatValue()\/ \r\n_this.getFact(<\/span><span style=\"font-weight: 400;\">\"^:hasStream\/:totalProduction\"<\/span><span style=\"font-weight: 400;\">).floatValue();&nbsp; <\/span>\r\n<span style=\"font-weight: 400;\">result<\/span><span style=\"font-weight: 400;\">;<\/span><\/pre>\n<h3 class=\"\"><span style=\"font-weight: 400;\">Calculate Mass Balance<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Measurements are not perfect, nor is the operation of a unit. One of the first indicators of a problem is when the mass flow in does not match the mass flow out. This can be expressed as another calculated property of a Unit:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">return<\/span><span style=\"font-weight: 400;\">&nbsp; <\/span><span style=\"font-weight: 400;\">_this<\/span><span style=\"font-weight: 400;\">.getFacts<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">\":hasFeedStream\/massFlow\"<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">.total<\/span><span style=\"font-weight: 400;\">() <\/span><span style=\"font-weight: 400;\">-_this<\/span><span style=\"font-weight: 400;\">.getFacts<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">\":totalProduction\"<\/span><span style=\"font-weight: 400;\">)<\/span><span style=\"font-weight: 400;\">.total<\/span><span style=\"font-weight: 400;\">();<\/span><\/pre>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Querying Results<\/span><\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">Access to the calculated values is via standard-SPARQL. However instead of returning the script literal, IntelligentGraph will invoke the script engine,&nbsp;<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">Thus to access the :massFlow calculated value, the SPARQL is simply:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">select <\/span><span style=\"font-weight: 400;\">?massFlow<\/span>\r\n<span style=\"font-weight: 400;\">{<\/span>\r\n <span style=\"font-weight: 400;\">:<\/span><span style=\"font-weight: 400;\">Stream_1 <\/span><span style=\"font-weight: 400;\">:massFlow ?massFlow <\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">If the script literal is required then the object variable can be postfixed with _SCRIPT:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">select <\/span><span style=\"font-weight: 400;\">?massFlow ?massFlow_SCRIPT <\/span>\r\n<span style=\"font-weight: 400;\">{<\/span>\r\n <span style=\"font-weight: 400;\">:<\/span><span style=\"font-weight: 400;\">Stream_1 <\/span><span style=\"font-weight: 400;\">:massFlow ?massFlow, ?massFlow_SCRIPT <\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">If a full trace of the calculation, including tracing calls to other scripts, is required then the object variable can be postfixed with _TRACE:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">select <\/span><span style=\"font-weight: 400;\">?massFlow ?massFlow_TRACE <\/span>\r\n<span style=\"font-weight: 400;\">{<\/span>\r\n <span style=\"font-weight: 400;\">:<\/span><span style=\"font-weight: 400;\">Stream_1 <\/span><span style=\"font-weight: 400;\">:massFlow ?massFlow, ?massFlow_TRACE <\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/pre>\n<h1 class=\"\"><span style=\"font-weight: 400;\">How to Write IntelligentGraph Scripts?<\/span><\/h1>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Script Languages<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Any <\/span><a href=\"https:\/\/docs.oracle.com\/javase\/9\/scripting\/java-scripting-api.htm#JSJSG109\"><span style=\"font-weight: 400;\">Java 9<\/span><\/a><span style=\"font-weight: 400;\"> supported language can be used simply by making the corresponding language JAR available.&nbsp;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">By default, JavaScript, Groovy, Python JAR are installed. The complete list of compliant languages is as follows<\/span><\/p>\n<p class=\"\" style=\"padding-left: 40px;\"><span style=\"font-weight: 400;\">AWK, BeanShell, ejs, FreeMarker, Groovy, Jaskell, Java, JavaScript, JavaScript (Web Browser), Jelly, JEP, Jexl, jst, JudoScript, JUEL, OGNL, Pnuts, Python, Ruby, Scheme, Sleep, Tcl, Velocity, XPath, XSLT, JavaFX Script, ABCL, AppleScript, Bex script, OCaml Scripting Project, PHP, Python, Smalltalk, CajuScript, MathEclipse<\/span><\/p>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Script Context Variables<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">In addition, each script has access to the following predefined variables that allow the script to access the context within which it is being run.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>_this<\/b><span style=\"font-weight: 400;\">, a Thing corresponding to the subject of the triples for which the script is the object. &nbsp;Since this available, helper functions are provided to navigate edges to or from this \u2018thing\u2019 below:<\/span><\/li>\n<\/ul>\n<ul class=\"\">\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>_property<\/b><span style=\"font-weight: 400;\">, a Thing corresponding to the predicate or property of the triples for which the script is the object.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>_customQueryOptions<\/b><span style=\"font-weight: 400;\">, a HashMap&lt;String, Value&gt; of name\/value pairs corresponding to the pairs of additional arguments to the SPARQL extension function. These are useful for passing application-specific parameters.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>_builder<\/b><span style=\"font-weight: 400;\">, a <\/span><a href=\"https:\/\/rdf4j.org\/javadoc\/latest\/org\/eclipse\/rdf4j\/model\/util\/ModelBuilder.html\"><span style=\"font-weight: 400;\">RDF4J graph builder<\/span><\/a><span style=\"font-weight: 400;\"> object allowing a graph to be constructed (and manipulated) within the script. A graph cannot be returned from a SPARQL function. However the IRI of the graph can be returned, and any graph created by a script will be persisted.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>_tripleSource<\/b><span style=\"font-weight: 400;\">, the <\/span><a href=\"https:\/\/rdf4j.org\/javadoc\/latest\/org\/eclipse\/rdf4j\/query\/algebra\/evaluation\/TripleSource.html\"><span style=\"font-weight: 400;\">RDF4J TripleSource<\/span><\/a><span style=\"font-weight: 400;\"> to which the subject, predicate, triple belongs.<\/span><\/li>\n<\/ul>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Fact and Path Functions<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The spreadsheets\u2019 secret sauce is the ability of a cell formula to access values of other cells, either individually or as a set. The IntelligentGraph provides this functionality with several methods associated with Thing, which are applicable to the _this Thing initiated for each script with the subject Thing.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Thing.getFact(String pathPattern) returns Value<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Returns the value of node referenced by the pathPattern, for example \u201c:volumeFlow\u201d returns the object value of the :<\/span><span style=\"font-weight: 400;\">volumeFlow<\/span><span style=\"font-weight: 400;\"> edge relative to _this node. The pathPattern allows for more complex path navigation.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Thing.getFacts(String pathPattern) returns Values<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Returns the values of nodes referenced by the pathPattern, for example \u201c:<\/span><span style=\"font-weight: 400;\">hasProductStream<\/span><span style=\"font-weight: 400;\">\u201d returns an iterator for all object values of the :<\/span><span style=\"font-weight: 400;\">hasProductStream<\/span><span style=\"font-weight: 400;\"> edge relative to _this node. The pathPattern allows for more complex path navigation.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Thing.getPath(String pathQL) returns Path<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Returns the first (shortest)&nbsp; path referenced by the pathQL, for example \u201c<\/span><span style=\"font-weight: 400;\">:parent{1..5}<\/span><span style=\"font-weight: 400;\">\u201d returns the path to the first ancestor of _this node. The pathQL allows for more complex path navigation.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Thing.getPaths(String pathQL) returns PathResults<\/span><\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Returns all paths referenced by the pathQL, for example<\/span> <span style=\"font-weight: 400;\">\u201c<\/span><span style=\"font-weight: 400;\">:parent{1..5}<\/span><span style=\"font-weight: 400;\">\u201d returns an iterator, starting with the shortest path,&nbsp; for all paths to the ancestors of _this node. The pathQL allows for more complex path navigation.<\/span><\/p>\n<h2 class=\"\">Path Patterns<\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">Spreadsheets are not limited to accessing just adjacent cells; neither is the IntelligentGraph. PathPatterns provide a powerful way of navigating from one Thing node to another. PathPatterns are inspired by<\/span><a href=\"https:\/\/www.w3.org\/TR\/sparql11-query\/#propertypaths\"> <span style=\"font-weight: 400;\">SPARQL and propertyPaths<\/span><\/a><span style=\"font-weight: 400;\">, but a richer, more expressive, PathQL was required for the IntelligentGraph.<\/span><\/p>\n<h3 class=\"\">Examples<\/h3>\n<p class=\"\"><span style=\"font-weight: 400;\">Examples of PathQL patterns are as follows:<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFact(\u201c:hasParent\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the first parent of $this.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFact(\u201c^:hasParent\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the first child of $this.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent\/:hasParent\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the grandparents of $this.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent\/^:hasParent\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the siblings of $this.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent[:gender :female]\/:hasParent\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the maternal grandparents of $this<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent[:gender :female]\/:hasParent[:gender :male]\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the maternal grandfather of $this.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent[:gender [ rdfs:label \u201cfemale\u201d]]\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the mother of $this but using the label instead of the IRI.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent[eq :Peter]\/:hasParent[:gender :male]\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return the grandfather of $this, who is the parent of :Peter.<\/span><\/p>\n<pre class=\"\"><span style=\"font-weight: 400;\">_this.getFacts(\u201c:hasParent[ne :Peter]\/:hasParent[:gender :male]\u201d)<\/span><\/pre>\n<p class=\"\"><span style=\"font-weight: 400;\">will return grandfathers of $this, who are not the parent of :Peter.<\/span><\/p>\n<p class=\"\">The following diagram visualizes a path through a genealogical graph, from _this to the find the parents of a maternal grandfather born in Maidstone:<\/p>\n<pre class=\"\">_this.getFacts(\u201c\/:parent[:gender :female]\/:parent[:gender :male, :birthplace [rdfs:label \u2018Maidstone\u2019]]\/:parent\u201d)<\/pre>\n<p class=\"\">&nbsp;<\/p>\n<p class=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-2764\" src=\"http:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/PathPatternExample2.png\" alt=\"\" width=\"1274\" height=\"846\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/PathPatternExample2.png 1274w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/PathPatternExample2-300x199.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/PathPatternExample2-1024x680.png 1024w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/PathPatternExample2-768x510.png 768w\" sizes=\"(max-width: 1274px) 100vw, 1274px\" \/><\/p>\n<p class=\"\" style=\"text-align: center;\"><strong>Figure 4: PathPatternQL Example<\/strong><\/p>\n<h1 class=\"\">How Is Performance?<\/h1>\n<p><span style=\"font-weight: 400;\">IntelligentGraph takes the following actions to improve performance:<\/span><\/p>\n<ol class=\"\">\n<li><span style=\"font-weight: 400;\">All intermediate calculation results are cached, keyed by the subjectNode, predicate, and customQueryOptions.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Cache can be cleared using the SPARQL function ClearCache.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">The SPARQL function ObjectValue takes as its argument the subject, predicate and objectValue. If the objectValue supplied is not of script datatype, the function will immediately return the objectValue.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Circular functions, in which A calls B calls A, are detected and rejected.<\/span><\/li>\n<\/ol>\n<h1 class=\"\">Can I Debug?<\/h1>\n<p class=\"\"><span style=\"font-weight: 400;\">Since IntelligentGraph combines calculations with the knowledge graph, it is inevitable that any evaluation will involve calls to values of other nodes which are in turn calculations. For this reason,&nbsp; IntelligenrtGraph supports tracing and debugging:<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">&nbsp;<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\"> <img loading=\"lazy\" class=\"alignnone size-full wp-image-2702\" src=\"http:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/EmbeddEdCalcDebugging.png\" alt=\"\" width=\"1366\" height=\"892\" srcset=\"https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/EmbeddEdCalcDebugging.png 1366w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/EmbeddEdCalcDebugging-300x196.png 300w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/EmbeddEdCalcDebugging-1024x669.png 1024w, https:\/\/inova8.com\/bg_inova8.com\/wp-content\/uploads\/2021\/02\/EmbeddEdCalcDebugging-768x502.png 768w\" sizes=\"(max-width: 1366px) 100vw, 1366px\" \/><\/span><\/p>\n<p class=\"\" style=\"text-align: center;\"><span style=\"font-weight: 400;\">Figure 4: Tracing Calculation<\/span><\/p>\n<h1 class=\"\">How Do I Add Intelligence to my RDFGraph?<\/h1>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Download<\/span><\/h2>\n<p class=\"\"><span style=\"font-weight: 400;\">The project is located in Github, from where the <\/span><a href=\"https:\/\/github.com\/peterjohnlawrence\/com.inova8.intelligentgraph\"><span style=\"font-weight: 400;\">intelligentgraph.jar<\/span><\/a><span style=\"font-weight: 400;\"> can be downloaded from there:<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">The intelligentgraph.jar does not include all of the scripting etc language dependencies, so to use it you would have to be certain all dependencies are already available.<\/span><\/p>\n<h2 class=\"\"><span style=\"font-weight: 400;\">Install<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">IntelligentGraphwill work only with RDF4J version 3.3.0 and above.&nbsp;<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">Copy intelligentgraph.jar<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To&nbsp; \/usr\/local\/tomcat\/webapps\/rdf4j-server\/WEB-INF\/lib\/intelligentgraph.jar<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">The RDF4J server will need to be restarted for it to recognize this new JAR and initiate the scripting engine.<\/span><\/p>\n<p class=\"\"><span style=\"font-weight: 400;\">[1]<\/span><span style=\"font-weight: 400;\"> In this case the script uses Groovy, but any<\/span><a href=\"https:\/\/docs.oracle.com\/javase\/9\/scripting\/java-scripting-api.htm#JSJSG109\"> <span style=\"font-weight: 400;\">Java 9 compliant<\/span><\/a><span style=\"font-weight: 400;\"> scripting language can be used, such as JavaScript, Python, Ruby, and many more.<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>IntelligentGraph embeds calculation and analysis capability within RDF knowledge graphs, rather than forcing analysis to be undertaken by exporting query results to external analysis applications such as Excel. IntelligentGraph achieves this by embedding scripts into the RDF knowledge graph which are evaluated when queried with SPARQL. Scripts, written in a variety of languages such as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2740,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"bgseo_title":"","bgseo_description":"","bgseo_robots_index":"index","bgseo_robots_follow":"follow","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[16,21,50,15,14,17,8,24,18,1],"tags":[51,52,54,55,53,44,57,34,58],"_links":{"self":[{"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/posts\/2697"}],"collection":[{"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/comments?post=2697"}],"version-history":[{"count":39,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/posts\/2697\/revisions"}],"predecessor-version":[{"id":3655,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/posts\/2697\/revisions\/3655"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/media\/2740"}],"wp:attachment":[{"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/media?parent=2697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/categories?post=2697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inova8.com\/bg_inova8.com\/wp-json\/wp\/v2\/tags?post=2697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}