internal SplitNode(SplitNode parent, char pos) { this.splitter = default(T); this.root = parent.root; this.position = parent.position + pos; this.left = null; this.right = null; }
internal SplitNode() { this.splitter = default(T); this.root = this; this.position = ""; this.left = null; this.right = null; }
/// <summary>Process the specified task. /// The game will execute the desired task and all effects coupled either /// directly or indirectly in synchronous manner. /// /// Call <see cref="Controller.Options(bool)"/> on the <see cref="CurrentPlayer"/> /// instance for tasks which are accepted as arguments. /// After this method returns, check <see cref="Controller.Options(bool)"/> /// again until only <see cref="EndTurnTask"/> remains, which will /// start the turn of <see cref="CurrentOpponent"/>. /// </summary> /// <param name="gameTask">The game task to execute.</param> public void Process(PlayerTask gameTask) { // start with no splits ... Splits = new List <Game>(); Log(LogLevel.INFO, BlockType.PLAY, "Game", gameTask.FullPrint()); // clear last power history PowerHistory.Last.Clear(); // make sure that we only use task for this game ... gameTask.Game = this; gameTask.Process(); // add enchantment and buff tag changes if (History) { Enchants.ForEach(p => p.Effects.Keys.ToList().ForEach(t => IdEntityDic.Values.ToList().ForEach(o => PowerHistory.Add(PowerHistoryBuilder.TagChange(o.Id, t, o[t]))))); foreach (var controller in _players) { controller.Hero.Enchants.ForEach(p => p.Effects.Keys.ToList().ForEach(t => PowerHistory.Add(PowerHistoryBuilder.TagChange(Game.CurrentPlayer.Hero.Id, t, Game.CurrentPlayer.Hero[t])))); //CurrentPlayer.Hero.Weapon?.Enchants.ForEach(p => p.IsEnabled()); //CurrentPlayer.Hero.Weapon?.Triggers.ForEach(p => p.IsEnabled()); //CurrentOpponent.Hero.Weapon?.Enchants.ForEach(p => p.IsEnabled()); //CurrentOpponent.Hero.Weapon?.Triggers.ForEach(p => p.IsEnabled()); controller.ControlledZones.Where(z => z != null).ToList().ForEach(z => z.Enchants.ForEach(p => p.Effects.Keys.ToList().ForEach(t => z.GetAll.ForEach(o => PowerHistory.Add(PowerHistoryBuilder.TagChange(o.Id, t, o[t])))))); } Characters.ForEach(c => c.Enchants.ForEach(p => p.Effects.Keys.ToList().ForEach(t => PowerHistory.Add(PowerHistoryBuilder.TagChange(c.Id, t, c[t]))))); } if (Splitting) { var finalSplits = SplitNode.GetSolutions(this, 10, 10000); Dump("Split", $"found {finalSplits.Count} final splits of {finalSplits.Sum(p => p.SameState + 1)}!"); finalSplits.GroupBy(p => p.SameState) .Select(i => new { Word = i.Key, Count = i.Count() }) .ToList().ForEach(p => Dump("Split", $" {p.Count}, with {p.Word} same states")); FinalSplits = finalSplits; } }
internal SplitNode FindCommonAncestorWith(SplitNode other) { return(root.FindNode(this.position, other.position, 0)); }
/// <summary> /// Based on algorithm MinSFA from POPL14. /// </summary> void ComputeSplitHistory() { var fa = autom; if (!fa.isDeterministic) { throw new AutomataException(AutomataExceptionKind.AutomatonIsNondeterministic); } this.initialFinalBlock = new Block(fa.GetFinalStates()); this.initialNonfinalBlock = new Block(fa.GetNonFinalStates()); this.initialFinalNode = new SplitNode(); this.initialNonfinalNode = new SplitNode(); splithistory[initialFinalBlock] = this.initialFinalNode; splithistory[initialNonfinalBlock] = this.initialNonfinalNode; foreach (var q in fa.GetFinalStates()) { Blocks[q] = initialFinalBlock; } foreach (var q in fa.GetNonFinalStates()) { Blocks[q] = initialNonfinalBlock; } var W = new BlockStack(); var W1 = new BlockStack(); if (initialNonfinalBlock.Count < initialFinalBlock.Count) { W1.Push(initialNonfinalBlock); } else { W1.Push(initialFinalBlock); } Func <T, T, T> MkDiff = (x, y) => solver.MkAnd(x, solver.MkNot(y)); //use breath first search wrt new elements while (!W1.IsEmpty) { var tmp = W; W = W1; W1 = tmp; while (!W.IsEmpty) { var B = W.Pop(); var Bcopy = new List <int>(B); //make a copy of B for iterating over its elemenents var Gamma = new Dictionary <int, T>(); //joined conditions leading to B from states leading to B foreach (var q in Bcopy) { foreach (var move in fa.GetMovesTo(q)) //moves leading to q { if (Blocks[move.SourceState].Count > 1) //singleton blocks cannot be further split { if (Gamma.ContainsKey(move.SourceState)) { Gamma[move.SourceState] = solver.MkOr(Gamma[move.SourceState], move.Label); } else { Gamma[move.SourceState] = move.Label; } } } } //if x is not in Gamma.Keys then return False else return Gamma[q] //this way initial (_,B)-splitting is not required Func <int, T> GAMMA = (x) => { T pred; if (Gamma.TryGetValue(x, out pred)) { return(pred); } else { return(solver.False); } }; var relevant2 = new HashSet <Block>(); foreach (var q in Gamma.Keys) { if (Blocks[q].Count > 1) { relevant2.Add(Blocks[q]); //collect the relevant blocks } } var relevantList = new List <Block>(relevant2); //only relevant blocks are potentially split while (relevantList.Count > 0) { var P = relevantList[0]; relevantList.RemoveAt(0); var PE = P.GetEnumerator(); PE.MoveNext(); var P1 = new Block(); bool splitFound = false; //psi may be false here T psi = GAMMA(PE.Current); P1.Add(PE.Current); //note that PE has at least 2 elements #region compute P1 as the new sub-block of P while (PE.MoveNext()) { var q = PE.Current; var phi = GAMMA(q); if (splitFound) { var psi_and_phi = solver.MkAnd(psi, phi); if (solver.IsSatisfiable(psi_and_phi)) { psi = psi_and_phi; P1.Add(q); } } else { var psi_min_phi = MkDiff(psi, phi); if (solver.IsSatisfiable(psi_min_phi)) { psi = psi_min_phi; splitFound = true; } else // [[psi]] is subset of [[phi]] { var phi_min_psi = MkDiff(phi, psi); if (!solver.IsSatisfiable(phi_min_psi)) { // [[phi]] is subset of [[psi]] P1.Add(q); //psi and phi are equivalent } else { //there is some a: q --a--> B and p --a--> compl(B) P1.Clear(); P1.Add(q); psi = phi_min_psi; splitFound = true; } } } } #endregion #region split P //if P1.Count == P.Count then nothing was split if (P1.Count < P.Count) { var node = splithistory[P]; node.Split(psi); //which one is left or right does not matter splithistory[P] = node.left; splithistory[P1] = node.right; foreach (var p in P1) { P.Remove(p); Blocks[p] = P1; } if (W.Contains(P) || W1.Contains(P)) { W1.Push(P1); } else if (P.Count <= P1.Count) { W1.Push(P); } else { W1.Push(P1); } if (P.Count > 1) { relevantList.Add(P); } if (P1.Count > 1) { relevantList.Add(P1); } } #endregion } } } }
internal void Split(T splitter) { this.splitter = splitter; this.left = new SplitNode(this, 'l'); this.right = new SplitNode(this, 'r'); }
public static Graph THINGS() { /* * Sizes * - EC3: 80 * - EC4: 110 * - SNG-3: 70 * - SNG-4: 90 * - SNG-5: 110 * In: * - 0:00:00, EC3(C), EC3(C) * - 0:05:00, SNG-4 * - 0:12:00, EC3, EC4 * - 0:30:00, EC4 * - 1:00:00, SNG-3, SNG-3 * - 1:10:00, SNG-5 * Out: * - 0:20:00, EC3 * - 0:25:00, SNG-4 * - 0:29:00, EC4, EC3 * - 0:45:00, EC3, EC4 * - 1:55:00, SNG-5, SNG-3 * - 2:10:00, SNG-3 * * Cleaning (C): * - EC3: 32 * - EC4: 47 * - SNG-3: 27 * - SNG-4: 35 * - SNG-5: 42 * * Insepction (I): * - EC3: 32 * - EC4: 47 * - SNG-3: 27 * - SNG-4: 35 * - SNG-5: 42 */ var graph = new Graph(); Func <int, int> hours = (int h) => h * 3600; Func <int, int> minutes = (int m) => m * 60; Func <int, int> seconds = (int s) => s; Func <int, int, int> track2secs = (int t, int s) => t * 60 + s * 30; Func <int, int> turnaround2secs = (int c) => c * 30; /* * - 0:00:00, EC3(C), EC3(C) * - 0:05:00, SNG4 * - 0:12:00, EC3, EC4 * - 0:30:00, EC4 * - 1:00:00, SNG3, SNG3 * - 1:10:00, SNG5 */ var ar1 = new ArrivalNode("(1,2)", 0); var ar2 = new ArrivalNode("(3)", minutes(5)); var ar3 = new ArrivalNode("(4, 5)", minutes(12)); var ar4 = new ArrivalNode("(6)", minutes(30)); var ar5 = new ArrivalNode("(7, 8)", hours(1)); var ar6 = new ArrivalNode("(9)", hours(1) + minutes(10)); /* * Out: * - 0:50:00, EC3 * - 0:25:00, SNG-4 * - 0:29:00, EC4, EC3 * - 0:45:00, EC3, EC4 * - 1:55:00, SNG-5, SNG-3 * - 2:10:00, SNG-3 */ var dep1 = new DepartureNode("(1)", minutes(60)); var dep2 = new DepartureNode("(3)", minutes(25)); var dep3 = new DepartureNode("(5,2)", minutes(69)); var dep4 = new DepartureNode("(4, 6)", minutes(45)); var dep5 = new DepartureNode("(9, 7)", hours(1) + minutes(55)); var dep6 = new DepartureNode("(8)", hours(2) + minutes(10)); { Node m12P1 = new MovementNode("(1, 2) to P1", track2secs(2, 1)); Node s12 = new SplitNode("(1, 2) -> (1), (2)", minutes(2) + 30); Node m1p7 = new MovementNode("(1) to P7", track2secs(3, 2)); Node service1p7 = new ServiceNode("(1) insepction", minutes(32)); Node service2p7 = new ServiceNode("(1) insepction", minutes(32)); Node m2p7 = new MovementNode("(2) to P7", track2secs(3, 2)); ar1.AddSuccessor(m12P1); m12P1 += s12; s12 += m1p7; s12 += m2p7; m1p7 += m2p7; m1p7 += service1p7; m2p7 += service2p7; Node m1p4 = new MovementNode("(1) to P4", track2secs(5, 4)); Node m2p4 = new MovementNode("(2) to P4", track2secs(5, 4)); service1p7 += m1p4; service2p7 += m2p4; m1p4.AddSuccessor(dep1); m2p4.AddSuccessor(dep6); } graph.ArrivalNodes.Add(ar1); graph.ArrivalNodes.Add(ar2); graph.ArrivalNodes.Add(ar3); graph.ArrivalNodes.Add(ar4); graph.ArrivalNodes.Add(ar5); graph.ArrivalNodes.Add(ar6); graph.DepartureNodes.Add(dep1); graph.DepartureNodes.Add(dep2); graph.DepartureNodes.Add(dep3); graph.DepartureNodes.Add(dep4); graph.DepartureNodes.Add(dep5); graph.DepartureNodes.Add(dep6); graph.Propagate(); return(graph); }
public static Graph Create() { var graph = new Graph(); Func <int, int> hours = (int h) => h * 3600; Func <int, int> minutes = (int m) => m * 60; Func <int, int> seconds = (int s) => s; Func <int, int, int> track2secs = (int t, int s) => t * 60 + s * 30; Func <int, int> turnaround2secs = (int c) => c * 30; Debug.Assert(track2secs(2, 1) == minutes(2) + seconds(30)); Debug.Assert(turnaround2secs(4) == minutes(2)); var ar1 = new ArrivalNode("(1,2)", 0); var ar2 = new ArrivalNode("(3)", minutes(2) + 30); var arm1 = new MovementNode("(1, 2) to T3", track2secs(2, 1)); var split12 = new SplitNode("(1, 2) to (1), (2)", minutes(2)); var m2 = new MovementNode("(2) to T2", track2secs(2, 1)); var s1 = new ServiceNode("(2) on T2", minutes(34)); var m3 = new MovementNode("(1) to T4", track2secs(2, 1)); var p3a = new ParkingNode("(1) P3"); var p3b = new ParkingNode("(2) P3"); var arm2a = new MovementNode("(3) to T3", track2secs(2, 1)); var arm2b = new TurnAroundNode(turnaround2secs(4)); var arm2c = new MovementNode("(3) to T1", track2secs(2, 1)); var m4 = new MovementNode("(2) to G", track2secs(3, 2)); var m5a = new MovementNode("(1) to T3", track2secs(2, 1)); var m5b = new TurnAroundNode(turnaround2secs(3)); var m5c = new MovementNode("(1) to T2", track2secs(2, 1)); var s2 = new ServiceNode("(1) on T2", minutes(34)); var m6 = new MovementNode("(1) to T1", track2secs(3, 2)); var m7 = new SplitNode("(3) (1) to (3, 1)", minutes(3)); var m8a = new MovementNode("(3, 1) to T4", track2secs(3, 2)); var m8b = new TurnAroundNode(turnaround2secs(7)); var m8c = new MovementNode("(3, 1) to G", track2secs(3, 2)); var dep1 = new DepartureNode("(2)", minutes(90)); var dep2 = new DepartureNode("(3, 1)", hours(2)); ar1.AddSuccessor(arm1); ar2.AddSuccessor(arm2a); split12.AddSuccessor(m2); split12.AddSuccessor(m3); split12.AddSuccessor(p3a); split12.AddSuccessor(p3b); p3a.AddSuccessor(m2); p3b.AddSuccessor(m3); m2.AddSuccessor(s1); m2.AddSuccessor(m3); arm1.AddSuccessor(split12); arm2a.AddSuccessor(arm2b); arm2b.AddSuccessor(arm2c); s1.AddSuccessor(m4); m4.AddSuccessor(dep1); m3.AddSuccessor(m5a); m5a.AddSuccessor(m5b); m5b.AddSuccessor(m5c); m5c.AddSuccessor(s2); s2.AddSuccessor(m6); m6.AddSuccessor(m7); arm2c.AddSuccessor(m7); m7.AddSuccessor(m8a); m8a.AddSuccessor(m8b); m8b.AddSuccessor(m8c); m8c.AddSuccessor(dep2); // Other graph.ArrivalNodes.Add(ar1); graph.ArrivalNodes.Add(ar2); graph.DepartureNodes.Add(dep1); graph.DepartureNodes.Add(dep2); graph.Propagate(); return(graph); }