/** * returns $noOfObjects of the best objects for users in $usersArray * method just pick randomly demanded number of the objects from the allowed ones * @param <type> $usersArray array of (userID => similarity) of the selected users * @param <type> $noOfObjects number of objects, we search for * @param <type> $objectList list of allowed objects * @return <type> array( objectID => similarity: 1 ) ) */ public function getBestObjectForUsers($usersArray, $noOfObjects, $objectList = "") { $table = Config::$objectTableName; $objectIDName = Config::$objectIDColumnName; if (is_array($objectList) and sizeof($objectList) != 0) { $objectQuery = " `" . $objectIDName . "` in ("; $first = 1; foreach ($objectList as $obj) { if ($first) { $first = 0; $objectQuery .= "" . $obj . ""; } else { $objectQuery .= ", " . $obj . ""; } } $objectQuery .= ")"; } else { $objectQuery = " 1 "; } $query = "select distinct `" . $objectIDName . "` from `" . $table . "` where " . $objectQuery . " order by RAND() limit " . $noOfObjects . " "; //echo $query; $database = ComponentDatabase::get_instance(); $qr = $database->executeQuery($query); $objectsList = $qr->getResponseList(); //packing answer into the array if (!$objectsList) { //wrong query $errLog = ErrorLog::get_instance(); $errLog->logError("Wrong SQL query, no prediction made", "Dummy"); return false; } else { $returnlist = array(); while ($record = $database->getNextRow($objectsList)) { $returnlist[$record[$objectIDName]] = 1; } return $returnlist; } }
protected function usersToObjectRate($dbQuery) { $database = ComponentDatabase::get_instance(); $qr = $database->executeQuery($dbQuery); $eventsList = $qr->getResponseList(); //rating objects if (!$eventsList) { //wrong query $errLog = ErrorLog::get_instance(); $errLog->logError("No events of the specified type found, no prediction made", "Standard"); return false; } else { while ($record = $database->getNextRow($eventsList)) { if (array_key_exists($record["objectID"], $this->objectToScoreArray)) { $objectRating = $this->objectToScoreArray[$record["objectID"]]; } else { $objectRating = 0; } if (is_array($this->users) and array_key_exists($record["userID"], $this->users)) { $userImportance = $this->users[$record["userID"]]; } else { $userImportance = 0; } $objectRating = $this->ratingAggregation($objectRating, $record["eventValue"], $record["eventType"], $this->eventImportance, $userImportance); $this->objectToScoreArray[$record["objectID"]] = $objectRating; } } }
/** * returns $noOfObjects of the most similar objects to the $objectID * method counts score of similarity each object O to the object O1 like this: * objectScore O = sum_foreach_user(user_score(O1)*userScore(O)) * this is based on assumption, that any positive score means positive interest in objects, * higher score means higher importance of the interest * @param <type> $noOfObjects number of similar objects, we search for * @param <type> $objectList list of allowed objects * @param <type> $usersArray array of (userID => similarity) of the selected users * @param <type> $implicitEventsList array of calculated implicitEvents * @param <type> $explicitEventsList array of calculated explicitEvents * @return <type> array( objectID => similarity: [0,1] ) ) */ public function getSimilarObjects($objectID, $noOfObjects, $objectList = "", $implicitEventsList = "", $explicitEventsList = "") { $this->objectsToScoreArray = array(); if (is_array($objectList) and sizeof($objectList) != 0) { $objectQuery = " and `o1`.`oid` in ("; $first = 1; foreach ($objectList as $obj) { if ($first) { $first = 0; $objectQuery .= "" . $obj . ""; } else { $objectQuery .= ", " . $obj . ""; } } $objectQuery .= ")"; } else { $objectQuery = ""; } //toto je drobna heuristika - nemelo by byt tak slozite to spocitat a udela to zakladni poradi objektu pro uzivatele a oreze zcela nevhodne objekty $query_objects = "SELECT `o1`.`oid` FROM `vsm_object_model` as `o1` left join `vsm_object_model` as `ref` on (`o1`.`feature`=`ref`.`feature` and `o1`.`oid`!=`ref`.`oid` and `ref`.`oid` = {$objectID}) " . " where 1 {$objectQuery} " . " group by `oid` " . " having sum(`o1`.`relevance`*`ref`.`relevance`)>0" . " order by sum(`o1`.`relevance`*`ref`.`relevance`) desc" . " limit 0," . $noOfObjects * 5 . ""; // echo $query_objects; $database = ComponentDatabase::get_instance(); $qr = $database->executeQuery($query_objects); $objects = $qr->getResponseList(); if (!$objects) { //wrong query $errLog = ErrorLog::get_instance(); $errLog->logError("No object passed the heuristics, no results", "VSM"); return false; } else { $userFeatures = $this->getObjectFeatures($objectID); //feature->similarity while ($record = $database->getNextRow($objects)) { $object_features = $this->getObjectFeatures($record["oid"]); //feature->similarity $similarity = $this->computeCosineSimilarity($userFeatures, $object_features); $this->objectsToScoreArray[$record["oid"]] = $similarity; } } arsort($this->objectsToScoreArray); // print_r($userSimilarity); // echo $noOfUsers; // print_r($this->userToObjectScoreArray); // print_r($this->otherUsersToObjectScoreArray); // print_r(array_slice($this->objectsToScoreArray,0,$noOfObjects, true)); return array_slice($this->objectsToScoreArray, 0, $noOfObjects, true); }
/** * returns $noOfUsers of the best objects from the $objectList * method aggregates object scores in eventValues of events from $aggregatedEventsList * @param <type> $objectID id of the selected object * @param <type> $noOfObjects number of similar objects, we search for * @param <type> $objectList list of allowed objects * @param <type> $aggregatedEventsList array of calculated aggregatedEvents * @return <type> array( objectID => similarity: [0-1]) ) */ public function getBestObjects($noOfObjects, $objectList = "", $aggregatedEventsList = "", $eventsValuesList = "") { $aggregatedTable = Config::$aggregatedEventStorageTable; $implicitTable = Config::$implicitEventStorageTable; $this->eventsArray = $aggregatedEventsList; if ($eventsValuesList != "") { $this->eventImportance = $eventsValuesList; } $this->objectsScoreArray = array(); if (is_array($aggregatedEventsList) and sizeof($aggregatedEventsList) != 0) { if (is_array($objectList) and sizeof($objectList) != 0) { $objectQuery = "and `objectID` in ("; $first = 1; foreach ($objectList as $obj) { if ($first) { $first = 0; $objectQuery .= "" . $obj . ""; } else { $objectQuery .= ", " . $obj . ""; } } $objectQuery .= ")"; } else { $objectQuery = ""; } $implicit_events = array(); $events = array(); foreach ($aggregatedEventsList as $eType) { if (in_array($eType, Config::$recognizedAggregatedEvaluationEvent)) { if ($eType == "opened_vs_shown_fraction") { $events[] = "object_shown_in_list"; $events[] = "object_opened_from_list"; } else { $events[] = $eType; } } } $eventQuery = "`eventType` in ("; $first = 1; foreach ($events as $eType) { if ($first) { $first = 0; $eventQuery .= "\"" . $eType . "\""; } else { $eventQuery .= ", \"" . $eType . "\""; } } $eventQuery .= ")"; $query = "select distinct `objectID`,`eventType`,`eventValue`\n from `" . $aggregatedTable . "`\n where " . $eventQuery . $objectQuery . " order by `objectID`"; //echo $query; $this->rateObjects($query); } else { $errLog = ErrorLog::get_instance(); $errLog->logError("No events specified, no prediction made", "Aggregated"); } arsort($this->objectsScoreArray); //print_r($this->objectsScoreArray); // echo $noOfUsers; // print_r($this->userToObjectScoreArray); // print_r($this->otherUsersToObjectScoreArray); return array_slice($this->objectsScoreArray, 0, $noOfObjects, true); }
/** *Returns set of users, that this heuristic approved to be used in similarity measuring */ private function getUserHeuristics($userID, $table, $eventNames, $objects) { $query = "select `userID`, count(DISTINCT `objectID`) as `count`\n from `" . $table . "`\n where `userID`!=" . $userID . " and " . $eventQueryImplicit . " " . $objects . "\n group by `userID` having `count`>=2"; //echo $query; $database = ComponentDatabase::get_instance(); $qr = $database->executeQuery($query); $eventsList = $qr->getResponseList(); if (!$eventsList) { //wrong query $errLog = ErrorLog::get_instance(); $errLog->logError("No user passed the heuristics, keeping the full no. Of Users", "Standard"); return " "; } else { $result = "and `userID` in ("; $first = 1; while ($record = $database->getNextRow($eventsList)) { if ($first) { $first = 0; $result .= $record["userID"]; } else { $result .= "," . $record["userID"]; } } $result .= " )"; return $result; } }
/** * returns $noOfUsers the most similar object to the one with $objectID * similarity is measured on the specified attributes - in the same way as in the ExtendedQueryHandler * @param <type> $objectID id of the selected object * @param <type> $noOfObjects number of similar objects, we search for * @param <type> $objectList list of allowed objects * @param <type> $attributesSelectionSQL sql code which selects all necesary attributes (the most important is "FROM" part) * @param <type> $attributesList array of Attribute class instances - the attributes which we want to use for measuring the objects distance * @return array( objectID => similarity: [0-1]) ) */ public function getSimilarObjects($objectID, $noOfObjects, $objectList = "", $attributesSelectionSQL = "", $attributesList = "") { if (is_array($attributesList) and sizeof($attributesList) != 0 and $attributesSelectionSQL != "") { $table = Config::$objectTableName; $objectIDName = Config::$objectIDColumnName; $this->sqlObject = new Query($attributesSelectionSQL); $where = $this->sqlObject->getWhere(); if ($where == "") { $where = "where `" . $table . "`.`" . $objectIDName . "`=" . $objectID . " "; } else { $where = $where . " and `" . $table . "`.`" . $objectIDName . "`=" . $objectID . " "; } $select = "select "; $attrNo = 0; $first = true; foreach ($attributesList as $attribute) { if ($first) { $first = false; $select .= " " . $attribute->getAttributeName() . " as `attribute" . $attrNo . "`"; } else { $select .= ", " . $attribute->getAttributeName() . " as `attribute" . $attrNo . "`"; } $attrNo++; } $this->sqlObject->setSelect($select); $this->sqlObject->setWhere($where); //echo $this->sqlObject->getSQL(); $bqHandler = new BasicQueryHandler($this->sqlObject->getSQL()); $bqHandler->sendQuery(); $objectResponse = $bqHandler->getQueryResponse(); if ($objectResponse->getQueryState()) { //we have the attribute values for demanded object $row = $objectResponse->getNextRow(); //print_r($row); $attrNo = 0; foreach ($attributesList as $attribute) { if ($row["attribute" . $attrNo . ""] != "") { $this->attributes[] = new Attribute($attribute->getAttributeName(), $attribute->getAttributeType(), $row["attribute" . $attrNo . ""], $row["attribute" . $attrNo . ""], $attribute->getToleranceFrom(), $attribute->getToleranceTo(), $attribute->getImportance(), $attribute->getExcludeUnsufficient()); } $attrNo++; } if (is_array($objectList) and sizeof($objectList) != 0) { $objectQuery = " `" . $table . "`.`" . $objectIDName . "` in ("; $first = 1; foreach ($objectList as $obj) { if ($first) { $first = 0; $objectQuery .= "" . $obj . ""; } else { $objectQuery .= ", " . $obj . ""; } } $objectQuery .= ")"; } else { $objectQuery = ""; } $this->sqlOtherObjects = new Query($attributesSelectionSQL); $where = $this->sqlOtherObjects->getWhere(); if ($where == "") { $where = "where " . $objectQuery . " and `" . $table . "`.`" . $objectIDName . "`!=" . $objectID . " "; } else { $where = $where . " and " . $objectQuery . " and `" . $table . "`.`" . $objectIDName . "`!=" . $objectID . " "; } $this->sqlOtherObjects->setSelect("select `" . $table . "`.`" . $objectIDName . "` "); $this->sqlOtherObjects->setWhere($where); $this->sqlOtherObjects->setLimit(" limit 0," . $noOfObjects . " "); $sql = $this->sqlOtherObjects->getSQL(); //print_r($sql); //execute query $eqHandler = new ExtendedQueryHandler($sql, $this->attributes); $eqHandler->sendQuery(); $eResponse = $eqHandler->getQueryResponse(); return $this->associateToArray($eResponse); } else { //somthing sinister happend in the database:)) $errLog = ErrorLog::get_instance(); $errLog->logError("Wrong Database query - no prediction made", "Attributes"); return false; } } else { $errLog = ErrorLog::get_instance(); $errLog->logError("No attributes specified or no SQL selecting attributes provided, no prediction made", "Attributes"); } }