/// Make some consistent parse decision using the Classifier and an oracle. /// If the Classifier makes a correct decision, then we make that. /// Otherwise, we use an oracle to randomly choose /// a consistent decision to perform. void Parser::make_decision_with_oracle(ParseState& state) { Actions actions = state.legal_actions(); assert(!actions.empty()); Action action = this->best_action(state, actions).first; if(state.is_consistent(action)) { Debug::log(5) << "Correctly performing: " << action.to_string() << "\n"; stats::correct_actions_add(1); } else { Debug::log(5) << "Instead of " << action.to_string() << ", "; actions = state.consistent_actions(); assert(!actions.empty()); if (parameter::parse_left_to_right() || parameter::parse_right_to_left()) { assert(actions.size() == 1); } // Randomly choose some consistent action. action = actions.at((unsigned)(drand48() * actions.size())); Debug::log(5) << "oracle chose " << action.to_string() << "\n"; } bool ret = state.perform(action, true); assert(ret); stats::total_actions_add(1); // FIXME: Don't necessarily use _parse_span_chart. _parse_span_chart.subtract(SpanItem(action), _parse_prc, _parse_rcl, _parse_cbs); Debug::warning(__FILE__, __LINE__, this->current_scores()); }
/// Make all consistent parse decisions. /// \param state The state in which the parse decisions should be made. void Parser::make_all_consistent_decisions(ParseState& state) { Actions actions = state.consistent_actions(); assert(!actions.empty()); Debug::log(3) << "Performing " << actions.size() << " consistent decisions...\n"; Actions legal_actions = state.consistent_legal_actions(); Actions illegal_actions = state.consistent_illegal_actions(); assert(legal_actions.size() + illegal_actions.size() == actions.size()); // Output the confidences *before* actually performing any of the actions. // (Otherwise, the confidences values will be tainted.) for (vector<Action>::const_iterator a = legal_actions.begin(); a != legal_actions.end(); a++) Debug::log(3) << "\t" << a->to_string() << " (conf=" << this->confidence(state, *a) << ")\n"; for (vector<Action>::const_iterator a = illegal_actions.begin(); a != illegal_actions.end(); a++) Debug::log(3) << "\t" << a->to_string() << " (ILLEGAL)\n"; for (vector<Action>::iterator a = actions.begin(); a != actions.end(); a++) { Debug::log(4) << "Actually performing " << a->to_string() << "\n"; // TRACE; cerr << state.to_string() << "\n"; // TRACE; cerr << a->to_string() << "\n"; bool b = state.perform(*a); assert(b); // Debug::log(4) << this->m_items.to_string() << "\n"; // Debug::log(9) << this->to_string() << "\n"; } Debug::log(3) << "...done performing " << actions.size() << " consistent decisions.\n"; }
/// Sort actions by their expected likelihood /// WRITEME more documentation /// \todo Make bucket size a parameter /// \todo Don't hardcode children span frequencies void Parser::sort_actions(Actions& actions) const { /// Put all TOP inferences last (first?) Actions top_actions; vector<Actions> sort; /// \todo Make bucket size a parameter unsigned bucketsize = 1000; sort.resize(bucketsize); for (Actions::const_iterator a = actions.begin(); a != actions.end(); a++) { if (a->label() == Label_TOP()) { top_actions.push_back(*a); continue; } double sizefreq = 0; /// \todo Don't hardcode children span frequencies /// We exclude TOP from these frequencies, since it skews the number of unaries switch(a->children().size()) { case 1: sizefreq = 0.231926; break; case 2: sizefreq = 0.565159; break; case 3: sizefreq = 0.147423; break; case 4: sizefreq = 0.0422515; break; case 5: sizefreq = 0.00985868; break; case 6: sizefreq = 0.00269639; break; case 7: sizefreq = 0.000553723; break; case 8: sizefreq = 3.61124e-05; break; case 9: sizefreq = 6.01873e-05; break; case 10: sizefreq = 1.20375e-05; break; case 11: sizefreq = 2.40749e-05; break; default: sizefreq = 0; break; } sizefreq /= 0.565159; double labelfreq = label_frequency(a->label()) / max_label_frequency(); double freq = sizefreq * labelfreq; unsigned bucket = (unsigned)((bucketsize-1) * freq); assert(bucket >= 0 && bucket < bucketsize); sort.at(bucket).push_back(*a); } unsigned actionsize = actions.size(); actions.clear(); //for(vector<Actions>::const_reverse_iterator as = sort.rbegin(); for(vector<Actions>::reverse_iterator as = sort.rbegin(); as != sort.rend(); as++) { actions.insert(actions.end(), as->begin(), as->end()); } // Insert TOP inferences at the end of the list actions.insert(actions.end(), top_actions.begin(), top_actions.end()); assert(actions.size() == actionsize); }
void Actor::setActionToEffectors(Action* action, Action* parent) { GB_ASSERT(action,"Actor::setActionToEffectors: action must be defined"); EffectorIDVector actualNonAcquiredEffectors = action->getAcquiredEffectors(); const EffectorIDVector &requiredEffectors = action->getRequiredEffectors(); //set new action to effectors for (size_t i = 0; i<requiredEffectors.size(); i++) { Effector* effector = getEffector(requiredEffectors[i]); GB_ASSERT(effector, format("Actor::getEffector: actor doesn't have effector %s", \ Effector::convertToString(requiredEffectors[i]))); Actions parentChain; getResponsibleParent(requiredEffectors[i],parent,&parentChain); //insert parents int customPriority = action->getEffectorPriority(requiredEffectors[i]); //case of multiple responsible children if (parentChain.size()==1 && (parent->hasEffectorResponsibleChild(requiredEffectors[i]))) { parent->addResponsibleChildForEffector(requiredEffectors[i], action); } for (size_t j = parentChain.size()-1; j>0; j--) { //action notification about new added effectors can be placed here Action* actionToInsert = parentChain[j-1]; Action* parentAction = parentChain[j]; Action* responsibleChild = j>1 ? parentChain[j-2] : action; actionToInsert->addRequiredEffector(requiredEffectors[i],false,customPriority,responsibleChild); if (effector->insertAction(actionToInsert,parentAction)) { actionToInsert->addAcquiredEffector(requiredEffectors[i]); } } //insert action if (effector->insertAction(action,parent)) { //maybe this is only for debug EffectorIDVector::iterator it = std::find(actualNonAcquiredEffectors.begin(),actualNonAcquiredEffectors.end(), requiredEffectors[i]); GB_ASSERT(it!=actualNonAcquiredEffectors.end(),"Actor::setActionToEffectors: can't set action properly."); actualNonAcquiredEffectors.erase(it); } } GB_ASSERT(actualNonAcquiredEffectors.empty(),"Actor::setActionToEffectors: can't set action properly."); }
void addInfo(Effector* effector,Actions actions) { for(size_t i = 0; i < actions.size(); i++) { _addInfo(effector,actions[i]); } }
bool Actor::checkEffectors(Action* action, Action* parentAction,EffectorIDVector &acquiredEffectors) { acquiredEffectors.clear(); bool principalAcquired = true; const Action::EffectorInfoMap &requiredEffectors = action->getRequiredEffectorInfos(); for (Action::EffectorInfoMap::const_iterator it = requiredEffectors.begin(),end = requiredEffectors.end(); it!=end; it++) { EffectorID effectorID = it->first; Effector* effector = getEffector(effectorID); GB_ASSERT(effector, format("Actor::getEffector: actor doesn't have effector %s", Effector::convertToString(effectorID))); bool principal = it->second.principal; //check if effector will be acquired by action when action is setting to parent bool isAcquired = false; Actions parentChain; Action* responsibleParent = getResponsibleParent(effectorID,parentAction,&parentChain); if (effector->isActive(responsibleParent)) { isAcquired = true; int customActionPriority = action->getEffectorPriority(effectorID); Action* currentAction = parentChain.size()>1 ? parentChain[parentChain.size()-2] : action; Action* settedAction = effector->getActiveChildAction(responsibleParent); //in our case, this can be done simpler, because comparing is based on action's priority //and doesn't depend on action(so action can be used instead of currentAction) if (!settedAction || compareActions(settedAction,currentAction,effectorID, settedAction->getEffectorPriority(effectorID),customActionPriority)) { isAcquired = true; acquiredEffectors.push_back(effectorID); } } if (principal && !isAcquired) { principalAcquired = false; } } return principalAcquired; }
/// Make some consistent parse decision. /// Randomly choose some consistent action, and perform it. /// \param state The state in which the parse decision should be made. /// \todo Allow classifier to confidence-rate actions, and choose highest rated /// action to perform? void Parser::make_consistent_decision(ParseState& state) { assert(!parameter::treebank_has_parse_paths()); Actions actions = state.consistent_actions(); assert(!actions.empty()); if (parameter::parse_left_to_right() || parameter::parse_right_to_left()) { assert(actions.size() == 1); } // Randomly choose some consistent action. Action action = actions.at(ParsePathRandom.get(actions.size())); //Action action = this->best_action(state, actions); Debug::log(5) << "Performing: " << action.to_string() << "\n"; state.perform(action); // FIXME: Don't necessarily use _parse_span_chart. _parse_span_chart.subtract(SpanItem(action), _parse_prc, _parse_rcl, _parse_cbs); }
/// Make some consistent parse decision using the Classifier. /// Choose the highest confidence legal consistent action. /// Only is no legal consistent action exists do /// we choose an illegal (consistent) action. /// \param state The state in which the parse decision should be made. void Parser::make_consistent_decision_with_classifier(ParseState& state) { assert(!parameter::treebank_has_parse_paths()); Actions actions = state.consistent_legal_actions(); Action action; // If some consistent legal action exists, if (!actions.empty()) { action = this->best_action(state, actions).first; Debug::log(5) << "Performing: " << action.to_string() << "\n"; bool debugout = false; double conf = this->confidence(state, action); if (conf <= -5) debugout = true; //if (conf <= -10) debugout = true; if (debugout) Debug::log(3) << "PRE (conf=" << conf << "): " << state.to_string() << "\n"; bool ret = state.perform(action, true); assert(ret); if (debugout) Debug::log(3) << "POST (conf=" << conf << "): " << state.to_string() << "\n"; } else { actions = state.consistent_illegal_actions(); assert(!actions.empty()); if (parameter::parse_left_to_right() || parameter::parse_right_to_left()) { assert(actions.size() == 1); } // Randomly choose some consistent (illegal) action. action = actions.at((unsigned)(drand48() * actions.size())); Debug::log(3) << "Performing illegal action: " << action.to_string() << "\n"; bool ret = state.perform(action); assert(ret); } // FIXME: Don't necessarily use _parse_span_chart. _parse_span_chart.subtract(SpanItem(action), _parse_prc, _parse_rcl, _parse_cbs); }
void Actor::releaseActionEffectors(Action* action,const EffectorIDVector& effectorIDs) { for (size_t i=0;i<effectorIDs.size();i++) { Effector* effector = getEffector(effectorIDs[i]); GB_ASSERT(effector, format("Actor::getEffector: actor doesn't have effector %s", Effector::convertToString(effectorIDs[i]))); Actions children; effector->getDirectChildren(action, children); GB_ASSERT(children.empty(), "Actor::releaseActionEffectors: action isn't allowed to have children on effector at this moment"); Actions becameActive; effector->removeAction(action,becameActive); for(size_t j=0; j<becameActive.size(); j++) { m_activatedEffectors[becameActive[j]].push_back(effectorIDs[i]); } } }
void Actor::print(Effector* effector,Action* action,std::ostringstream& buff,std::string& tabs,bool full) { static const char* spaces = "----"; std::ostringstream actionBuff; if (action!=m_rootAction) { tabs += spaces; buff<<tabs; action->print(actionBuff); std::string actionStr = actionBuff.str(); size_t pos = 0; while ((pos = actionStr.find("\n",pos))!=std::string::npos) { pos += 1; if (pos==actionStr.size()) break; actionStr.insert(pos,tabs); pos += tabs.size(); } buff<<actionStr; } Actions childs; if (full) { effector->getDirectChildren(action,childs); for (size_t i=0; i<childs.size();i++) { print(effector,childs[i],buff,tabs,full); } } else { Action* child = effector->getActiveChildAction(action); if (child) print(effector,child,buff,tabs,full); } if (action!=m_rootAction) tabs.erase(tabs.size()-sizeof(spaces),sizeof(spaces)); }
void Actor::releaseAction(Action* action) { //GB_INFO("ReleaseAction begin: %s (%p)",action->getDescString().c_str(), action); static std::string tabs; //GB_INFO("%sReleaseAction: %s (%p)",tabs.c_str(), action->getDescString().c_str(), action); tabs.append(" "); GB_ASSERT(m_actionsToDelete.find(action) == m_actionsToDelete.end(), "Action has already been deleted. Action logic is corrupted!"); m_actionsToDelete.insert(action); //terminate childs Actions childs; action->getChilds(childs); for (Actions::iterator it=childs.begin(), end=childs.end(); it!=end; it++) { Action* child = *it; child->terminate(Action::CANCELED); } //remove from effectors const EffectorIDVector& effectorIDs = action->getRequiredEffectors(); for (size_t i=0;i<effectorIDs.size();i++) { Effector* effector = getEffector(effectorIDs[i]); GB_ASSERT(effector, format("Actor::getEffector: actor doesn't have effector %s", Effector::convertToString(effectorIDs[i]))); Actions becameActive; effector->removeAction(action,becameActive); for(size_t j=0; j<becameActive.size(); j++) { m_activatedEffectors[becameActive[j]].push_back(effectorIDs[i]); } } tabs.erase(tabs.size()-4,4); //GB_INFO("ReleaseAction end: %s",action->getDescString().c_str()); }
void EditorContext::DoActions(Actions& actions) { for (int i=0; i<actions.size(); ++i) { actions[i](); } actions.clear(); }