private MoveCondition CheckMoveCondition(CraneMove move) { if (move.EmptyMove) { return(MoveCondition.Valid); // just a crane relocation } if (move.SourceId == 0) // Production -> X { var block = World.Production.BottomToTop.LastOrDefault(); if (block == null || block.Id != move.BlockId) { return(MoveCondition.BlockNotFound); } } else if (move.SourceId <= World.Buffers.Count) // Buffer -> X { var block = World.Buffers[move.SourceId - 1].BottomToTop.LastOrDefault(); if (block == null || block.Id != move.BlockId) { return(MoveCondition.BlockNotFound); } } else { return(MoveCondition.InvalidSource); // Handover -> X } if (move.TargetId == 0) { return(MoveCondition.InvalidTarget); // X -> Production } else if (move.TargetId <= World.Buffers.Count) // X -> Buffer { if (World.Buffers[move.TargetId - 1].BottomToTop.Count >= World.Buffers[move.TargetId - 1].MaxHeight) { return(MoveCondition.HeightLimitViolated); } } else // X -> Handover { if (!World.Handover.Ready || World.Handover.Block != null) { return(MoveCondition.HandoverNotReady); } Block block; if (move.SourceId == World.Production.Id) { block = World.Production.BottomToTop.LastOrDefault(); } else { block = World.Buffers[move.SourceId - 1].BottomToTop.LastOrDefault(); } if (!block.Ready) { return(MoveCondition.BlockNotReady); } } return(MoveCondition.Valid); }
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 BrpState Apply(CraneMove move) { var result = new BrpState(this); var block = result.Stacks[move.SourceId].Blocks.Pop(); if (move.TargetId != HandoverId) { result.Stacks[move.TargetId].Blocks.Push(block); } result.Moves.Add(move); return(result); }
/// If the top block of the production stack can be put on a buffer schedule this move. private static void ClearProductionStack(World world, CraneSchedule schedule) { var blocks = world.Production.BottomToTop.Count; if (blocks > 0) { var top = world.Production.BottomToTop[blocks - 1]; foreach (var stack in world.Buffers) { if (stack.MaxHeight > stack.BottomToTop.Count) { var move = new CraneMove(); move.BlockId = top.Id; move.SourceId = world.Production.Id; move.TargetId = stack.Id; schedule.Moves.Add(move); return; } } } }
void PlanShuffleCrane() { var dontUse = new List <int>(); foreach (var mov in plan.Moves) { dontUse.Add(mov.PickupLocationId); dontUse.Add(mov.DropoffLocationId); } var move_id = plan.Moves.Count; var src = ArrivalStacks().OrderBy(loc => loc.Stack.BottomToTop.Any() ? loc.Stack.BottomToTop.Min(block => block.Sequence) : int.MaxValue).First(); var amount = Math.Min(SizeOf(src), world.ShuffleCrane.CraneCapacity); if (amount == 0) { return; } var tgt = BufferStacks().FirstOrDefault(tgt => RemainingCapacity(tgt) >= amount && !dontUse.Contains(tgt.Id)); if (tgt != null) { var mov = new CraneMove(); move_id += 1; mov.Id = move_id; mov.Type = MoveType.PickupAndDropoff; mov.ReleaseTime = new TimeStamp() { MilliSeconds = world.Now.MilliSeconds }; mov.PickupLocationId = src.Id; mov.DropoffLocationId = tgt.Id; mov.RequiredCraneId = world.ShuffleCrane.Id; mov.Amount = amount; plan.Moves.Add(mov); return; } }
/// If any block on top of a stack can be moved to the handover schedule this move. private static void AnyHandoverMove(World world, CraneSchedule schedule) { if (!world.Handover.Ready) { return; } foreach (var stack in world.Buffers) { var blocks = stack.BottomToTop.Count; if (blocks > 0) { var top = stack.BottomToTop[blocks - 1]; if (top.Ready) { var move = new CraneMove(); move.BlockId = top.Id; move.SourceId = stack.Id; move.TargetId = world.Handover.Id; schedule.Moves.Add(move); } } } }
void PlanHandoverCrane() { var moveId = plan.Moves.Count; var sourceRequest = new List <(Location, int, Block, MoveRequest)>(); foreach (var req in world.MoveRequests) { foreach (var src in BufferStacks()) { var(block, pos) = src.Stack.BottomToTop.Select((slab, idx) => (slab, idx)).FirstOrDefault(x => x.slab.Id == req.BlockId); if (block != null) { sourceRequest.Add((src, pos, block, req)); break; } } } sourceRequest.Sort((a, b) => (SizeOf(a.Item1) - a.Item2).CompareTo(SizeOf(a.Item1) - a.Item2)); foreach (var(src, pos, block, req) in sourceRequest) { var ty = block.Type; var seq = block.Sequence; var couldTakeTopN = src.Stack.BottomToTop.Reverse().TakeWhile(b => { var isNext = b.Type == ty && b.Sequence == seq; seq += 1; return(isNext); }).Count(); var mov = new CraneMove(); moveId += 1; mov.Id = moveId; mov.Type = MoveType.PickupAndDropoff; mov.ReleaseTime = new TimeStamp() { MilliSeconds = world.Now.MilliSeconds }; mov.PickupLocationId = src.Id; if (couldTakeTopN > 0) { var amount = Math.Min(couldTakeTopN, world.HandoverCrane.CraneCapacity); mov.DropoffLocationId = req.TargetLocationId; mov.RequiredCraneId = world.HandoverCrane.Id; mov.Amount = amount; } else { // Relocate blocks that are in the way var mustRelocate = SizeOf(src) - pos - 1; var amount = Math.Min(mustRelocate, world.HandoverCrane.CraneCapacity); var tgt = BufferStacks().FirstOrDefault(tgt => tgt.Id != src.Id && RemainingCapacity(tgt) >= amount); if (tgt != null) { mov.DropoffLocationId = tgt.Id; mov.RequiredCraneId = world.HandoverCrane.Id; mov.Amount = amount; } else { continue; } } plan.Moves.Add(mov); return; } }
private IEnumerable <Event> OrderGenerator() { var moveId = _world.CraneMoves.Count == 0 ? 0 : _world.CraneMoves.Select(x => x.Id).Max(); while (true) { var newMoves = false; foreach (var b in _world.AllBlocks()) { var loc = _world.Locations.SingleOrDefault(x => x.Stack.Topmost == b); if (loc == null || _world.CraneMoves.Any(x => x.PickupLocationId == loc.Id || x.DropoffLocationId == loc.Id)) { continue; } var freeTargets = (from l in _world.Locations let lm = _world.CraneMoves.Where(x => x.Type == MoveType.PickupAndDropoff && (x.PickupLocationId == l.Id || x.DropoffLocationId == l.Id)).ToList() where l.Id != loc.Id && lm.Sum(x => { if (x.PickupLocationId == l.Id) { return(-x.Amount); } if (x.DropoffLocationId == l.Id) { return(x.Amount); } return(0); }) + l.Height < l.MaxHeight && l.FreeHeight > 0 select new { Location = l, Moves = lm }).ToList(); if (freeTargets.Count == 0) { continue; } var choice = Environment.RandChoice(freeTargets, freeTargets.Select(x => 1.0).ToList()); var move = new CraneMove() { Amount = 1, DueDate = new TimeStamp(long.MaxValue), PickupLocationId = loc.Id, PickupGirderPosition = loc.GirderPosition, DropoffLocationId = choice.Location.Id, DropoffGirderPosition = choice.Location.GirderPosition, Id = ++moveId, PredecessorIds = new HashSet <int>(choice.Moves.Select(x => x.Id)), ReleaseTime = Now, Type = MoveType.PickupAndDropoff }; _world.CraneMoves.Add(move); _moves.Add(new CraneMoveEvent(Environment, move)); newMoves = true; } if (newMoves) { _scheduler.Schedule(); } yield return(new AnyOf(Environment, CraneMoves.Select(x => x.Finished))); foreach (var finished in CraneMoves.Where(x => x.Finished.IsProcessed).ToList()) { for (var i = 0; i < _world.CraneMoves.Count; i++) { if (_world.CraneMoves[i].Id == finished.Id) { _world.CraneMoves.RemoveAt(i); break; } } _moves.Remove(finished); } } }
public static string FormatOutput(this CraneMove move) { return($"Move Block {move.BlockId} from {move.SourceId} to {move.TargetId}"); }
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); }