Source for file InfModelB.php

Documentation is available at InfModelB.php

  1. <?php
  2. // ----------------------------------------------------------------------------------
  3. // Class: InfModelB
  4. // ----------------------------------------------------------------------------------
  5.  
  6. /**
  7. * A InfModelB extends the InfModel Class, with a backward chaining algorithm.
  8. * Only the loaded or added base-triples are stored.
  9. * A find-query evaluates the inference rules and recursively tries to find the statements.
  10. * InfModelB memorises "Dead-Ends" until the next add() command, thus
  11. * makin a second find much faster.
  12. * InfModelB is safe for loops in Ontologies, that would cause infinite loops.
  13. * WARNING: A find(null,null,null) might take very long.
  14. *
  15. @version  $Id: fsource_infModel__infModelInfModelB.php.html 442 2007-06-01 16:19:26Z cax $
  16. @author Daniel Westphal <mail at d-westphal dot de>
  17.  
  18. *
  19. @package infModel
  20. @access    public
  21. ***/
  22.  
  23. class InfModelB extends InfModel 
  24. {
  25.  
  26.     /**
  27.     * Array that holds combinations of inference rules with distinct
  28.     * find-querys, that don't lead to any inference.
  29.     *
  30.     * @var        array 
  31.     * @access    private
  32.     */
  33.      var $findDeadEnds;
  34.      
  35.          
  36.        /**
  37.     * Constructor
  38.     * You can supply a base_uri
  39.     *
  40.     * @param string $baseURI 
  41.     * @access    public
  42.     */    
  43.      function InfModelB($baseURI null)
  44.      {
  45.          parent::InfModel($baseURI);
  46.          $this->findDeadEnds=array();    
  47.      }
  48.     
  49.     /**
  50.     * Adds a new triple to the Model without checking, if the statement
  51.     * is already in the Model. So if you want a duplicate free Model use
  52.     * the addWithoutDuplicates() function (which is slower then add())
  53.     *
  54.     * @param    object Statement    $statement 
  55.     * @access    public
  56.     * @throws    PhpError
  57.     */     
  58.      function add($statement)
  59.      {
  60.          parent::add($statement);
  61.          //Reset the found dead-ends.
  62.          $this->findDeadEnds=array();    
  63.      }
  64.      
  65.     /**
  66.     * General method to search for triples.
  67.     * NULL input for any parameter will match anything.
  68.     * Example:  $result = $m->find( NULL, NULL, $node );
  69.     * Finds all triples with $node as object.
  70.     * Returns an empty MemModel if nothing is found.
  71.     * To improve the search speed with big Models, call index(INDEX_TYPE)
  72.     * before seaching.
  73.      *
  74.     * It recursively searches in the statements and rules to find
  75.     * matching statements.
  76.     *
  77.     * @param    object Node    $subject 
  78.     * @param    object Node    $predicate 
  79.     * @param    object Node    $object 
  80.     * @return    object MemModel 
  81.     * @access    public
  82.     * @throws    PhpError
  83.     */
  84.     function find($subject,$predicate,$object
  85.     {
  86.         $searchStringIndex=array();
  87.         $resultModel=new MemModel();
  88.         
  89.         //add all infered statements without duplicates to the result model
  90.         foreach ($this->_infFind($subject,$predicate,$object,array())as $statement)
  91.         {
  92.             $resultModel->addWithoutDuplicates($statement);    
  93.         };
  94.         return $resultModel;
  95.     }
  96.  
  97.     /**
  98.      * This is the main inference method of the InfModelB
  99.      * The algorithm works as follows:
  100.      * Find all statements in the base model, that matches the current
  101.      * find-query.
  102.      * Check all rules, if they are able to deliver infered statements,
  103.      * that match the current find-query. Don't use rules with queries,
  104.      * that lead to dead-ends and don't use a rule-query-combination that
  105.      * was used before in this branch (ontology loops).
  106.      * If a rule is possible do deliver such statements, get a new
  107.      * find-query, that is possible to find those statements, that are able
  108.      * to trigger this rule.
  109.      * Call this _infFind method wirh the new find-query and entail the
  110.      * resulting statements.
  111.      * If this rule, wasn't able to return any statements with this distinct
  112.      * query, add this combination to the dead-ends.
  113.      * Return the statements from the base triples and those, which were infered.
  114.      *
  115.      * If $findOnlyFirstMatching is set to true, only the first match in
  116.      * the base-statements is entailed an returned (used in contains() and
  117.      * findFirstMatchingStatement() methods).
  118.      *
  119.      * You can set an offset to look for the first matching statement by setting the
  120.      * $offset var.
  121.      * 
  122.     * It recursively searches in the statements and rules to find matching
  123.     * statements
  124.     *
  125.     * @param    object Node    $subject 
  126.     * @param    object Node    $predicate 
  127.     * @param    object Node    $object 
  128.     * @param    array        $searchStringIndex 
  129.     * @param    boolean     $findOnlyFirstMatching 
  130.     * @param    integer     $offset 
  131.     * @param    integer     $resultCount 
  132.     * @return    object array Statements
  133.     * @access    private
  134.     */
  135.     function _infFind ($subject,$predicate,$object$searchStringIndex$findOnlyFirstMatching false$offset 0,$resultCount )
  136.     {
  137.         $return=array();
  138.         //Find all matching statements in the base statements
  139.         $findResult=parent::find($subject,$predicate,$object);
  140.         //For all found statements
  141.         foreach ($findResult->triples as $statement)
  142.             {
  143.                 $return[]=$statement;
  144.                 $resultCount++;
  145.  
  146.                 //Return, if only the firstMatchingStatement was wanted
  147.                 if ($findOnlyFirstMatching && $resultCount $offset)
  148.                     return $return;
  149.             };
  150.             
  151.         //Don't infer statements about the schema (rdfs:subClass, etc..)
  152.         //is false
  153.         if ($predicate == null || 
  154.             (is_a($predicate,'Node'&& 
  155.             !in_array($predicate->getLabel(),$this->supportedInference))
  156.             )
  157.             //Check only Rules, that the EntailmentIndex returned.
  158.                foreach ($this->_findRuleEntailmentInIndex($subject,$predicate,$objectas $ruleKey)
  159.             {
  160.                 $infRule=$this->infRules[$ruleKey];
  161.                 $serializedRuleStatement=$ruleKey.serialize($subject).serialize($predicate).serialize($object);
  162.                 //If it is to ontology loop and no dead-end
  163.                 if (!in_array($serializedRuleStatement$searchStringIndex&& 
  164.                     !in_array($serializedRuleStatement$this->findDeadEnds))
  165.                 {    
  166.                     //Keep this distinct rule query cobination for 
  167.                     //this branch to detect loops
  168.                     $searchStringIndex[]=$serializedRuleStatement;    
  169.                     
  170.                     //If the rule is able to deliver statements that match 
  171.                     //this query
  172.                     if ($infRule->checkEntailment($subject,$predicate,$object))
  173.                     {
  174.                         //Get a modified find-query, that matches statements, 
  175.                         //that trigger this rule
  176.                         $modefiedFind=$infRule->getModifiedFind($subject,$predicate,$object);
  177.                         //Call this method with the new find-query
  178.                         $infFindResult=$this->_infFind($modefiedFind['s'],
  179.                                                         $modefiedFind['p'],
  180.                                                         $modefiedFind['o']
  181.                                                         $searchStringIndex
  182.                                                         $findOnlyFirstMatching,
  183.                                                         $offset,
  184.                                                         $resultCount;
  185.                         //If it deliverd statements that matches the trigger
  186.                         if (isset($infFindResult[0]))
  187.                         {
  188.                             foreach ($infFindResult as $statement)
  189.                             {    
  190.                                 //Entail the statements and check, if they are not about the 
  191.                                 //ontology
  192.                                 $newStatement=$infRule->entail($statement);
  193.                                 if (!in_array($newStatement->getLabelPredicate(),$this->supportedInference))
  194.                                     //Check if, the entailed statements are, what we are looking for
  195.                                     if($this->_nodeEqualsFind($subject,$newStatement->getSubject()) && 
  196.                                         $this->_nodeEqualsFind($predicate,$newStatement->getPredicate()) && 
  197.                                         $this->_nodeEqualsFind($object,$newStatement->getObject() ) )
  198.                                     {
  199.                                         //Add to results
  200.                                         $return[]=$newStatement;
  201.                                         $resultCount++;
  202.                                         
  203.                                         //or return at once
  204.                                         if ($findOnlyFirstMatching && $resultCount $offset)
  205.                                             return $return;
  206.                                     }
  207.                                }
  208.                         else 
  209.                         {
  210.                             //If there were no results of the rule-query-combination, 
  211.                             //mark this combination as a dead-end.
  212.                             $this->findDeadEnds[]=$serializedRuleStatement;
  213.                         }
  214.                     }
  215.                 }    
  216.         }
  217.         //Return the array of the found statements
  218.         return $return;    
  219.     }
  220.     
  221.      /**
  222.     * Tests if the Model contains the given triple.
  223.     * TRUE if the triple belongs to the Model;
  224.     * FALSE otherwise.
  225.     * 
  226.     * @param    object Statement    &$statement 
  227.     * @return    boolean 
  228.     * @access    public
  229.     */
  230.     function contains(&$statement
  231.     {
  232.     //throws an error, if $statement is not of class Statement
  233.     if(!is_a($statement,'Statement'))
  234.         trigger_error(RDFAPI_ERROR '(class: InfModelB; method: contains): 
  235.             $statement has to be object of class Statement'E_USER_ERROR);    
  236.     
  237.     //Call the _infFind method, but let it stop, if it finds the first match.    
  238.     if (count$this->_infFind($statement->getSubject(),
  239.                                 $statement->getPredicate(),
  240.                                 $statement->getObject(),
  241.                                 array(),true) ) >0)
  242.         {
  243.             return true;
  244.         else 
  245.         {
  246.             return false;
  247.         };
  248.     }
  249.     
  250.   /**
  251.    * Searches for triples and returns the first matching statement.
  252.    * NULL input for any parameter will match anything.
  253.    * Example:  $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
  254.    * Returns the first statement of the MemModel where the object equals $node.
  255.    * Returns an NULL if nothing is found.
  256.    * You can define an offset to search for. Default = 0
  257.    *
  258.    * @param    object Node    $subject 
  259.    * @param    object Node    $predicate 
  260.    * @param    object Node    $object 
  261.    * @param    integer    $offset 
  262.    * @return    object Statement 
  263.    * @access    public
  264.    */
  265.    function findFirstMatchingStatement($subject$predicate$object$offset 0
  266.     {
  267.         //Call the _infFind method, but let it stop, if it finds the 
  268.         //first match.    
  269.            $res$this->_infFind($subject,$predicate,$object,array(),true,$offset);
  270.                
  271.         if (isset($res[$offset]))
  272.         {
  273.             return $res[$offset];
  274.         else 
  275.         {
  276.             return NULL;
  277.         };
  278.     }  
  279.  
  280.     /**
  281.     * Returns a StatementIterator for traversing the Model.
  282.     *
  283.     * @access    public
  284.     * @return    object    StatementIterator 
  285.     */  
  286.     function getStatementIterator(
  287.     {
  288.         // Import Package Utility
  289.             include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
  290.         // Gets a MemModel by executing a find(null,null,null) to get a 
  291.         //inferable statements.    
  292.         // WARNING: might be slow
  293.         return new StatementIterator($this->getMemModel());
  294.     }    
  295.     
  296.     /**
  297.     * Number of all inferable triples in the Model.
  298.     * WARNING: uses a find(null,null,null) to find all statements! (might take a while)
  299.     * 
  300.     * @param     boolean 
  301.     * @return    integer 
  302.     * @access    public
  303.     */
  304.     function size()
  305.     {
  306.         // Gets a MemModel by executing a find(null,null,null) to get a 
  307.         //inferable statements.    
  308.         // WARNING: might be slow
  309.            $res $this->getMemModel();
  310.            return $res->size();
  311.     }
  312.         
  313.     /**
  314.     * Create a MemModel containing all the triples (including inferred
  315.     * statements) of the current InfModelB.
  316.     *
  317.     * @return object MemModel 
  318.     * @access public
  319.     */
  320.     function getMemModel(
  321.     {
  322.         
  323.         $return=$this->find(null,null,null);
  324.         $return->setBaseURI($this->baseURI);
  325.         $return->addParsedNamespaces($this->getParsedNamespaces());
  326.         return $return;
  327.     }
  328.  
  329.     /**
  330.     * Create a MemModel containing only the base triples (without inferred
  331.     * statements) of the current InfModelB.
  332.     *
  333.     * @return object MemModel 
  334.     * @access public
  335.     */
  336.     function getBaseMemModel(
  337.     {
  338.         $returnnew MemModel();
  339.         $return->setBaseURI($this->baseURI);
  340.         foreach ($this->triples as $statement)
  341.             $return->add($statement);
  342.             
  343.         $retun->addParsedNamespaces($this->getParsedNamespaces());
  344.         return $return;
  345.     }
  346.  
  347.     /**
  348.     * Short Dump of the  InfModelB.
  349.     *
  350.     * @access    public
  351.     * @return    string 
  352.     */  
  353.     function toString(
  354.     {
  355.        return 'InfModelB[baseURI=' $this->getBaseURI(';  size=' $this->size(true']';
  356.     }
  357.  
  358.     /**
  359.     * Dumps of the InfModelB including ALL inferable triples.
  360.     *
  361.     * @access    public
  362.     * @return    string 
  363.     */  
  364.     function toStringIncludingTriples(
  365.     {
  366.            $dump $this->toString(chr(13);
  367.            $stateIt=new StatementIterator($this->find(null,null,null));
  368.         while($statement=$stateIt->next())
  369.         {
  370.                $dump .= $statement->toString(chr(13);
  371.            }
  372.            return $dump;
  373.     }  
  374.  
  375.     /**
  376.     * Saves the RDF,N3 or N-Triple serialization of the full InfModelB
  377.     * (including inferred triples) to a file.
  378.     * You can decide to which format the model should be serialized by
  379.     * using a corresponding suffix-string as $type parameter. If no $type
  380.     * parameter is placed this method will serialize the model to XML/RDF
  381.     * format.
  382.     * Returns FALSE if the InfModelB couldn't be saved to the file.
  383.     *
  384.     * @access    public
  385.     * @param     string     $filename 
  386.     * @param     string     $type 
  387.     * @throws   PhpError
  388.     * @return    boolean 
  389.     */  
  390.     function saveAs($filename$type ='rdf'
  391.     {
  392.     
  393.         $memmodel=$this->getMemModel();
  394.         return $memmodel->saveAs($filename$type);
  395.     
  396.  
  397.     /**
  398.     * Writes the RDF serialization of the Model including ALL inferable
  399.     * triples as HTML.
  400.     *
  401.     * @access    public
  402.     */  
  403.     function writeAsHtml(
  404.     {
  405.             require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
  406.         $ser new RdfSerializer();
  407.         $rdf =$ser->serialize($this->getMemModel());
  408.         $rdf htmlspecialchars($rdfENT_QUOTES);
  409.         $rdf str_replace(' ''&nbsp;'$rdf);
  410.         $rdf nl2br($rdf);
  411.         echo $rdf
  412.     }  
  413.  
  414.     /**
  415.     * Writes the RDF serialization of the Model including ALL inferable
  416.     * triples as HTML table.
  417.     *
  418.     * @access    public
  419.     */  
  420.     function writeAsHtmlTable(
  421.     {
  422.             // Import Package Utility
  423.             include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);               
  424.         RDFUtil::writeHTMLTable($this->getMemModel());
  425.     }  
  426.     
  427.     
  428.     /**
  429.     * Writes the RDF serialization of the Model including ALL inferable
  430.     * triples.
  431.     *
  432.     * @access    public
  433.     * @return    string 
  434.     */  
  435.     function writeRdfToString(
  436.     {
  437.            // Import Package Syntax
  438.         include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);           
  439.         $ser new RdfSerializer();
  440.         $rdf =$ser->serialize($this->getMemModel());
  441.         return $rdf;
  442.     }    
  443.  
  444.     /**
  445.     * Removes the triple from the MemModel.
  446.     * TRUE if the triple is removed.
  447.     * FALSE otherwise.
  448.     *
  449.     * Checks, if it touches any statements, that added inference rules
  450.     * to the model.
  451.     *
  452.     * @param    object Statement    $statement 
  453.     * @return   boolean 
  454.     * @access    public
  455.     * @throws    PhpError
  456.     */
  457.     function remove($statement)
  458.     {
  459.         if (parent::contains($statement))
  460.         {
  461.             if (in_array($statement->getLabelPredicate(),$this->supportedInference));
  462.                 while (count($this->_removeFromInference($statement))>0);
  463.                 
  464.             $this->findDeadEnds=array();
  465.             return parent::remove($statement);
  466.         else 
  467.         {
  468.             return false;
  469.         }
  470.     }
  471.  
  472.     /**
  473.     * Checks, if a single node matches a single find pattern.
  474.     * TRUE if the node matches.
  475.     * FALSE otherwise.
  476.     *
  477.     * Checks, if it touches any statements, that added inference rules
  478.     * to the model.
  479.     *
  480.     * @param    object Statement    $statement 
  481.     * @return   boolean 
  482.     * @access    private
  483.     */
  484.     function _nodeEqualsFind($find$node)
  485.     {
  486.         //If the find pattern is a node, use the nodes equal-method and 
  487.         //return the result.
  488.         if (is_a($find,'Node'))
  489.             return $node->equals($find);
  490.         
  491.         //Null-pattern matches anything.
  492.         if ($find == null)
  493.         {
  494.             return true;
  495.         else 
  496.         {
  497.             return false;
  498.         }
  499.     }
  500.     
  501.     /**
  502.     * Returns a FindIterator for traversing the MemModel.
  503.     * Disabled in InfModelB.
  504.     *
  505.     * @access    public
  506.     * @return    object    FindIterator 
  507.     */  
  508.     function findAsIterator($sub=null,$pred=null,$obj=null{
  509.         $errmsg RDFAPI_ERROR '(class: InfModelB; method: findAsIterator): 
  510.                                     This function is disabled in the
  511.                                     Inference Model';
  512.         trigger_error($errmsgE_USER_ERROR)
  513.     }      
  514. }
  515. ?>

Documentation generated on Fri, 1 Jun 2007 16:49:27 +0200 by phpDocumentor 1.3.2