// Phase 2: EXPANSION kết hợp dữ liệu BTMM trained public static Node ExpandChildBTMM(this Node node) { // Tính & Lưu lại child Strength, để ko cần tính lại khi expand // Cộng child strength để tính allChildStrength luôn if (node.ChildStrengths == null) { node.ChildStrengths = new Dictionary <ulong, double>(node.UntriedMoves.Count); double allChildStrength = 0; foreach (var bitMove in node.UntriedMoves) { double strength = BTMMAlgorithm.StrongOfAction(node.State, bitMove); node.ChildStrengths.Add(bitMove, strength); allChildStrength += strength; } node.AllChildStrength = allChildStrength; } // Expand random child var i = Constant.Random.Next(node.UntriedMoves.Count); var move = node.UntriedMoves[i]; node.UntriedMoves.RemoveAt(i); // Untried -> Try var newState = node.State.Clone().NextState(move); var child = new Node(newState, node, move); child.Strength = node.ChildStrengths[move]; // dùng lại child strength đã được tính trước đó node.ChildNodes.Add(child); return(child); }
// Distribute probability based on Roulette wheel method private static ulong RouletteWheelSelection(this State state) { // Nếu chỉ có 1 legal move => trả về legal move đó luôn if (state.BitLegalMoves.PopCount() == 1) { return(state.BitLegalMoves); } // Có từ 2 legal moves trở lên mới cần tính roulette wheel var listLegalMoves = state.GetArrayLegalMoves(); var moveCount = listLegalMoves.Length; var wheel = new int[moveCount]; var maxWheel = 0; for (var i = 0; i < moveCount; i++) { // StrongOfAction trả về giá trị nằm trong khoảng [0.01, 100], nên nhân 1000 để cast int chính xác hơn // Câu trên SAI: Gamma nằm mới nằm trong khoảng [0.01, 100], còn strong thì được nhân bởi 1 hoặc nhiều gamma var temp = (int)(1000 * BTMMAlgorithm.StrongOfAction(state, listLegalMoves[i])); maxWheel += temp; wheel[i] = maxWheel; } var selectPos = Constant.Random.Next(0, maxWheel); for (var i = 0; i < moveCount; i++) { if (selectPos <= wheel[i]) { return(listLegalMoves[i]); } } return(0UL); }