/** * @param int $id * @param int $miner * @param int|string $rules * @param bool $inRuleClipboard * @throws BadRequestException * @throws ForbiddenRequestException * @return Rule[] */ private function changeRulesClipboardState($id = null, $miner, $rules, $inRuleClipboard) { $task = $this->tasksFacade->findTask($id); $this->checkMinerAccess($task->miner); $ruleIdsArr = explode(',', str_replace(';', ',', $rules)); $result = array(); if (count($ruleIdsArr) > 0) { foreach ($ruleIdsArr as $ruleId) { try { $rule = $this->rulesFacade->findRule($ruleId); //TODO optimalizovat kontroly... $ruleTask = $rule->task; if ($ruleTask->taskId != $task->taskId) { throw new InvalidArgumentException(); } if ($ruleTask->miner->minerId != $miner) { throw new InvalidArgumentException(); } if ($rule->inRuleClipboard != $inRuleClipboard) { $rule->inRuleClipboard = $inRuleClipboard; $this->rulesFacade->saveRule($rule); } $result[] = $rule; } catch (\Exception $e) { continue; } } } $this->tasksFacade->checkTaskInRuleClipoard($ruleTask); return $result; }
/** * Funkce pro načtení PMML * @param string $pmml * @return bool */ public function parseRulesPMML($pmml) { $xml = simplexml_load_string($pmml); $xml->registerXPathNamespace('guha', 'http://keg.vse.cz/ns/GUHA0.1rev1'); $guhaAssociationModel = $xml->xpath('//guha:AssociationModel'); $guhaAssociationModel = $guhaAssociationModel[0]; /** @var \SimpleXMLElement $associationRulesXml */ $associationRulesXml = $guhaAssociationModel->AssociationRules; if (count($associationRulesXml->AssociationRule) == 0) { return true; } //pokud nejsou vrácena žádná pravidla, nemá smysl zpracovávat cedenty... #region zpracování cedentů jen s jedním subcedentem $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)=1]'); $alternativeCedentIdsArr = array(); if (!empty($dbaItems)) { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; $BARefStr = (string) $dbaItem->BARef; $alternativeCedentIdsArr[$idStr] = isset($alternativeCedentIdsArr[$BARefStr]) ? $alternativeCedentIdsArr[$BARefStr] : $BARefStr; } } if (!empty($alternativeCedentIdsArr)) { $repeat = true; while ($repeat) { $repeat = false; foreach ($alternativeCedentIdsArr as $id => $referencedId) { if (isset($alternativeCedentIdsArr[$referencedId])) { $alternativeCedentIdsArr[$id] = $alternativeCedentIdsArr[$referencedId]; $repeat = true; } } } } #endregion /** @var Cedent[] $cedentsArr */ $cedentsArr = array(); /** @var RuleAttribute[] $ruleAttributesArr */ $ruleAttributesArr = array(); $unprocessedIdsArr = array(); #region zpracování rule attributes $bbaItems = $associationRulesXml->xpath('//BBA'); if (!empty($bbaItems)) { foreach ($bbaItems as $bbaItem) { $ruleAttribute = new RuleAttribute(); //FIXME IMPORTANT změna ukládání ruleAttributes //FIXME IMPORTANT podpora většího množství hodnot v rule attribute $idStr = (string) $bbaItem['id']; $ruleAttribute->field = (string) $bbaItem->FieldRef; $ruleAttribute->value = (string) $bbaItem->CatRef; $ruleAttributesArr[$idStr] = $ruleAttribute; $this->rulesFacade->saveRuleAttribute($ruleAttribute); } } //pročištění pole s alternativními IDčky if (!empty($alternativeCedentIdsArr)) { foreach ($alternativeCedentIdsArr as $id => $alternativeId) { if (isset($ruleAttributesArr[$alternativeId])) { unset($alternativeCedentIdsArr[$id]); } } } #endregion #region zpracování cedentů s více subcedenty/hodnotami $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)>0]'); if (!empty($dbaItems)) { do { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; if (isset($cedentsArr[$idStr])) { continue; } if (isset($alternativeCedentIdsArr[$idStr])) { continue; } if (isset($ruleAttributesArr[$idStr])) { continue; } $process = true; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (!isset($cedentsArr[$BARefStr]) && !isset($ruleAttributesArr[$BARefStr])) { $unprocessedIdsArr[$BARefStr] = $BARefStr; $process = false; } } if ($process) { unset($unprocessedIdsArr[$idStr]); //vytvoření konkrétního cedentu... $cedent = new Cedent(); if (isset($dbaItem['connective'])) { $cedent->connective = Strings::lower((string) $dbaItem['connective']); } else { $cedent->connective = 'conjunction'; } $this->rulesFacade->saveCedent($cedent); $cedentsArr[$idStr] = $cedent; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (isset($cedentsArr[$BARefStr])) { $cedent->addToCedents($cedentsArr[$BARefStr]); } elseif (isset($ruleAttributesArr[$BARefStr])) { $cedent->addToRuleAttributes($ruleAttributesArr[$BARefStr]); } } $this->rulesFacade->saveCedent($cedent); } else { $unprocessedIdsArr[$idStr] = $idStr; } } } while (!empty($unprocessedIdsArr)); } #endregion foreach ($associationRulesXml->AssociationRule as $associationRule) { $rule = new Rule(); $rule->task = $this->task; if (isset($associationRule['antecedent'])) { //jde o pravidlo s antecedentem $antecedentId = (string) $associationRule['antecedent']; if (isset($alternativeCedentIdsArr[$antecedentId])) { $antecedentId = $alternativeCedentIdsArr[$antecedentId]; } $rule->antecedent = $cedentsArr[$antecedentId]; } else { //jde o pravidlo bez antecedentu $rule->antecedent = null; } $consequentId = (string) $associationRule['consequent']; if (isset($alternativeCedentIdsArr[$consequentId])) { $consequentId = $alternativeCedentIdsArr[$consequentId]; } $rule->consequent = $cedentsArr[$consequentId]; $rule->text = (string) $associationRule->Text; $fourFtTable = $associationRule->FourFtTable; $rule->a = (string) $fourFtTable['a']; $rule->b = (string) $fourFtTable['b']; $rule->c = (string) $fourFtTable['c']; $rule->d = (string) $fourFtTable['d']; $this->rulesFacade->saveRule($rule); } $this->rulesFacade->calculateMissingInterestMeasures(); return true; }
/** * Funkce pro načtení PMML * @param string|\SimpleXMLElement $pmml * @param int &$rulesCount = null - informace o počtu importovaných pravidel * @param bool $updateImportedRulesHeads=false * @return bool * @throws \Exception */ public function fullParseRulesPMML($pmml, &$rulesCount = null, $updateImportedRulesHeads = false) { Debugger::log('fullParseRulesPMML start ' . time(), ILogger::DEBUG); if ($pmml instanceof \SimpleXMLElement) { $xml = $pmml; } else { $xml = simplexml_load_string($pmml); } $xml->registerXPathNamespace('guha', 'http://keg.vse.cz/ns/GUHA0.1rev1'); $guhaAssociationModel = $xml->xpath('//guha:AssociationModel'); $guhaAssociationModel = $guhaAssociationModel[0]; $rulesCount = (string) $guhaAssociationModel['numberOfRules']; /** @var \SimpleXMLElement $associationRulesXml */ $associationRulesXml = $guhaAssociationModel->AssociationRules; if (count($associationRulesXml->AssociationRule) == 0) { return true; } //pokud nejsou vrácena žádná pravidla, nemá smysl zpracovávat cedenty... #region zpracování cedentů jen s jedním subcedentem $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)=1]'); $alternativeCedentIdsArr = array(); if (!empty($dbaItems)) { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; $BARefStr = (string) $dbaItem->BARef; $alternativeCedentIdsArr[$idStr] = isset($alternativeCedentIdsArr[$BARefStr]) ? $alternativeCedentIdsArr[$BARefStr] : $BARefStr; } } if (!empty($alternativeCedentIdsArr)) { do { $repeat = false; foreach ($alternativeCedentIdsArr as $id => $referencedId) { if (isset($alternativeCedentIdsArr[$referencedId])) { $alternativeCedentIdsArr[$id] = $alternativeCedentIdsArr[$referencedId]; $repeat = true; } } } while ($repeat); } #endregion /** @var Cedent[] $cedentsArr */ $cedentsArr = []; /** @var RuleAttribute[] $ruleAttributesArr */ $ruleAttributesArr = []; /** @var string[] $unprocessedIdsArr */ $unprocessedIdsArr = []; /** @var ValuesBin[]|Value[] $valuesBinsArr */ $valuesBinsArr = []; /** @var Attribute[] $attributesArr - pole indexované pomocí názvů atributů použitých v PMML */ $attributesArr = $this->miner->metasource->getAttributesByNamesArr(); #region zpracování rule attributes $bbaItems = $associationRulesXml->xpath('//BBA'); if (!empty($bbaItems)) { foreach ($bbaItems as $bbaItem) { $ruleAttribute = new RuleAttribute(); $idStr = (string) $bbaItem['id']; //uložení vazby na Attribute $attributeName = (string) $bbaItem->FieldRef; $valueName = (string) $bbaItem->CatRef; $attribute = $attributesArr[$attributeName]; $ruleAttribute->attribute = $attribute; $valueItem = $attribute->preprocessing->findValue($valueName); if ($valueItem instanceof Value) { $ruleAttribute->value = $valueItem; } elseif ($valueItem instanceof ValuesBin) { $ruleAttribute->valuesBin = $valueItem; } elseif ($attribute->preprocessing->specialType == Preprocessing::SPECIALTYPE_EACHONE) { //pokud jde o preprocessing each-one a nebyla nalezena příslušná hodnota v DB, tak ji uložíme $value = new Value(); $value->format = $attribute->preprocessing->format; $value->value = $valueName; $this->metaAttributesFacade->saveValue($value); $ruleAttribute->value = $value; } $this->rulesFacade->saveRuleAttribute($ruleAttribute); $ruleAttributesArr[$idStr] = $ruleAttribute; } } //pročištění pole s alternativními IDčky if (!empty($alternativeCedentIdsArr)) { foreach ($alternativeCedentIdsArr as $id => $alternativeId) { if (isset($ruleAttributesArr[$alternativeId])) { unset($alternativeCedentIdsArr[$id]); } } } #endregion #region zpracování cedentů s více subcedenty/hodnotami $dbaItems = $associationRulesXml->xpath('./DBA[count(./BARef)>0]'); if (!empty($dbaItems)) { do { foreach ($dbaItems as $dbaItem) { $idStr = (string) $dbaItem['id']; if (isset($cedentsArr[$idStr])) { continue; } if (isset($alternativeCedentIdsArr[$idStr])) { continue; } if (isset($ruleAttributesArr[$idStr])) { continue; } $process = true; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (!isset($cedentsArr[$BARefStr]) && !isset($ruleAttributesArr[$BARefStr])) { $unprocessedIdsArr[$BARefStr] = $BARefStr; $process = false; } } if ($process) { unset($unprocessedIdsArr[$idStr]); //vytvoření konkrétního cedentu... $cedent = new Cedent(); if (isset($dbaItem['connective'])) { $cedent->connective = Strings::lower((string) $dbaItem['connective']); } else { $cedent->connective = 'conjunction'; } $this->rulesFacade->saveCedent($cedent); $cedentsArr[$idStr] = $cedent; foreach ($dbaItem->BARef as $BARef) { $BARefStr = (string) $BARef; if (isset($alternativeCedentIdsArr[$BARefStr])) { $BARefStr = $alternativeCedentIdsArr[$BARefStr]; } if (isset($cedentsArr[$BARefStr])) { $cedent->addToCedents($cedentsArr[$BARefStr]); } elseif (isset($ruleAttributesArr[$BARefStr])) { $cedent->addToRuleAttributes($ruleAttributesArr[$BARefStr]); } } $this->rulesFacade->saveCedent($cedent); } else { $unprocessedIdsArr[$idStr] = $idStr; } } } while (!empty($unprocessedIdsArr)); } #endregion #region association rules /** @var Cedent[] $topCedentsArr - pole s cedenty na vrcholné úrovni (pokud je ruleAttribute přímo na vrcholné úrovni, musí být zabalen v cedentu)*/ $topCedentsArr = array(); foreach ($associationRulesXml->AssociationRule as $associationRule) { $rule = false; if ($updateImportedRulesHeads) { try { $rule = $this->rulesFacade->findRuleByPmmlImportId($this->task->taskId, (string) $associationRule['id']); } catch (\Exception $e) { /*ignore*/ } } if (!$rule) { $rule = new Rule(); } $rule->task = $this->task; #region antecedent if (isset($associationRule['antecedent'])) { //jde o pravidlo s antecedentem $antecedentId = (string) $associationRule['antecedent']; if (isset($alternativeCedentIdsArr[$antecedentId])) { $antecedentId = $alternativeCedentIdsArr[$antecedentId]; } if (isset($cedentsArr[$antecedentId])) { $rule->antecedent = $cedentsArr[$antecedentId]; } else { if (isset($ruleAttributesArr[$antecedentId])) { if (!isset($topCedentsArr[$antecedentId])) { $cedent = new Cedent(); $cedent->connective = 'conjunction'; $this->rulesFacade->saveCedent($cedent); $topCedentsArr[$antecedentId] = $cedent; $cedent->addToRuleAttributes($ruleAttributesArr[$antecedentId]); $this->rulesFacade->saveCedent($cedent); } $rule->antecedent = $topCedentsArr[$antecedentId]; } else { throw new \Exception('Import failed!'); } } } else { //jde o pravidlo bez antecedentu $rule->antecedent = null; } #endregion antecedent #region consequent $consequentId = (string) $associationRule['consequent']; if (isset($alternativeCedentIdsArr[$consequentId])) { $consequentId = $alternativeCedentIdsArr[$consequentId]; } if (isset($cedentsArr[$consequentId])) { $rule->consequent = $cedentsArr[$consequentId]; } else { if (isset($ruleAttributesArr[$consequentId])) { if (!isset($topCedentsArr[$consequentId])) { $cedent = new Cedent(); $cedent->connective = 'conjunction'; $this->rulesFacade->saveCedent($cedent); $topCedentsArr[$consequentId] = $cedent; $cedent->addToRuleAttributes($ruleAttributesArr[$consequentId]); $this->rulesFacade->saveCedent($cedent); } $rule->consequent = $topCedentsArr[$consequentId]; } else { throw new \Exception('Import failed!'); } } #endregion consequent $rule->text = (string) $associationRule->Text; $fourFtTable = $associationRule->FourFtTable; $rule->a = (string) $fourFtTable['a']; $rule->b = (string) $fourFtTable['b']; $rule->c = (string) $fourFtTable['c']; $rule->d = (string) $fourFtTable['d']; $this->rulesFacade->saveRule($rule); } $this->rulesFacade->calculateMissingInterestMeasures($this->task); #endregion association rules Debugger::log('fullParseRulesPMML end ' . time(), ILogger::DEBUG); return true; }