void BuildTable::CalcBuildTable (int cur, int endbuild, int depth, ResInfo res) { const UnitDef* d = deflist [cur].def; res.buildtime += d->buildTime; res.energy += d->energyCost; res.metal += d->metalCost; float score = CalcScore(depth,res); std::vector<int> &bb=buildby[cur]; for (std::vector<int>::iterator a = bb.begin(); a!=bb.end(); ++a) // for every unit that can build cur { BuildTable::Table::ent& ent = table.get (*a, endbuild); float entscore = CalcScore (ent.depth, ent.res); if (ent.id < 0 || entscore > score) { ent.id = cur; ent.depth = depth; ent.res = res; CalcBuildTable(*a, endbuild, depth+1, res); } } }
/*>void DisplayScores(FILE *fp, char **SeqTable, int nseq, int seqlen, int MaxInMatrix, int Method, BOOL Extended) ------------------------------------------------------------------- Display the variability scores for each position in the alignment 11.09.96 Original By: ACRM 17.09.96 Added MaxInMatrix and prints amino acid list 15.07.08 Added Extended parameter and printing */ void DisplayScores(FILE *fp, char **SeqTable, int nseq, int seqlen, int MaxInMatrix, int Method, BOOL Extended) { int i, j; for(i=0; i<seqlen; i++) { if(Extended) { fprintf(fp,"%4d %9.6f ", i+1, CalcScore(SeqTable, nseq, seqlen, i, MaxInMatrix, Method)); } else { fprintf(fp,"%4d %6.3f ", i+1, CalcScore(SeqTable, nseq, seqlen, i, MaxInMatrix, Method)); } for(j=0; j<nseq; j++) { fprintf(fp,"%c",SeqTable[j][i]); } fprintf(fp,"\n"); } }
/******************************************************** *! @brief 関数 - @param[out] - @param[in] - @par - @return - @note *********************************************************/ PRIVATE EVALUATE_TREE_T* CreateEvaluateTree( PLAYER_T CurrentPlayer ) { EVALUATE_TREE_T *pEvaluateTreeTop; EVALUATE_TABLE_T *pReversiTableTop; SIZE_T AllocateAreaSize; unsigned int Depth; /* Create Evaluate Table of Top Node */ pReversiTableTop = (EVALUATE_TABLE_T*)malloc( sizeof(EVALUATE_TABLE_T) ); AllocateAreaSize = sizeof( pReversiTableTop->aEvaluatReversiTable ); CopyCurrentReversiTable( pReversiTableTop->aEvaluatReversiTable, AllocateAreaSize ); /* Create Evaluate Tree Top Node */ pEvaluateTreeTop = (EVALUATE_TREE_T*)malloc( sizeof(EVALUATE_TREE_T) ); pEvaluateTreeTop->Depth = 0; pEvaluateTreeTop->NodeID = 0; pEvaluateTreeTop->DiscInfo.h = 0; pEvaluateTreeTop->DiscInfo.v = 0; pEvaluateTreeTop->DiscInfo.CurrentPlayer= TOGGLE_PLAYER( CurrentPlayer ); /* Currentは1手前の相手ターンの盤面 */ pEvaluateTreeTop->NumNextIndex = 0; pEvaluateTreeTop->pEvaluatReversiTable = pReversiTableTop; pEvaluateTreeTop->Score = CalcScore( pEvaluateTreeTop->DiscInfo.CurrentPlayer, pEvaluateTreeTop->pEvaluatReversiTable->aEvaluatReversiTable ); pEvaluateTreeTop->pNextNode = NULL; pEvaluateTreeTop->pNextDepthNode = NULL; /* Create Tree */ MakeTree( pEvaluateTreeTop ); return pEvaluateTreeTop; }
void KENLM<Model>::EvaluateInIsolation(MemPool &pool, const System &system, const Phrase<Moses2::Word> &source, const TargetPhraseImpl &targetPhrase, Scores &scores, SCORE &estimatedScore) const { // contains factors used by this LM float fullScore, nGramScore; size_t oovCount; CalcScore(targetPhrase, fullScore, nGramScore, oovCount); float estimateScore = fullScore - nGramScore; bool GetLMEnableOOVFeature = false; if (GetLMEnableOOVFeature) { float scoresVec[2], estimateScoresVec[2]; scoresVec[0] = nGramScore; scoresVec[1] = oovCount; scores.PlusEquals(system, *this, scoresVec); estimateScoresVec[0] = estimateScore; estimateScoresVec[1] = 0; SCORE weightedScore = Scores::CalcWeightedScore(system, *this, estimateScoresVec); estimatedScore += weightedScore; } else { scores.PlusEquals(system, *this, nGramScore); SCORE weightedScore = Scores::CalcWeightedScore(system, *this, estimateScore); estimatedScore += weightedScore; } }
void LanguageModel::EvaluateInIsolation(const Phrase &source , const TargetPhrase &targetPhrase , ScoreComponentCollection &scoreBreakdown , ScoreComponentCollection &estimatedFutureScore) const { // contains factors used by this LM float fullScore, nGramScore; size_t oovCount; CalcScore(targetPhrase, fullScore, nGramScore, oovCount); float estimateScore = fullScore - nGramScore; if (StaticData::Instance().GetLMEnableOOVFeature()) { vector<float> scores(2), estimateScores(2); scores[0] = nGramScore; scores[1] = oovCount; scoreBreakdown.Assign(this, scores); estimateScores[0] = estimateScore; estimateScores[1] = 0; estimatedFutureScore.Assign(this, estimateScores); } else { scoreBreakdown.Assign(this, nGramScore); estimatedFutureScore.Assign(this, estimateScore); } }
FFState* LexicalReordering::Evaluate( const Hypothesis& hypo, const FFState* prev_state, ScoreComponentCollection* out) const { out->PlusEquals(this, CalcScore(const_cast<Hypothesis*>(&hypo))); //TODO need to return proper state, calc score should not use previous //hypothesis, it should use the state. return NULL; }
int Umeyama(const gsl_matrix * const A, const gsl_matrix * const B, gsl_matrix * const Assignment, float *score) { int res = 0; gsl_matrix_complex *AE = NULL, *BE = NULL; gsl_matrix *P = NULL, *AS = NULL, *BS = NULL, *AN = NULL, *BN = NULL, *AssignmentT = NULL; #ifdef USE_ASP long *col_mate; long *row_mate; cost **pTempCost; int i, j; #endif struct timeval start, end; long mtime, seconds, useconds; #ifdef VERBOSE PrintGSLMatrix(A, "Umeyama A"); PrintGSLMatrix(B, "Umeyama B"); #endif AE = gsl_matrix_complex_alloc(A->size1, A->size2); if(AE == NULL) goto _exit; AS = gsl_matrix_alloc(A->size1, A->size2); if(AS == NULL) goto _exit; AN = gsl_matrix_alloc(A->size1, A->size2); if(AN == NULL) goto _exit; ComputeHermitianMatrix(A, AE, AS, AN); #ifdef VERBOSE PrintGSLMatrix(AS, "AS"); PrintGSLMatrix(AN, "AN"); #endif if( IsHermitian(AE) == false ) { fprintf(stderr, "FATAL: AE is not Hermitian!\n"); exit(0); } #ifdef VERBOSE fprintf(stderr, "Verified AE is Hermitian.\n"); #endif BE = gsl_matrix_complex_alloc(B->size1, B->size2); if(BE == NULL) goto _exit; BS = gsl_matrix_alloc(B->size1, B->size2); if(BS == NULL) goto _exit; BN = gsl_matrix_alloc(B->size1, B->size2); if(BN == NULL) goto _exit; ComputeHermitianMatrix(B, BE, BS, BN); #ifdef VERBOSE PrintGSLMatrix(BS, "BS"); PrintGSLMatrix(BN, "BN"); #endif if( IsHermitian(BE) == false ) { fprintf(stderr, "FATAL: BE is not Hermitian!\n"); exit(0); } #ifdef VERBOSE fprintf(stderr, "Verified BE is Hermitian.\n"); WriteComplexMatrixToFile(BE); PrintGSLMatrixComplex(AE, "AE"); PrintGSLMatrixComplex(BE, "BE"); #endif P = gsl_matrix_alloc(A->size1, A->size2); if(P == NULL) goto _exit; res = EigenDecomp(AE, BE, P); if( res == -1 ) goto _exit; #ifdef VERBOSE PrintGSLMatrix(P, "P"); PrintGSLMatrix(P, "Computing Hungarian"); #endif // Begin timing Hungarian gettimeofday(&start, NULL); #ifdef USE_ASP col_mate = new long[P->size1]; row_mate = new long[P->size1]; pTempCost = new cost*[P->size1]; for(i = 0; i < P->size1; ++i) pTempCost[i] = new cost[P->size2]; for(i = 0; i < P->size1; ++i) for(j = 0; j < P->size2; ++j) pTempCost[i][j] = gsl_matrix_get(P, i, j); asp(P->size1, pTempCost, col_mate, row_mate); for(i = 0; i < P->size1; ++i) delete[] pTempCost[i]; delete[] pTempCost; // Update assignment matrix for(i = 0; i < P->size1; ++i) gsl_matrix_set(Assignment, i, col_mate[i], 1); delete[] col_mate; delete[] row_mate; #else Hungarian(P, true, Assignment); #endif // End timing Hungarian gettimeofday(&end, NULL); seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; fprintf(stderr, "%ld ms\t", mtime); // PrintGSLMatrixUint(Assignment, "Assignment"); // Allocate and initialize AssgtT AssignmentT = gsl_matrix_alloc(Assignment->size1, Assignment->size2); if(AssignmentT == NULL) goto _exit; gsl_matrix_memcpy(AssignmentT, Assignment); gsl_matrix_transpose(AssignmentT); /* PrintGSLMatrix(AS, "AS"); PrintGSLMatrix(AN, "AN"); PrintGSLMatrix(BS, "BS"); PrintGSLMatrix(BN, "BN"); */ *score = CalcScore(AS, AN, BS, BN, Assignment, AssignmentT); _exit: if(P != NULL) gsl_matrix_free(P); if(AS != NULL) gsl_matrix_free(AS); if(AN != NULL) gsl_matrix_free(AN); if(BS != NULL) gsl_matrix_free(BS); if(BN != NULL) gsl_matrix_free(BN); if(AE != NULL) gsl_matrix_complex_free(AE); if(BE != NULL) gsl_matrix_complex_free(BE); if(AssignmentT != NULL) gsl_matrix_free(AssignmentT); return res; }
/******************************************************** *! @brief 関数 - @param[out] - @param[in] - @par - @return - @note *********************************************************/ PRIVATE void MakeTree( EVALUATE_TREE_T *pCurrentNode ) { int h, v; DISC_INFO_T DiscInfo; ERROR_CHECK Result; EVALUATE_TREE_T *pNextDepthNode; EVALUATE_TREE_T *pNextNode; if ( pCurrentNode->Depth <= DEPTH_MAX ) { #ifdef DEBUG_MAKE_NODE printf("\nDepth = %d, NodeID = %d, CurrentPlayer = %d, Pos = [%d, %d], Score = %d" ,pCurrentNode->Depth ,pCurrentNode->NodeID ,pCurrentNode->DiscInfo.CurrentPlayer ,pCurrentNode->DiscInfo.h ,pCurrentNode->DiscInfo.v/COEF_LINE ,pCurrentNode->Score ); PrintReversiTable( pCurrentNode->pEvaluatReversiTable->aEvaluatReversiTable ); #endif /* 有効な位置を探す */ for ( v=REALV(1); v < VERTICAL_NUM; v=v+REALV(1) ) { for ( h=REALH(1); h < HORIZON_NUM; h=h+REALH(1) ) { DiscInfo.h = h; DiscInfo.v = v; DiscInfo.CurrentPlayer = TOGGLE_PLAYER( pCurrentNode->DiscInfo.CurrentPlayer ); Result = CheckInputPos( &DiscInfo, pCurrentNode->pEvaluatReversiTable->aEvaluatReversiTable, FALSE ); /* 有効な位置を見つけたら新しいノードを生成する */ if ( Result == SUCCESS ) { if ( pCurrentNode->NumNextIndex == 0 ) { /* 1つでも有効な位置が見つかったら次の深さのノードを生成する */ /* Tableへのポインタは生成し終わったら消滅して欲しいのでスコープは必要最低限に限定する */ EVALUATE_TABLE_T *pNextDepthTable; /* Create Evaluate Table of Next Depth Node */ pNextDepthTable = (EVALUATE_TABLE_T*)malloc( sizeof(EVALUATE_TABLE_T) ); memcpy( pNextDepthTable, pCurrentNode->pEvaluatReversiTable, sizeof(EVALUATE_TABLE_T) ); /* CurrentノードのTableをコピーする */ ReversingDisc( DiscInfo, pNextDepthTable->aEvaluatReversiTable ); /* コピーしたTableで石をひっくり返す */ /* Create Evaluate Tree Next Depth Node */ pCurrentNode->pNextDepthNode = (EVALUATE_TREE_T*)malloc( sizeof(EVALUATE_TREE_T) ); pNextDepthNode = pCurrentNode->pNextDepthNode; /* 確保した領域にポインタを繋ぐ */ pNextDepthNode->Depth = pCurrentNode->Depth + 1; pNextDepthNode->NodeID = pCurrentNode->NumNextIndex; pNextDepthNode->DiscInfo.h = DiscInfo.h; pNextDepthNode->DiscInfo.v = DiscInfo.v; pNextDepthNode->DiscInfo.CurrentPlayer = DiscInfo.CurrentPlayer; pNextDepthNode->pEvaluatReversiTable = pNextDepthTable; pNextDepthNode->Score = CalcScore( pNextDepthNode->DiscInfo.CurrentPlayer, pNextDepthNode->pEvaluatReversiTable->aEvaluatReversiTable ); pNextDepthNode->pNextNode = NULL; pNextDepthNode->pNextDepthNode = NULL; /* Create Evaluate Tree Next Next Depth Node */ MakeTree( pNextDepthNode ); /* 探索深度限界判定 */ if ( pNextDepthNode != NULL ) { /* NextDepthがまだ探索深度限界に達していない */ pNextNode = pNextDepthNode->pNextNode; /* 以後、新しい選択肢が見つかったらNextNodeに新規Nodeを追加していく */ } else { /* NextDepthが探索深度限界に達していた */ return; /* 深度限界なので他の選択肢を探る必要なし */ } } else { /* 次の選択肢が見つかったらノードを生成する */ /* Tableへのポインタは生成し終わったら消滅して欲しいのでスコープは必要最低限に限定する */ EVALUATE_TABLE_T *pNextTable; /* Create Evaluate Table of Next Node */ pNextTable = (EVALUATE_TABLE_T*)malloc( sizeof(EVALUATE_TABLE_T) ); memcpy( pNextTable, pCurrentNode->pEvaluatReversiTable, sizeof(EVALUATE_TABLE_T) ); /* CurrentノードのTableをコピーする */ ReversingDisc( DiscInfo, pNextTable->aEvaluatReversiTable ); /* コピーしたTableで石をひっくり返す */ /* Create Evaluate Tree Next Node */ pNextNode = (EVALUATE_TREE_T*)malloc( sizeof(EVALUATE_TREE_T) ); pNextNode->Depth = pCurrentNode->pNextDepthNode->Depth; pNextNode->NodeID = pCurrentNode->NumNextIndex; pNextNode->DiscInfo.h = DiscInfo.h; pNextNode->DiscInfo.v = DiscInfo.v; pNextNode->DiscInfo.CurrentPlayer = DiscInfo.CurrentPlayer; pNextNode->pEvaluatReversiTable = pNextTable; pNextNode->Score = CalcScore( pNextNode->DiscInfo.CurrentPlayer, pNextNode->pEvaluatReversiTable->aEvaluatReversiTable ); pNextNode->pNextNode = NULL; pNextNode->pNextDepthNode = NULL; /* Create Evaluate Tree Next Depth Next Node */ MakeTree( pNextNode ); /* pNextNodeに今回生成したNodeのNextNodeアドレスを入れておく * 新しい選択肢が見つかったらpNextNodeに追加していく */ pNextNode = pNextNode->pNextNode; } pCurrentNode->NumNextIndex++; /* 有効な選択肢が見つかったら次の深さのノード数をインクリメントする */ } } } } else { /* 評価木の深度が限界に達したので、確保した領域を解放してTree生成終了 */ FREE( pCurrentNode->pEvaluatReversiTable ); FREE( pCurrentNode ); return; } #ifdef DEBUG_MAKE_NODE printf("\n [Depth = %d] NumNextIndex = %d" ,pCurrentNode->Depth ,pCurrentNode->NumNextIndex ); #endif return; }
void GreedyTensorSearch(const TTrainData& data, const TVector<int>& splitCounts, double modelLength, TProfileInfo& profile, TFold* fold, TLearnContext* ctx, TSplitTree* resSplitTree) { TSplitTree currentSplitTree; TrimOnlineCTRcache({fold}); TVector<TIndexType> indices(data.LearnSampleCount); MATRIXNET_INFO_LOG << "\n"; const bool useStatsFromPrevTree = AreStatsFromPrevTreeUsed(ctx->Params.ObliviousTreeOptions.Get()); if (useStatsFromPrevTree) { AssignRandomWeights(data.LearnSampleCount, ctx, fold); ctx->StatsFromPrevTree.GarbageCollect(); } for (ui32 curDepth = 0; curDepth < ctx->Params.ObliviousTreeOptions->MaxDepth; ++curDepth) { TCandidateList candList; AddFloatFeatures(data, ctx, &ctx->StatsFromPrevTree, &candList); AddOneHotFeatures(data, ctx, &ctx->StatsFromPrevTree, &candList); AddSimpleCtrs(data, fold, ctx, &ctx->StatsFromPrevTree, &candList); AddTreeCtrs(data, currentSplitTree, fold, ctx, &ctx->StatsFromPrevTree, &candList); auto IsInCache = [&fold](const TProjection& proj) -> bool {return fold->GetCtrRef(proj).Feature.empty();}; SelectCtrsToDropAfterCalc(ctx->Params.SystemOptions->CpuUsedRamLimit, data.GetSampleCount(), ctx->Params.SystemOptions->NumThreads, IsInCache, &candList); CheckInterrupted(); // check after long-lasting operation if (!useStatsFromPrevTree) { AssignRandomWeights(data.LearnSampleCount, ctx, fold); } profile.AddOperation(TStringBuilder() << "AssignRandomWeights, depth " << curDepth); double scoreStDev = ctx->Params.ObliviousTreeOptions->RandomStrength * CalcScoreStDev(*fold) * CalcScoreStDevMult(data.LearnSampleCount, modelLength); TVector<size_t> candLeafCount(candList.ysize(), 1); const ui64 randSeed = ctx->Rand.GenRand(); ctx->LocalExecutor.ExecRange([&](int id) { auto& candidate = candList[id]; if (candidate.Candidates[0].SplitCandidate.Type == ESplitType::OnlineCtr) { const auto& proj = candidate.Candidates[0].SplitCandidate.Ctr.Projection; if (fold->GetCtrRef(proj).Feature.empty()) { ComputeOnlineCTRs(data, *fold, proj, ctx, &fold->GetCtrRef(proj), &candidate.ResultingCtrTableSize); candLeafCount[id] = candidate.ResultingCtrTableSize; } } TVector<TVector<double>> allScores(candidate.Candidates.size()); ctx->LocalExecutor.ExecRange([&](int oneCandidate) { if (candidate.Candidates[oneCandidate].SplitCandidate.Type == ESplitType::OnlineCtr) { const auto& proj = candidate.Candidates[oneCandidate].SplitCandidate.Ctr.Projection; Y_ASSERT(!fold->GetCtrRef(proj).Feature.empty()); } allScores[oneCandidate] = CalcScore(data.AllFeatures, splitCounts, *fold, indices, ctx->ParamsUsedWithStatsFromPrevTree, ctx->Params, candidate.Candidates[oneCandidate].SplitCandidate, currentSplitTree.GetDepth(), &ctx->StatsFromPrevTree); }, NPar::TLocalExecutor::TExecRangeParams(0, candidate.Candidates.ysize()) , NPar::TLocalExecutor::WAIT_COMPLETE); if (candidate.Candidates[0].SplitCandidate.Type == ESplitType::OnlineCtr && candidate.ShouldDropCtrAfterCalc) { fold->GetCtrRef(candidate.Candidates[0].SplitCandidate.Ctr.Projection).Feature.clear(); } TFastRng64 rand(randSeed + id); rand.Advance(10); // reduce correlation between RNGs in different threads for (size_t i = 0; i < allScores.size(); ++i) { double bestScoreInstance = MINIMAL_SCORE; auto& splitInfo = candidate.Candidates[i]; const auto& scores = allScores[i]; for (int binFeatureIdx = 0; binFeatureIdx < scores.ysize(); ++binFeatureIdx) { const double score = scores[binFeatureIdx]; const double scoreInstance = TRandomScore(score, scoreStDev).GetInstance(rand); if (scoreInstance > bestScoreInstance) { bestScoreInstance = scoreInstance; splitInfo.BestScore = TRandomScore(score, scoreStDev); splitInfo.BestBinBorderId = binFeatureIdx; } } } }, 0, candList.ysize(), NPar::TLocalExecutor::WAIT_COMPLETE); size_t maxLeafCount = 1; for (size_t leafCount : candLeafCount) { maxLeafCount = Max(maxLeafCount, leafCount); } fold->DropEmptyCTRs(); CheckInterrupted(); // check after long-lasting operation profile.AddOperation(TStringBuilder() << "Calc scores " << curDepth); const TCandidateInfo* bestSplitCandidate = nullptr; double bestScore = MINIMAL_SCORE; for (const auto& subList : candList) { for (const auto& candidate : subList.Candidates) { double score = candidate.BestScore.GetInstance(ctx->Rand); TProjection projection = candidate.SplitCandidate.Ctr.Projection; ECtrType ctrType = ctx->CtrsHelper.GetCtrInfo(projection)[candidate.SplitCandidate.Ctr.CtrIdx].Type; if (!ctx->LearnProgress.UsedCtrSplits.has(std::make_pair(ctrType, projection)) && score != MINIMAL_SCORE) { score *= pow(1 / (1 + subList.ResultingCtrTableSize / static_cast<double>(maxLeafCount)), ctx->Params.ObliviousTreeOptions->ModelSizeReg.Get()); } if (score > bestScore) { bestScore = score; bestSplitCandidate = &candidate; } } } if (bestScore == MINIMAL_SCORE) { break; } if (bestSplitCandidate->SplitCandidate.Type == ESplitType::OnlineCtr) { TProjection projection = bestSplitCandidate->SplitCandidate.Ctr.Projection; ECtrType ctrType = ctx->CtrsHelper.GetCtrInfo(projection)[bestSplitCandidate->SplitCandidate.Ctr.CtrIdx].Type; ctx->LearnProgress.UsedCtrSplits.insert(std::make_pair(ctrType, projection)); } auto bestSplit = TSplit(bestSplitCandidate->SplitCandidate, bestSplitCandidate->BestBinBorderId); if (bestSplit.Type == ESplitType::OnlineCtr) { const auto& proj = bestSplit.Ctr.Projection; if (fold->GetCtrRef(proj).Feature.empty()) { size_t totalLeafCount; ComputeOnlineCTRs(data, *fold, proj, ctx, &fold->GetCtrRef(proj), &totalLeafCount); DropStatsForProjection(*fold, *ctx, proj, &ctx->StatsFromPrevTree); } } else if (bestSplit.Type == ESplitType::OneHotFeature) { bestSplit.BinBorder = data.AllFeatures.OneHotValues[bestSplit.FeatureIdx][bestSplit.BinBorder]; } SetPermutedIndices(bestSplit, data.AllFeatures, curDepth + 1, *fold, &indices, ctx); if (useStatsFromPrevTree) { ctx->ParamsUsedWithStatsFromPrevTree.SelectParametersForSmallestSplitSide(curDepth + 1, *fold, indices, &ctx->LocalExecutor); } currentSplitTree.AddSplit(bestSplit); MATRIXNET_INFO_LOG << BuildDescription(ctx->Layout, bestSplit); MATRIXNET_INFO_LOG << " score " << bestScore << "\n"; profile.AddOperation(TStringBuilder() << "Select best split " << curDepth); int redundantIdx = GetRedundantSplitIdx(curDepth + 1, indices); if (redundantIdx != -1) { DeleteSplit(curDepth + 1, redundantIdx, ¤tSplitTree, &indices); MATRIXNET_INFO_LOG << " tensor " << redundantIdx << " is redundant, remove it and stop\n"; break; } } *resSplitTree = std::move(currentSplitTree); }
void Search(std::vector<int> startNeighbor, int*** srcShitAry, int** srcShitDataAry, int* srcShitSizeAry, const int width, const int height, const int stonesNum, const int* srcMap, const int maxFreeSize){ RESTART : aStack.clear(); int freeSize = maxFreeSize; int* map = new int[(width+1) * height]; //対象領域だけを考慮したマップ for(int i = 0; i < (width+1)*height; i++) map[i] = srcMap[i]; int*** shitAry = srcShitAry; //起点配列表現をした糞(ズク)の配列 int** shitDataAry = srcShitDataAry; int* shitSizeAry = srcShitSizeAry; /* int*** shitAry = new int**[stonesNum]; //起点配列表現をした糞(ズク)の配列 int** shitDataAry = new int*[stonesNum]; int* shitSizeAry = new int[stonesNum]; for(int s = 0; s < stonesNum; s++){ //糞(ズク)配列のコピー shitAry[s] = new int*[8]; for(int i = 0; i < 8; i++){ if(srcShitAry[s][i] == 0) { shitAry[s][i] = 0; continue; } shitAry[s][i] = new int[17]; for(int j = 0; j < 17; j++){ shitAry[s][i][j] = srcShitAry[s][i][j]; } } //糞(ズク)データ配列のコピー shitDataAry[s] = new int[8]; for(int i = 0; i < 8; i++){ shitDataAry[s] = srcShitDataAry[s]; } //サイズ配列のコピー shitSizeAry[s] = srcShitSizeAry[s]; }*/ int areaAry[1025]; //下の方でつかいまわしている int subAreaMap[2048]; int putPoints[17]; int putAryLength; int putShitNum = 0; int startKn = 0; std::stack<WideData*> bdStack; int DEBUG_COUNT = 0; int kn = 0; int tmlCount = 0; while(1){ //幅優先探索用のコード bool startFlag = false; if(bdStack.size() == 0){ kn = startKn; startFlag = true; startKn++; if(startKn == stonesNum){ break; } } else { PUT_PROCESS: kn = bdStack.top()->GetShitNumber(); int remove = RemoveShit(map, kn, shitSizeAry[kn], width, height); freeSize += remove; if(remove != 0) { putShitNum--; aStack.pop_back(); } if(!bdStack.top()->Exist()) { delete bdStack.top(); bdStack.pop(); continue; } //実配置処理 wdElement* data = bdStack.top()->GetNext(); while(data->deadArea > minScore || (data->deadArea == minScore && data->needShitNum+putShitNum >= minScore_minShitNum)){ if(!bdStack.top()->Exist()){ delete bdStack.top(); bdStack.pop(); goto PUT_PROCESS; } data = bdStack.top()->GetNext(); } int st = data->st; int placePoint = data->basePoint; int DUMMY; PutShit(map, kn, shitAry[kn][st], placePoint, width+1, height, &DUMMY); putShitNum++; freeSize -= shitSizeAry[kn]; Answer_t ans; ans.basePoint=placePoint; ans.state=st; ans.shitNumber=kn; aStack.push_back(ans); if(kn == stonesNum-1){ goto TERMINAL; } #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("\tshit : %d(%c)\n", kn, kn+49); DEBUG_printMap(map, width+1, height); printf("free : %d\n", freeSize); printf("dead : %d\n", data->deadArea); DEBUG_waitKey(); #endif #endif kn++; while(kn < stonesNum && shitSizeAry[kn] > data->maxAreaSize){ //サイズ的に置けない糞(ズク)をスキップ kn++; #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("%d skipped\n\n", kn); #endif #endif } if(kn == stonesNum) { goto TERMINAL; } //int deadArea = CalcDeadArea(map, width+1, height, freeSize, &(shitSizeAry[kn]), stonesNum-kn, areaAry, &needShitNum); /* if(minScore < data->deadArea || (minScore == data->deadArea && minScore_minShitNum <= data->needShitNum+putShitNum)){ continue; }*/ } //配置処理ここまで BREADTH_MAKE: std::vector<wdElement*>* breadthData = new std::vector<wdElement*>(); for(int st = 0; st < 8; st++){ const int* shit = shitAry[kn][st]; if(shitAry[kn][st] == 0) continue; //ベースポイント配列作成 std::vector<int> baseAry; if(startFlag){ baseAry = startNeighbor; } else { std::vector<int>* neighbor = CalcNeighborPoint(map, width+1, height); //ココ for(int s = 0; shit[s] != -1; s++){ for(int n = 0; n < neighbor->size(); n++){ int value = (*neighbor)[n] - shit[s]; for(int i = 0; i < baseAry.size(); i++){ if(value == baseAry[i]){ goto NEXT; } } baseAry.push_back(value); NEXT:; } } delete neighbor; } //全てのベースポイントを探索 for(int i = 0; i < baseAry.size(); i++){ int basePoint = baseAry[i]; /* printf("%d\n", basePoint); bool a = DEBUG_JudgePutable(map, shit, basePoint, width, height, putPoints, &putAryLength); DEBUG_printPutShitOnMap(map, putPoints, putAryLength, width, height); DEBUG_waitKey(); */ if(JudgePutable(map, shit, basePoint, width, height)){ int neighborNum; PutShit(map, kn, shitAry[kn][st], basePoint, width+1, height, &neighborNum); freeSize -= shitSizeAry[kn]; int needShitNum = 0; int fit; int checkArea = CheckSubArea(map, width+1, height, freeSize, areaAry, subAreaMap, &fit); int deadArea = CalcDeadArea(map, width+1, height, freeSize, &(shitSizeAry[kn]), stonesNum-kn, areaAry, &needShitNum); //doko RemoveShit(map, kn, shitSizeAry[kn], width, height); freeSize += shitSizeAry[kn]; //ここでやれるだろ if(minScore < deadArea || (minScore == deadArea && minScore_minShitNum <= needShitNum+putShitNum)){ continue; } wdElement* temp = new wdElement(); temp->st = st; temp->basePoint = basePoint; temp->fit = fit; temp->fit2 = neighborNum; temp->deadArea = deadArea; temp->maxAreaSize = checkArea; temp->needShitNum = needShitNum; breadthData->push_back(temp); } } } if(breadthData->size() == 0){ //置けないなら #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("%d cannot place\n\n", kn); #endif #endif delete breadthData; kn++; if(kn == stonesNum) goto TERMINAL; goto BREADTH_MAKE; } else { InsertSort(breadthData, breadthData->size()); // for(int i = 0; i < breadthData->size(); i++){ #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("shit %d(%c) place pattern\n", kn, kn+49); #endif #endif for(int i = 0; i < breadthData->size() && (breadthData->data())[i]->rank == 0; i++){ wdElement* elm = breadthData->data()[i]; #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("\t%d | %d-(%d, %d) : %d [%d %d]", elm->rank, elm->st, elm->basePoint%(width+1), elm->basePoint/(width+1), elm->deadArea, elm->fit, elm->fit2); DEBUG_waitKey(); #endif #endif } bdStack.push(new WideData(kn, breadthData, startFlag)); } continue; TERMINAL: #ifdef DEBUG_CODE #ifdef CHECK_CODE printf("\t<<<terminal>>>\n\n"); #endif #endif int score = CalcScore(map, width, height); bool update = false; if(minScore > score){ update = true; } else if(minScore == score){ if(minScore_minShitNum > putShitNum){ update = true; } } if(update){ minScore = score; minScore_minShitNum = putShitNum; #ifdef DEBUG_CODE //DEBUG_printMap(map, width+1, height); LARGE_INTEGER end; QueryPerformanceCounter( &end ); printf("score(%d,%d)\n", minScore, minScore_minShitNum); printf("time : %d\n", (end.QuadPart - start.QuadPart)/liFreq.QuadPart); #endif bestAnsStack = aStack; MAX_TERMINAL_COUNT = HIGH_COUNT; SendSolution(&bestAnsStack, stonesNum, shitDataAry, width+1); tmlCount = 0; } else { tmlCount++; #ifdef CHECK_CODE if(tmlCount%100 == 0){ printf("%d : %d\n", tmlCount/100, kn); } #endif int maxCount = MAX_TERMINAL_COUNT; if(tmlCount == maxCount){ //十万回終端を探索しても解が改善されないなら //koko while(bdStack.size() > 1){ delete bdStack.top(); bdStack.pop(); } while(aStack.size() > 1){ aStack.pop_back(); } freeSize += RemoveShitNums(map, startKn, width, height); //状態をクリア /* RemoveAllShit(map, width, height); freeSize = 0; */ putShitNum = 1; tmlCount = 0; // #ifdef DEBUG_CODE if(MAX_TERMINAL_COUNT == HIGH_COUNT){ printf("focus end : %d\n", MAX_TERMINAL_COUNT); } else { printf("replace : %d\n", MAX_TERMINAL_COUNT); } #ifdef CHECK_CODE DEBUG_printMap(map, width+1, height); printf("free : %d\n", freeSize); DEBUG_waitKey(); #endif #endif MAX_TERMINAL_COUNT = LOW_COUNT; continue; } } if(bdStack.size() == 0) break; if(bdStack.top()->GetShitNumber() == stonesNum-1){ //置いた糞(ズク)が最後なら delete bdStack.top(); bdStack.pop(); int remove = RemoveShit(map, kn, shitSizeAry[kn], width, height); freeSize += remove; if(remove != 0) putShitNum--; aStack.pop_back(); } } delete map; goto RESTART; }
bool eChatPrefixSpamTester::Check( tString & out, nTimeRolling & timeOut, eChatPrefixSpamType & typeOut ) { if ( !ShouldCheckMessage( say_ ) ) return false; RemoveTimedOutPrefixes(); // check from known prefixes if ( HasKnownPrefix( out, timeOut ) ) { typeOut = eChatPrefixSpamType_Known; return true; } eChatLastSaid::SaidList & lastSaid = player_->GetLastSaid().lastSaid_; // Map of Prefix => Data std::map< tString, PrefixEntry > foundPrefixes; for ( eChatLastSaid::SaidList::iterator it = lastSaid.begin(); it != lastSaid.end(); ++it ) { eChatSaidEntry & said = *it; if ( !ShouldCheckMessage( said ) || say_.Said() == said.Said() ) continue; int common = CommonPrefix( say_.Said(), said.Said() ); if ( common > 0 ) { const tString prefix = say_.Said().SubStr(0, common); // User is talking to a player. Not prefix spam, but we still check the // message text excluding the player name. // Example: Player 1: grind center. [etc...] int nameLen; if ( ChatDirectedTowardsPlayer( prefix, nameLen ) ) { said.SetType( eChatMessageType_Public_Direct ); said.said_ = said.said_.SubStr( nameLen + 1 ); return false; } if ( foundPrefixes.find(prefix) == foundPrefixes.end() ) foundPrefixes[prefix] = PrefixEntry(); PrefixEntry & data = foundPrefixes[prefix]; data.occurrences += 1; CalcScore( data, common, prefix ); if ( data.score >= se_prefixSpamRequiredScore ) { #ifdef DEBUG con << "Spam prefix found: \"" << se_EscapeColors( prefix ) << "\" with score " << data.score << '\n'; #endif nTimeRolling t = player_->GetLastSaid().AddPrefix( prefix, data.score, say_.Time() ); timeOut = RemainingTime( t ); // We caught the prefix. Don't catch words that start with the prefix. RemovePrefixEntries( prefix, said ); out = se_EscapeColors( prefix ); typeOut = eChatPrefixSpamType_New; return true; } } } return false; }