public RFState(RFState other) { Moves = other.Moves.ToList(); Handover = new Stack(other.Handover); Production = new Stack(other.Production); Buffers = new List <Stack>(); Buffers.AddRange(other.Buffers.Select(buf => new Stack(buf))); }
public RFState Apply(CraneMove move) { var result = new RFState(this); var block = result.RemoveBlock(move.SourceId); result.AddBlock(move.TargetId, block); result.Moves.Add(move); return(result); }
public Tuple <List <CraneMove>, double> GetBestMoves(List <CraneMove> moves, int depth, int handovers, long leftoverDueTime) { if (depth == 0) { return(new Tuple <List <CraneMove>, double>(moves, this.CalculateReward(handovers, leftoverDueTime))); } else { double bestRating = int.MinValue; List <CraneMove> bestMoves = new List <CraneMove>(); System.Diagnostics.Debugger.Launch(); foreach (var move in this.GetAllPossibleMoves()) { if (!moves.Any(m => move.BlockId == m.BlockId && move.SourceId == m.SourceId && move.TargetId == m.TargetId)) { var newState = new RFState(this.Apply(move)); moves.Add(move); Tuple <List <CraneMove>, double> newMoves = null; if (move.TargetId == Handover.Id) { var block = FindBlock(move.BlockId); newMoves = newState.GetBestMoves(moves, depth - 1, handovers + 1, leftoverDueTime + block.Due.MilliSeconds); } else { newMoves = newState.GetBestMoves(moves, depth - 1, handovers, leftoverDueTime); } if (bestMoves == null || bestRating < newMoves.Item2) { bestRating = newMoves.Item2; bestMoves = new List <CraneMove>(newMoves.Item1); if (newMoves.Item2 > 1000) { break; } } moves.Remove(move); } } return(new Tuple <List <CraneMove>, double>(bestMoves, bestRating)); } }
private CraneSchedule PlanMoves(World world, OptimizerType opt) { if (world.Buffers == null || (world.Crane.Schedule.Moves?.Count ?? 0) > 0) { if (world.Buffers == null) { Console.WriteLine($"Cannot calculate, incomplete world."); } else { Console.WriteLine($"Crane already has {world.Crane.Schedule.Moves?.Count} moves"); } return(null); } var schedule = new CraneSchedule() { SequenceNr = seqNr++ }; var initial = new RFState(world); var solution = initial.GetBestMovesBeam(new List <CraneMove>(), 6, 5); var list = solution.Item1.ConsolidateMoves(); if (solution != null) { schedule.Moves.AddRange(list.Take(3) .TakeWhile(move => world.Handover.Ready || move.TargetId != world.Handover.Id)); } if (schedule.Moves.Count > 0) { Console.WriteLine($"Delivering answer for Worldtime {world.Now}"); return(schedule); } else { Console.WriteLine($"No answer for Worldtime {world.Now}"); return(null); } }
public Tuple <List <CraneMove>, double> GetBestMovesBeam(List <CraneMove> x, int depth, int width) { var bestMoves = new Stack <Tuple <CraneMove, double, int> >(ExpandMoveState(0)); // reduce depth because this is the first move depth--; var states = new RFState[width]; for (int i = 0; i < width; i++) { states[i] = new RFState(this); } while (depth > 0) { if (bestMoves.Count <= states.Length) { for (int i = 0; bestMoves.Count > 0; i++) { states[i] = states[i].Apply(bestMoves.Pop().Item1); } } var moves = new List <Tuple <CraneMove, double, int> >(); for (int i = 0; i < states.Length; i++) { moves.AddRange(states[i].ExpandMoveState(i)); } moves = moves.OrderByDescending(item => item.Item2).Take(width).ToList(); var newStates = new RFState[width]; for (int i = 0; i < moves.Count(); i++) { var move = moves.ElementAt(i); newStates[i] = states[move.Item3].Apply(move.Item1); } for (int i = 0; i < states.Length; i++) { if (newStates[i] != null) { states[i] = new RFState(newStates[i]); } } depth--; } double bestReward = 0; RFState bestState = null; for (int i = 0; i < states.Length; i++) { var reward = states[i].ExpandMoveState(1, 1).Count() > 0 ? states[i].ExpandMoveState(1, 1).First().Item2 : 0; if (reward > bestReward) { bestReward = reward; bestState = states[i]; } } if (bestState == null) { return(new Tuple <List <CraneMove>, double>(new List <CraneMove>(), 0)); } else { return(new Tuple <List <CraneMove>, double>(bestState.Moves, bestState.CalculateReward(0, 0))); } }
public double CalculateMoveReward(CraneMove move) { double reward = 0; var oldState = new RFState(this); var newState = oldState.Apply(move); if (move.TargetId == Handover.Id) { reward += 500; } else { if (move.SourceId == Production.Id) { reward += 15; var productionFill = oldState.Production.Count / (double)oldState.Production.MaxHeight; if (productionFill >= 1) { reward += 600; } else if (productionFill >= 0.75) { reward += 150; } else if (productionFill > 0.25) { reward += 25; } if (oldState.Buffers.First(stack => stack.Id == move.TargetId).ContainsReady) { if (oldState.Buffers.First(stack => stack.Id == move.TargetId).Top().Ready) { reward -= 100; } else { reward -= 25; } } } else { var oldSourceBuffer = oldState.Buffers.First(stack => stack.Id == move.SourceId); var oldTargetBuffer = oldState.Buffers.First(stack => stack.Id == move.TargetId); var newSourceBuffer = newState.Buffers.First(stack => stack.Id == move.SourceId); var newTargetBuffer = newState.Buffers.First(stack => stack.Id == move.TargetId); if (!oldTargetBuffer.ContainsReady || oldTargetBuffer.IsEmpty) { reward += 20; } else if (oldTargetBuffer.ContainsReady) { if (oldTargetBuffer.Top().Ready) { reward -= 100; } else { reward -= 30; } } if (oldTargetBuffer.ContainsDueBelow(new TimeStamp() { MilliSeconds = 5 * 60000 })) { reward -= 10; } if (oldTargetBuffer.BlocksAboveReady() < newTargetBuffer.BlocksAboveReady()) { reward -= 20; } if (oldSourceBuffer.BlocksAboveReady() > newSourceBuffer.BlocksAboveReady()) { reward += 40; } if (oldSourceBuffer.ContainsReady) { reward += (oldSourceBuffer.MaxHeight - oldSourceBuffer.BlocksAboveReady()) * 10; } if (newSourceBuffer.Top() != null && newSourceBuffer.Top().Ready) { reward += 100; } } } return(reward); }