public AGI_CalcFields(AGI_CalcFields agic, COMMON_MAP map) { setConstData(map); fields = new int[F_MAX_X * F_MAX_Y]; agic.fields.CopyTo(fields, 0); closed = agic.closed; }
public StoreData(bool idExists, AGI_CalcFields ag, COMMON_MAP map) { if (idExists == true) { ID = idCounter; StoreData.idCounter++; } else { ID = 0; } stoneIdList = new List<int>(); stonePlaceList = new List<int>(); stoneKindsList = new List<int>(); evalueList = new List<float>(); evalue = -1; score = -1; closed = false; agicF = new AGI_CalcFields(ag, map); lastAttackStone = 0; }
public StoreData(StoreData st, COMMON_MAP map) { this.ID = st.ID; stoneIdList = new List<int>(); stonePlaceList = new List<int>(); stoneKindsList = new List<int>(); evalueList = new List<float>(); for(int i=0; i < st.stoneKindsList.Count; i++) { stoneIdList.Add(st.stoneIdList[i]); stonePlaceList.Add(st.stonePlaceList[i]); stoneKindsList.Add(st.stoneKindsList[i]); } for(int i=0; i < evalueList.Count; i++) { evalueList.Add(st.evalueList[i]); } evalue = st.evalue; score = st.score; closed = st.closed; agicF = new AGI_CalcFields(st.agicF, map); lastAttackStone = st.lastAttackStone; }
private string exchangeFieldsToString(AGI_CalcFields agicF) { string strRet = ""; for (int i = 0; i < agicF.GetAgiCalcFieldsSize(); i++) { strRet += agicF.GetAgiCalcFieldNum(i).ToString(); } return strRet; }
/* スコアの計算 */ private int calcScore(AGI_CalcFields agicF) { int score = 0; score = agicF.GetAgiCalcScore(); return score; }
/* サイズを含めた評価関数評価関数(EVAL_C) */ private float calcEvalSizeKai(AGI_CalcFields agicF, AGI_CalcFields beforeAgicF, int score, int passSize, int closedDepthSize) { float eval = 0; eval = agicF.GetAgiCalcEvalSizeKai(beforeAgicF, score, passSize, closedDepthSize); return eval; }
/* サイズを含めた評価関数(EVAL_A) */ private float calcEvalInitial(AGI_CalcFields agicF, AGI_CalcFields beforeAgicF, int closedDepthSize) { float eval = 0; eval = agicF.GetAgiCalcEvalInitial(beforeAgicF, closedDepthSize); return eval; }
/* 問題文をディクショナリに格納 */ private bool storeRootFields(AGI_CalcFields agicF) { bool result = true; /* 各種登録 */ /* ID取得 */ StoreData regist = new StoreData(false, agicF, commonMap); regist.ID = 0; /* ROOTのID */ /* store登録 */ regist.evalue = 0.0F; regist.score = calcScore(agicF); storeDataDic.Add(regist.ID, regist); return result; }
/* StoreDataへ格納(並列) */ private int storeFieldsForParallel(AGI_CalcFields agicF, int parentId, int stoneId, int kinds, int placeIdx, AGI_CalcFields beforeAgiF, int evalKind) { int retId = -1; /* 各種登録 */ /* ID取得 */ StoreData regist = new StoreData(true, agicF, commonMap); /* store登録 */ /* stoneの登録(親のstoneを受け継ぐ) */ if (storeDataDic.ContainsKey(parentId) == true) { for (int i = 0; i < storeDataDic[parentId].GetStoneInfoSize(); i++) { regist.SetStoneInfo(storeDataDic[parentId].GetStoneInfoId(i), storeDataDic[parentId].GetStoneInfoPlace(i), storeDataDic[parentId].GetStoneInfoKind(i)); } int passStoneSize = stoneId - regist.GetFinallyStoneId(); regist.SetStoneInfo(stoneId, placeIdx, kinds); regist.score = calcScore(agicF); switch (evalKind) { case EVAL_A: /* サイズが大きいほど有利 */ regist.evalue = calcEvalInitial(agicF, beforeAgiF, smallOrderList[stoneId]); break; case EVAL_B: regist.evalue = calcEvalDepth(agicF, beforeAgiF, smallOrderList[stoneId]); break; case EVAL_C: regist.evalue = calcEvalSizeKai(agicF, beforeAgiF, regist.score, passStoneSize, smallOrderList[stoneId]); break; default: regist.evalue = calcEvalSizeKai(agicF, beforeAgiF, regist.score, passStoneSize, smallOrderList[stoneId]); break; } for (int i = 0; i < storeDataDic[parentId].GetEvalueListSize(); i++) { regist.SetEvalueList(storeDataDic[parentId].GetEvalueInfo(i)); } regist.SetEvalueList(regist.evalue); regist.lastAttackStone = stoneId; Object thisLock = new Object(); lock (thisLock) { if (saveStoreDataDic.ContainsKey(regist.ID) != true) { try { saveStoreDataDic.Add(regist.ID, regist); } catch (System.ArgumentException) { saveStoreDataDic[regist.ID] = regist; } } else { saveStoreDataDic[regist.ID] = regist; } } retId = regist.ID; } return retId; }
private void step3() { /* 2手以降処理 */ /* 当てはめ先は自陣の近似1 or 近似2セル */ for (;;) { if (searchQueId.Count == 0) { break; } int maxEvaId = 0; int maxEval = 0; searchQueId.TryPeek(out maxEvaId); if (storeDataDic.ContainsKey(maxEvaId) == true) { maxEval = storeDataDic[maxEvaId].score; } depthSize = calcDepthSize(maxEval); for (int i = 0; i < depthSize; i++) { queueSearchDepthForParallel(); } searchTimes++; queueSearchForParallel(); selectionQueue(); if (searchQueId.Count != 0) { int priId = -1; float priEval; int priScore; searchQueId.TryPeek(out priId); if (priId != -1) { priEval = storeDataDic[priId].evalue; priScore = storeDataDic[priId].score; Console.WriteLine("id={0},eval={1}, score={2}", priId, priEval, priScore); } #if false if (searchQueId.TryPeek(out id) == true) { var key = dic.FirstOrDefault(x => x.Value.Equals(id)).Key; /* dicのValue(ID)よりFields(Key)を取得 */ if (key != null) { AGI_CalcFields debug = new AGI_CalcFields(key); //debug.PrintAgiCalcFields(); } } #endif } } }
private void step1() { /* 初手処理 */ /* 石1~石(INIT_SEARCH_IDX)まで全探索 */ AGI_CalcFields calcF = new AGI_CalcFields(agi.GetAgiFields(), commonMap); storeRootFields(calcF); /* 親の登録 */ for (int id = 0; id < INIT_SEARCH_IDX; id++) { if(id > agi.GetAgiStoneList().GetListSize()) /* 石全体の数よりオーバーした場合 */ { break; } for (int idx = 0; idx < calcF.GetAgiCalcFieldsSize(); idx++) /* すべてのセルで確認 */ { for (int kind = 0; kind < (int)Kinds.REV_R270; kind++) /* すべての回転・反転で確認 */ { if (agi.GetAgiStoneList().GetAgiStoneKindsList(id).GetAGIStones(kind) == null) /* 重複により削除された石 */ { continue; } AGI_CalcFields resultF = placement(calcF, id, kind, idx, false); /* 配置確認 */ if (resultF == null) /* 配置失敗 */ { continue; } else { /* ROOT_ID = 0 */ if (storeFields(resultF, 0, id, kind, idx, calcF, EVAL_A) == -1) /* 書き込み失敗 */ { continue; } } } } } }
public void SetAgiCalcCopyFromA(AGI_CalcFields A) { for (int i = 0; i < fields.Length; i++) { this.fields[i] = A.fields[i]; } }
/* 評価値に石のサイズが影響する評価関数 Normal*/ public float GetAgiCalcEvalSizeKai(AGI_CalcFields beforeAgiF, int score, int passSize, int depthSize) { float retEval = 0.0F; int stoneCnt = 0; int depth = DEPTH_MAX; int[] closed = new int[4] { 0, 0, 0, 0 }; int closedFieldsSize = 0; int falesFieldsSize = 0; for (int i = 0; i < fields.Length; i++) { int cntmyFieldEdge = 0; /* スコア対象の辺の数をカウント */ int cntwallEdge = 0; int cntObjectEdge = 0; if (beforeAgiF.GetAgiCalcFieldNum(i) != MY_FIELD && fields[i] == MY_FIELD) /* 前回から今回で自陣に変化した場合 */ { stoneCnt++; /* 上 */ if (i - F_MAX_X >= 0) { /* エッジ接続チェック */ switch (fields[i - F_MAX_X]) { case MY_FIELD: if (beforeAgiF.GetAgiCalcFieldNum(i - F_MAX_X) == MY_FIELD && fields[i - F_MAX_X] == MY_FIELD) { cntmyFieldEdge++; } break; case WALL: cntwallEdge++; break; case OBJECT: cntObjectEdge++; break; default: break; } /* 閉路チェック */ closed[0] = checkClosedCell2(i - F_MAX_X, depth); } /* 下 */ if (i + F_MAX_X < fields.Length) { switch (fields[i + F_MAX_X]) { case MY_FIELD: if (beforeAgiF.GetAgiCalcFieldNum(i + F_MAX_X) == MY_FIELD && fields[i + F_MAX_X] == MY_FIELD) { cntmyFieldEdge++; } break; case WALL: cntwallEdge++; break; case OBJECT: cntObjectEdge++; break; default: break; } closed[1] = checkClosedCell2(i + F_MAX_X, depth); } /* 左 */ if (i - 1 >= 0) { switch (fields[i - 1]) { case MY_FIELD: if (beforeAgiF.GetAgiCalcFieldNum(i - 1) == MY_FIELD && fields[i - 1] == MY_FIELD) { cntmyFieldEdge++; } break; case WALL: cntwallEdge++; break; case OBJECT: cntObjectEdge++; break; default: break; } closed[2] = checkClosedCell2(i - 1, depth); } /* 右 */ if (i + 1 < fields.Length) { switch (fields[i + 1]) { case MY_FIELD: if (beforeAgiF.GetAgiCalcFieldNum(i + 1) == MY_FIELD && fields[i + 1] == MY_FIELD) { cntmyFieldEdge++; } break; case WALL: cntwallEdge++; break; case OBJECT: cntObjectEdge++; break; default: break; } closed[3] = checkClosedCell2(i + 1, depth); } /* 閉路のマス数以下の石がすでにない場合 */ for (int k = 0; k < closed.Length; k++) { if ((closed[k] != 0) && (closed[k] < depthSize)) { falesFieldsSize++; } } /* 規定以下の閉路数 */ for (int k = 0; k < closed.Length; k++) { if ((closed[k] != 0) && (closed[k] < DEPTH_MAX)) { closedFieldsSize++; } if ((closed[k] != 0) && (closed[k] < (DEPTH_MAX/2))) { closedFieldsSize++; } } } retEval += (cntObjectEdge * CONNECT_OBJECT) + (cntwallEdge * CONNECT_WALL) + (cntmyFieldEdge * CONNECT_MY_FIELD); } retEval = (retEval/ (float)stoneCnt) * RATE_CONNECT + (float)score * RATE_SCORE; /* プラス要素 */ retEval = retEval - (PASS_STONE_RATE * passSize) - (FAILES_FIELD_RATE * falesFieldsSize) - (CLOSED_FIELD_RATE * closedFieldsSize); return (retEval); }
/* 評価値に石のサイズが影響しない評価関数 Initial */ public float GetAgiCalcEvalInitial(AGI_CalcFields beforeAgiF, int depthSize) { float retEval = 0; int stoneCnt = 0; int depth = DEPTH_MAX; int[] closed = new int[4] { 0, 0, 0, 0 }; int closedFieldsSize = 0; int falesFieldsSize = 0; for (int i = 0; i < fields.Length; i++) { int cntEdge = 0; /* スコア対象の辺の数をカウント */ if (beforeAgiF.GetAgiCalcFieldNum(i) != MY_FIELD && fields[i] == MY_FIELD) /* 前回から今回で自陣に変化した場合 */ { stoneCnt++; /* 上 */ if (i - F_MAX_X >= 0) { /* エッジ接続チェック */ if (fields[i - F_MAX_X] == MY_FIELD || fields[i - F_MAX_X] == OBJECT || fields[i - F_MAX_X] == WALL) { cntEdge++; } /* 閉路チェック */ closed[0] = checkClosedCell2(i - F_MAX_X, depth); } /* 下 */ if (i + F_MAX_X < fields.Length) { if (fields[i + F_MAX_X] == MY_FIELD || fields[i + F_MAX_X] == OBJECT || fields[i + F_MAX_X] == WALL) { cntEdge++; } closed[1] = checkClosedCell2(i + F_MAX_X, depth); } /* 左 */ if (i - 1 >= 0) { if (fields[i - 1] == MY_FIELD || fields[i - 1] == OBJECT || fields[i - 1] == WALL) { cntEdge++; } closed[2] = checkClosedCell2(i - 1, depth); } /* 右 */ if (i + 1 < fields.Length) { if (fields[i + 1] == MY_FIELD || fields[i + 1] == OBJECT || fields[i + 1] == WALL) { cntEdge++; } closed[3] = checkClosedCell2(i + 1, depth); } /* 閉路のマス数以下の石がすでにない場合 */ for (int k = 0; k < closed.Length; k++) { if ((closed[k] != 0) && (closed[k] < depthSize)) { falesFieldsSize++; } } /* 規定以下の閉路数 */ for (int k = 0; k < closed.Length; k++) { if ((closed[k] != 0) && (closed[k] < DEPTH_MAX)) { closedFieldsSize++; } if ((closed[k] != 0) && (closed[k] < (DEPTH_MAX / 2))) { closedFieldsSize++; } } } if (cntEdge >= 3) { retEval += SCORE_MAX; } else if (cntEdge == 2) { retEval += SCORE_MID; } else if (cntEdge == 1) { retEval += SCORE_MIN; } else { retEval += NON_SCORE; } } retEval = retEval / (float)stoneCnt; retEval = retEval - (FAILES_FIELD_RATE * falesFieldsSize) - (CLOSED_FIELD_RATE * closedFieldsSize); return (retEval); }
StoreData() { ID = idCounter; StoreData.idCounter++; lastAttackStone = 0; stoneIdList = new List<int>(); stonePlaceList = new List<int>(); stoneKindsList = new List<int>(); evalueList = new List<float>(); closed = false; agicF = null; lastAttackStone = 0; evalue = -1; score = -1; }
/* 石の配置 NG:null */ private AGI_CalcFields placement(AGI_CalcFields agicOrgF, int stoneId, int kinds, int placeIdx, bool connectCheck) { AGI_CalcFields retAgicF = new AGI_CalcFields(agicOrgF, commonMap); AGI_Stones setStone = new AGI_Stones(agi.GetAgiStoneList().GetAgiStoneKindsList(stoneId).GetAGIStones(kinds)); /* 石の加算処理 */ for (int i = 0; i < setStone.GetSize(); i++) { int idx = agiST2agiF(retAgicF.GetMaxX(), retAgicF.GetMaxY(), setStone.GetXSize(), setStone.GetYSize(), placeIdx, i); retAgicF.SetAgiCalcNum (idx, retAgicF.GetAgiCalcFieldNum(idx) + setStone.GetNum(i)); } /* 判定 */ bool connectFlg = false; /* 自陣と接続するか判定 */ for (int i = 0; i < retAgicF.GetAgiCalcFieldsSize(); i++) { int tmp = retAgicF.GetAgiCalcFieldNum(i); if ((tmp > 0) && ((tmp % 2) == 0)) { /* 正の偶数値があった場合、自・壁・障のいずれかと重なる */ return null; } if ((connectFlg == false) && (tmp == -6)) /* 近傍(-7) + 自陣(1) */ { connectFlg = true; } } if ((connectCheck == true) && (connectFlg != true)) { return null; } /* 加算前(石設置済み)に戻す */ retAgicF.GetReturnCalcFld(); return retAgicF; }
/* 探索(並列) */ private void queueSearchForParallel() { int searchSize = searchQueId.Count; int[] queIdArray = searchQueId.ToArray(); int[] searchField = new int[9] { MY_FIELD, NEIGHT1, NEIGHT2, NEIGHT3, NEIGHT4, NEIGHT5, NEIGHT6, NEIGHT7, NEIGHT8 }; int answerSize = 9999999; Object thisLock = new Object(); Parallel.For(0, searchSize, i => { /// Console.WriteLine(searchQueId.Count); int targetId = queIdArray[i]; /* キューからID取得 */ // string key; // key = dic.FirstOrDefault(x => x.Value.Equals(targetId)).Key; /* dicのValue(ID)よりFields(Key)を取得 */ // if (key != null) //{ // string strFields = key.ToString(); /* キーをStirngへ変換 */ if (storeDataDic.ContainsKey(targetId) == true) { StoreData tgtSD = storeDataDic[targetId]; AGI_CalcFields tgtAgiCF = new AGI_CalcFields(tgtSD.GetAgiCalcFields(), commonMap); /* stringからAGI_CalcFieldsを復元 */ for (int idKind = tgtSD.lastAttackStone + 1; idKind <= tgtSD.lastAttackStone + SEARCH_KIND_MAX; idKind++) /* SEARCH_KIND_MAX先分走査 */ { /* 石の決定 */ if (idKind < agi.GetAgiStoneList().GetListSize()) /* 石最大オーバー */ { bool setFlg = false; for (int kind = 0; kind < (int)Kinds.REV_R270; kind++) { if (agi.GetAgiStoneList().GetAgiStoneKindsList(idKind).GetAGIStones(kind) == null) /* 重複により削除された石 */ { continue; } int maxX = agi.GetAgiStoneList().GetAgiStoneKindsList(idKind).GetAGIStones(kind).GetXSize() - 2; int maxY = agi.GetAgiStoneList().GetAgiStoneKindsList(idKind).GetAGIStones(kind).GetYSize() - 2; int targetSize = Math.Max(maxX, maxY); if (targetSize >= 8) { targetSize = 8; } else if (targetSize <= 0) { targetSize = 0; } for (int idx = 0; idx < tgtAgiCF.GetAgiCalcFieldsSize(); idx++) /* 接地セル走査 */ { if ((tgtAgiCF.GetAgiCalcFieldNum(idx) == MY_FIELD) || /* 自フィールドまたは */ ((tgtAgiCF.GetAgiCalcFieldNum(idx) < 0) && (tgtAgiCF.GetAgiCalcFieldNum(idx) >= searchField[targetSize])) || /* 近傍以内または */ (((tgtAgiCF.GetAgiCalcFieldNum(idx) == WALL) || (tgtAgiCF.GetAgiCalcFieldNum(idx) == OBJECT)) && /* 壁または障害物であり、かつ */ ( ((tgtAgiCF.GetAgiCalcFieldNum(idx + 1) >= searchField[targetSize]) && (tgtAgiCF.GetAgiCalcFieldNum(idx + 1) < 0)) || /* 右隣りが近傍値 */ ((tgtAgiCF.GetAgiCalcFieldNum(idx + F_MAX_X) >= searchField[targetSize]) && (tgtAgiCF.GetAgiCalcFieldNum(idx + F_MAX_X) < 0)) ||/* 下隣が近傍値 */ ((tgtAgiCF.GetAgiCalcFieldNum(idx + (F_MAX_X + 1)) >= searchField[targetSize]) && (tgtAgiCF.GetAgiCalcFieldNum(idx + (F_MAX_X + 1)) < 0)) /* 右下が近傍値 */ ) ) ) { AGI_CalcFields resultF = placement(tgtAgiCF, idKind, kind, idx, true); /* 配置確認 */ if (resultF == null) /* 配置失敗 */ { continue; } else { int retId = storeFieldsForParallel(resultF, tgtSD.ID, idKind, kind, idx, tgtAgiCF, EVAL_C); if (retId == -1) /* 書き込み失敗 */ { continue; } else { setFlg = true; if (resultF.GetAgiCalcEmptySize() != 0) { nextQueId.Enqueue(retId); } else { lock (thisLock) { StoreData tmp; if (saveStoreDataDic.ContainsKey(retId) == true) { tmp = new StoreData(saveStoreDataDic[retId], commonMap); if (answerId.ContainsKey(retId) == true) { answerId[retId] = tmp; } else { answerId.Add(retId, tmp); } } else { nextQueId.Enqueue(retId); } } } } } } } } if (setFlg == false) { int retId = storeFieldsForParallelLast(tgtSD, idKind); nextQueId.Enqueue(retId); } } else { lock (thisLock) { if (answerSize < tgtSD.score) { if (answerId.ContainsKey(targetId) == false) { answerId.Add(targetId, tgtSD); } answerSize = tgtSD.score; } } } } } else { ; } }); foreach (var key in saveStoreDataDic.Keys) { if (storeDataDic.ContainsKey(key) == true) { if (saveStoreDataDic.ContainsKey(key) == true) { storeDataDic[key] = saveStoreDataDic[key]; } } else { if (saveStoreDataDic.ContainsKey(key) == true) { storeDataDic.Add(key, saveStoreDataDic[key]); } } } saveStoreDataDic.Clear(); searchQueId = new ConcurrentQueue<int>(); }
/* StoreDataへ格納 */ private int storeFields(AGI_CalcFields agicF, int parentId, int stoneId, int kinds, int placeIdx, AGI_CalcFields beforeAgiF, int evalKind) { int retId = -1; /* 各種登録 */ /* ID取得 */ StoreData regist = new StoreData(true, agicF, commonMap); /* stoneの登録(親のstoneを受け継ぐ) */ for (int i = 0; i < storeDataDic[parentId].GetStoneInfoSize(); i++) { regist.SetStoneInfo(storeDataDic[parentId].GetStoneInfoId(i), storeDataDic[parentId].GetStoneInfoPlace(i), storeDataDic[parentId].GetStoneInfoKind(i)); } int passSize = regist.GetFinallyStoneId() - stoneId; regist.SetStoneInfo(stoneId, placeIdx, kinds); regist.score = calcScore(agicF); if (evalKind == EVAL_A) { /* サイズが大きいほど有利 */ regist.evalue = calcEvalInitial(agicF, beforeAgiF, smallOrderList[stoneId]); } else if (evalKind == EVAL_B) { regist.evalue = calcEvalDepth(agicF, beforeAgiF, smallOrderList[stoneId]); } else { regist.evalue = calcEvalSizeKai(agicF, beforeAgiF, regist.score, passSize, smallOrderList[stoneId]); } regist.closed = agicF.closed; storeDataDic.Add(regist.ID, regist); regist.lastAttackStone = stoneId; retId = regist.ID; return retId; }