source: Dev/branches/rest-dojo-ui/jQueryUI/server/rdfapi/infModel/InfModelF.php @ 312

Last change on this file since 312 was 312, checked in by jkraaijeveld, 13 years ago
File size: 10.6 KB
Line 
1<?php
2// ----------------------------------------------------------------------------------
3// Class: InfModelF
4// ----------------------------------------------------------------------------------
5require_once RDFAPI_INCLUDE_DIR . 'infModel/InfModel.php';
6
7/**
8* A InfModelF extends the InfModel Class, with a forward chaining algorithm. 
9* If a new statement is added, it is enferd at
10* once and all the entailed statements are added too.
11* When adding or removing a statement, that produced a new inference rule,
12* all entailed statements are discarded and the whole base model is infered
13* again.
14* The InfModelF is safe for loops in Ontologies, that would cause infinite loops.
15*
16* @version  $Id: InfModelF.php 575 2008-06-20 12:20:12Z cweiske $
17* @author Daniel Westphal <mail at d-westphal dot de>
18
19*
20* @package infModel
21* @access       public
22**/
23
24class InfModelF extends InfModel
25{
26
27        /**
28        * Array that holds the position of the infered statements in the model.
29        *
30        * @var          array
31        * @access       private
32        */     
33        var $infPos;
34       
35       
36        /**
37        * Variable that influences the habbit when adding statements.
38        * Used by the loadModel method to increase performance.
39        *
40        * @var          boolean
41        * @access       private
42        */
43        var $inferenceEnabled;
44       
45               
46        /**
47    * Constructor
48        * You can supply a base_uri.
49    *
50    * @param string $baseURI
51        * @access       public
52    */         
53        function InfModelF($baseURI = NULL)
54        {
55                parent::InfModel($baseURI);
56                $this->infPos=array();
57                $this->inferenceEnabled=true;   
58        }
59
60        /**
61        * Adds a new triple to the MemModel without checking if the statement
62        * is already in the MemModel.
63        * So if you want a duplicate free MemModel use the addWithoutDuplicates()
64        * function (which is slower then add())
65        * The statement is infered and all entailed statements are added.
66        *
67        * @param        object Statement        $statement
68        * @access       public
69        * @throws       PhpError
70        */
71        function add ($statement)
72        {
73                parent::add($statement);
74                if ($this->inferenceEnabled)
75                {
76                        foreach ($this->entailStatement($statement) as $state)
77                        {
78                                //a addWithoutDublicates construct
79                                if(!$this->contains($state))
80                                {
81                       
82                                        parent::add($state);
83                                        //save the position of the infered statements
84                                        end($this->triples);
85                                        $this->infPos[]=key($this->triples);
86                                };
87                        };
88                //apply the complete inference to the model, if the added statement was able to add a rule
89                if (in_array($statement->getLabelPredicate(),$this->supportedInference))
90                        $this->applyInference();
91                }
92        }
93       
94 
95        /**
96        * Checks if a new statement is already in the MemModel and adds
97        * the statement, if it is not in the MemModel.
98        * addWithoutDuplicates() is significantly slower then add().
99        * Retruns TRUE if the statement is added.
100        * FALSE otherwise.
101        * The statement is infered and all entailed statements are added.
102        *
103        * @param        object Statement        $statement
104        * @return   boolean
105        * @access       public
106        * @throws       PhpError
107        */     
108         function addWithoutDuplicates(& $statement)
109         {
110                if(!$this->contains($statement))
111                {
112                        parent::add($statement);
113                        if ($this->inferenceEnabled)
114                        {
115                                foreach ($this->entailStatement($statement) as $statement)
116                                {
117                                        if(!$this->contains($statement))
118                                                {
119                                                        parent::add($statement);
120                                                        //save the position of the infered statements
121                                                        end($this->triples);
122                                                        $this->infPos[]=key($this->triples);
123                                                };
124                                };
125                        if (in_array($statement->getLabelPredicate(),$this->supportedInference))
126                                $this->applyInference();
127                        }
128                        return true;
129                 }
130                 return false;
131         }
132
133       
134
135        /**
136        * Entails every statement and adds the entailments if not already
137        * in the model.
138        *
139        * @access       private
140        */             
141        function applyInference()
142        {
143                //check every statement in the model
144                foreach ($this->triples as $statement)
145                {
146                        //gat all statements, that it recursively entails
147                        foreach ($this->entailStatement($statement) as $statement)
148                        {
149                                if (!$this->contains($statement))
150                                {
151                                        parent::add($statement);
152                                        //add the InfStatement position to the index
153                                        end($this->triples);
154                                        $this->infPos[]=key($this->triples);
155                                };
156                        };
157                };
158        }
159       
160 
161        /**
162        * Entails a statement by recursively using the _entailStatementRec
163        * method.
164        *
165        * @param        object Statement        $statement
166        * @return   array of statements
167        * @access       public
168        */                     
169        function entailStatement (& $statement)
170        {
171                $infStatementsIndex=array();
172                return $this->_entailStatementRec($statement,$infStatementsIndex);
173        }
174
175        /**
176        * Recursive method, that checks the statement with the trigger of
177        * every rule. If the trigger matches and entails new statements,
178        * those statements are recursively infered too.
179        * The $infStatementsIndex array holds lready infered statements
180        * to prevent infinite loops.
181        *
182        *
183        * @param        object Statement $statement
184        * @param        array $infStatementsIndex
185        * @return   array of statements
186        * @access       private
187        */
188        function _entailStatementRec ( $statement,& $infStatementsIndex)
189        {
190                $infStatements = array();
191                $return = array();
192               
193                //dont entail statements about the supported inference-schema
194                if (!in_array($statement->getLabelPredicate(),$this->supportedInference))
195                {
196                        //check only the rules, that were returned by the index
197                        foreach ($this->_findRuleTriggerInIndex($statement) as $key )
198                        {
199                                $infRule=$this->infRules[$key];
200       
201                                $stateString=$key.serialize($statement);
202                                //If the statement wasn't infered before
203                                if (!in_array($stateString,$infStatementsIndex))
204                                {
205                                        $infStatementsIndex[]=$stateString;
206                                        //Check, if the Statements triggers this rule
207                                        if($infRule->checkTrigger($statement))
208                                        {
209                                                $infStatement=$infRule->entail($statement);
210                                                #if(!$this->contains($infStatement))
211                                                {
212                                                        $return[]=$infStatement;
213                                                        $return=array_merge($return,
214                                                                                                $this->_entailStatementRec($infStatement,
215                                                                                                                                                        $infStatementsIndex));
216                                                };     
217                                                                                                                                               
218                                        };
219                                };
220                        };
221                };     
222                return $return;
223        }
224       
225        /**
226        * Removes all infered statements from the model but keeps the
227        * infernece rules.
228        *
229        * @access       public
230        */       
231        function removeInfered()
232        {
233                $indexTmp=$this->indexed;
234                $this->index(-1);
235                foreach ($this->infPos as $key)
236                {
237                        unset($this->triples[$key]);
238                };
239                $this->infPos=array();
240                $this->index($indexTmp);
241        }       
242         
243         
244        /**
245        * Load a model from a file containing RDF, N3 or N-Triples.
246        * This function recognizes the suffix of the filename (.n3 or .rdf) and
247        * calls a suitable parser, if no $type is given as string
248        * ("rdf" "n3" "nt");
249        * If the model is not empty, the contents of the file is added to
250        * this DbModel.
251        *
252        * While loading the model, the inference entailing is disabled, but
253        * new inference rules are added to increase performance.
254        *
255        * @param        string  $filename
256        * @param        string  $type
257        * @access       public
258        */
259        function load($filename, $type = NULL)
260        {
261                //Disable entailing to increase performance
262                $this->inferenceEnabled=false;
263                parent::load($filename, $type);
264                //Enable entailing
265                $this->inferenceEnabled=true;
266                //Entail all statements
267                $this->applyInference();
268        }
269       
270        /**
271        * Short Dump of the InfModelF.
272        *
273        * @access       public
274        * @return       string
275        */ 
276        function toString() {
277           return 'InfModelF[baseURI=' . $this->getBaseURI() . '; 
278                                size=' . $this->size(true) . ']';
279        }
280               
281        /**
282        * Create a MemModel containing all the triples (including inferred
283        * statements) of the current InfModelF.
284        *
285        * @return object MemModel
286        * @access public
287        */
288        function & getMemModel()
289        {
290                $return= new MemModel();
291                $return->setBaseURI($this->baseURI);
292                foreach ($this->triples as $statement)
293                        $return->add($statement);
294               
295                $return->addParsedNamespaces($this->getParsedNamespaces());     
296                return $return;
297        }
298         
299        /**
300        * Create a MemModel containing only the base triples
301        * (without inferred statements) of the current InfModelF.
302        *
303        * @return object MemModel
304        * @access public
305        */
306        function  getBaseMemModel()
307        {
308                $return= new MemModel();
309                $return->setBaseURI($this->baseURI);
310                foreach ($this->triples as $key => $statement)
311                        if (!in_array($key,$this->infPos))
312                                $return->add($statement);
313                $retun->addParsedNamespaces($this->getParsedNamespaces());
314                return $return;
315        }
316       
317       
318        /**
319        * Removes the triple from the MemModel.
320        * TRUE if the triple is removed.
321        * FALSE otherwise.
322        *
323        * Checks, if it touches any statements, that added inference rules
324        * to the model
325        *
326        * @param        object Statement        $statement
327        * @return   boolean
328        * @access       public
329        * @throws       PhpError
330        */
331        function remove($statement)
332        {
333                //If the statement is in the model
334                if($this->contains($statement))
335                {
336                        $inferenceRulesWereTouched=false;
337                        //If the statement was able to add inference rules
338                        if (in_array($statement->getLabelPredicate(),$this->supportedInference))
339                        {
340                                $statementPositions=$this->_removeFromInference($statement);
341                                $inferenceRulesWereTouched=true;
342                        } else
343                        //get the position of all matching statements
344                        {
345                                $statementPositions=array();
346                                //find the positions of the statements
347                                $statementPosition=-1;
348                                do
349                                {
350                                       
351                                        $statementPosition =
352                                        $this->findFirstMatchOff($statement->getSubject(),
353                                                                                                $statement->getPredicate(),
354                                                                                                $statement->getObject(),
355                                                                                                $statementPosition+1);
356                                                                                               
357                                        if ($statementPosition!=-1)
358                                                $statementPositions[]=$statementPosition;                                                       
359                                                                                               
360                                }       while ($statementPosition != -1);                       
361                        }
362                       
363                        //remove matching statements
364                        parent::remove($statement);
365                        foreach ($statementPositions as $statementPosition)
366                        {
367                                //if the statement was infered, remove it from the index of the infered statements.
368                                if (in_array($statementPosition,$this->infPos))
369                                        unset ($this->infPos[$statementPosition]);
370                        }
371                        if ($inferenceRulesWereTouched)
372                        {
373                                //remove the statement and re-entail the model
374                                $this->removeInfered();
375                                $this->applyInference();
376                        }
377                        return true;
378                } else
379                {
380                        return false;   
381                }
382        }
383       
384        /**
385        * Adds another model to this MemModel.
386        * Duplicate statements are not removed.
387        * If you don't want duplicates, use unite().
388        * If any statement of the model to be added to this model contains a blankNode
389        * with an identifier already existing in this model, a new blankNode is generated.
390        *
391        * @param        object Model    $model
392        * @access       public
393        * @throws phpErrpr
394        *
395        */
396        function addModel(&$model) 
397        {
398                //Disable entailing to increase performance
399                $this->inferenceEnabled=false;
400                parent::addModel($model);
401                //Enable entailing
402                $this->inferenceEnabled=true;
403                //Entail all statements
404                $this->applyInference();
405        }
406};
407?>
Note: See TracBrowser for help on using the repository browser.