size_t DfpnSolver::MID(const DfpnBounds& maxBounds, DfpnHistory& history) { maxBounds.CheckConsistency(); SG_ASSERT(maxBounds.phi > 1); SG_ASSERT(maxBounds.delta > 1); ++m_numMIDcalls; size_t prevWork = 0; SgEmptyBlackWhite colorToMove = GetColorToMove(); DfpnData data; if (TTRead(data)) { prevWork = data.m_work; if (! maxBounds.GreaterThan(data.m_bounds)) // Estimated bounds are larger than we had // anticipated. The calling state must have computed // the max bounds with out of date information, so just // return here without doing anything: the caller will // now update to this new info and carry on. return 0; } else { SgEmptyBlackWhite winner = SG_EMPTY; if (TerminalState(colorToMove, winner)) { ++m_numTerminal; DfpnBounds terminal; if (colorToMove == winner) DfpnBounds::SetToWinning(terminal); else { SG_ASSERT(SgOppBW(colorToMove) == winner); DfpnBounds::SetToLosing(terminal); } TTWrite(DfpnData(terminal, SG_NULLMOVE, 1)); return 1; } } ++m_generateMoves; DfpnChildren children; GenerateChildren(children.Children()); // Not thread safe: perhaps move into while loop below later... std::vector<DfpnData> childrenData(children.Size()); for (size_t i = 0; i < children.Size(); ++i) LookupData(childrenData[i], children, i); // Index used for progressive widening size_t maxChildIndex = ComputeMaxChildIndex(childrenData); SgHashCode currentHash = Hash(); SgMove bestMove = SG_NULLMOVE; DfpnBounds currentBounds; size_t localWork = 1; do { UpdateBounds(currentBounds, childrenData, maxChildIndex); if (! maxBounds.GreaterThan(currentBounds)) break; // Select most proving child std::size_t bestIndex = 999999; DfpnBoundType delta2 = DfpnBounds::INFTY; SelectChild(bestIndex, delta2, childrenData, maxChildIndex); bestMove = children.MoveAt(bestIndex); // Compute maximum bound for child const DfpnBounds childBounds(childrenData[bestIndex].m_bounds); DfpnBounds childMaxBounds; childMaxBounds.phi = maxBounds.delta - (currentBounds.delta - childBounds.phi); childMaxBounds.delta = delta2 == DfpnBounds::INFTY ? maxBounds.phi : std::min(maxBounds.phi, std::max(delta2 + 1, DfpnBoundType(delta2 * (1.0 + m_epsilon)))); SG_ASSERT(childMaxBounds.GreaterThan(childBounds)); if (delta2 != DfpnBounds::INFTY) m_deltaIncrease.Add(float(childMaxBounds.delta-childBounds.delta)); // Recurse on best child PlayMove(bestMove); history.Push(bestMove, currentHash); localWork += MID(childMaxBounds, history); history.Pop(); UndoMove(); // Update bounds for best child LookupData(childrenData[bestIndex], children, bestIndex); // Compute some stats when find winning move if (childrenData[bestIndex].m_bounds.IsLosing()) { m_moveOrderingIndex.Add(float(bestIndex)); m_moveOrderingPercent.Add(float(bestIndex) / (float)childrenData.size()); m_totalWastedWork += prevWork + localWork - childrenData[bestIndex].m_work; } else if (childrenData[bestIndex].m_bounds.IsWinning()) maxChildIndex = ComputeMaxChildIndex(childrenData); } while (! CheckAbort()); // Find the most delaying move for losing states, and the smallest // winning move for winning states. if (currentBounds.IsSolved()) { if (currentBounds.IsLosing()) { std::size_t maxWork = 0; for (std::size_t i = 0; i < children.Size(); ++i) { if (childrenData[i].m_work > maxWork) { maxWork = childrenData[i].m_work; bestMove = children.MoveAt(i); } } } else { std::size_t minWork = DfpnBounds::INFTY; for (std::size_t i = 0; i < children.Size(); ++i) { if (childrenData[i].m_bounds.IsLosing() && childrenData[i].m_work < minWork) { minWork = childrenData[i].m_work; bestMove = children.MoveAt(i); } } } } // Store search results TTWrite(DfpnData(currentBounds, bestMove, localWork + prevWork)); return localWork; }
bool Library::process_phrase(const char *loc_str, read_line &io, bool force, bool json) { if (NULL==loc_str) return true; std::string query; analyze_query(loc_str, query); if (!query.empty()) io.add_to_history(query.c_str()); gsize bytes_read; gsize bytes_written; GError *err=NULL; char *str=NULL; if (!utf8_input) str=g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err); else str=g_strdup(loc_str); if (NULL==str) { fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str); fprintf(stderr, "%s\n", err->message); g_error_free(err); return false; } if (str[0]=='\0') return true; TSearchResultList res_list; switch (analyze_query(str, query)) { case qtFUZZY: LookupWithFuzzy(query, res_list); break; case qtREGEXP: LookupWithRule(query, res_list); break; case qtSIMPLE: SimpleLookup(str, res_list); if (res_list.empty()) LookupWithFuzzy(str, res_list); break; case qtDATA: LookupData(query, res_list); break; default: /*nothing*/; } if (!res_list.empty()) { /* try to be more clever, if there are one or zero results per dictionary show all */ bool show_all_results=true; typedef std::map< string, int, std::less<string> > DictResMap; if (!force) { DictResMap res_per_dict; for(TSearchResultList::iterator ptr=res_list.begin(); ptr!=res_list.end(); ++ptr){ std::pair<DictResMap::iterator, DictResMap::iterator> r = res_per_dict.equal_range(ptr->bookname); DictResMap tmp(r.first, r.second); if (tmp.empty()) //there are no yet such bookname in map res_per_dict.insert(DictResMap::value_type(ptr->bookname, 1)); else { ++((tmp.begin())->second); if (tmp.begin()->second>1) { show_all_results=false; break; } } } }//if (!force) if (!show_all_results && !force) { printf(_("Found %d items, similar to %s.\n"), res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); for (size_t i=0; i<res_list.size(); ++i) { string loc_bookname, loc_def; loc_bookname=utf8_to_locale_ign_err(res_list[i].bookname); loc_def=utf8_to_locale_ign_err(res_list[i].def); printf("%d)%s-->%s\n", i, utf8_output ? res_list[i].bookname.c_str() : loc_bookname.c_str(), utf8_output ? res_list[i].def.c_str() : loc_def.c_str()); } int choise; for (;;) { string str_choise; printf(_("Your choice[-1 to abort]: ")); if(!stdio_getline(stdin, str_choise)){ putchar('\n'); exit(EXIT_SUCCESS); } sscanf(str_choise.c_str(), "%d", &choise); if (choise>=0 && choise<int(res_list.size())) { sdcv_pager pager; print_search_result(pager.get_stream(), res_list[choise]); break; } else if (choise==-1) break; else printf(_("Invalid choise.\nIt must be from 0 to %d or -1.\n"), res_list.size()-1); } } else { sdcv_pager pager(force); if (!json) { fprintf(pager.get_stream(), _("Found %d items, similar to %s.\n"), res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); for (PSearchResult ptr=res_list.begin(); ptr!=res_list.end(); ++ptr) print_search_result(pager.get_stream(), *ptr); } else { char *out; cJSON *root,*fld; root=cJSON_CreateArray(); for (PSearchResult ptr=res_list.begin(); ptr!=res_list.end(); ++ptr) { const TSearchResult & res = *ptr; string loc_bookname, loc_def, loc_exp; if(!utf8_output){ loc_bookname=utf8_to_locale_ign_err(res.bookname); loc_def=utf8_to_locale_ign_err(res.def); loc_exp=utf8_to_locale_ign_err(res.exp); } cJSON_AddItemToArray(root,fld=cJSON_CreateObject()); cJSON_AddStringToObject(fld, "dict", utf8_output ? res.bookname.c_str() : loc_bookname.c_str()); cJSON_AddStringToObject(fld, "word", utf8_output ? res.def.c_str() : loc_def.c_str()); cJSON_AddStringToObject(fld, "definition", utf8_output ? res.exp.c_str() : loc_exp.c_str()); } out=cJSON_Print(root); cJSON_Delete(root); fprintf(pager.get_stream(), "%s", out); free(out); } } } else { string loc_str; if (!utf8_output) loc_str=utf8_to_locale_ign_err(str); printf(_("Nothing similar to %s, sorry :(\n"), utf8_output ? str : loc_str.c_str()); } g_free(str); return true; }