Beispiel #1
0
 public Drone(Input input, int id)
 {
     this.input = input;
     this.id = id;
     X = input.WareHouses[0].X;
     Y = input.WareHouses[0].Y;
 }
Beispiel #2
0
 public Solution(Input input)
 {
     _input = input;
     _deliveryOrders = new StringBuilder[input.NbDrones];
     for (int i = 0; i < input.NbDrones; i++)
         _deliveryOrders[i] = new StringBuilder();
 }
Beispiel #3
0
        public static Input Parse(string fileName)
        {
            var input = new Input();
            using(var reader = new StreamReader(fileName))
            {
                var inputParams = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray();
                input.R = inputParams[0];
                input.C = inputParams[1];
                input.NbDrones = inputParams[2];
                input.NbTurns = inputParams[3];
                input.MaxPayload = inputParams[4];

                reader.ReadLine(); //nb product types, osef
                input.ProductTypes = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray();

                input.NbWareHouses = Int32.Parse(reader.ReadLine());
                input.WareHouses = new WareHouse[input.NbWareHouses];

                for(int i = 0; i < input.NbWareHouses; i++)
                {
                    var coords = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray();
                    input.WareHouses[i] = new WareHouse{
                        X = coords[0],
                        Y = coords[1],
                        id = i,
                        Stock = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray(),
                    };
                }

                var nbOrders = Int32.Parse(reader.ReadLine());
                input.Orders = new Order[nbOrders];
                for(int i = 0; i < nbOrders; i++)
                {
                    var coords = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray();
                    var order = new Order {
                        X = coords[0],
                        Y = coords[1],
                        id = i,
                        NbItemsRemaining = Int32.Parse(reader.ReadLine()),
                        ItemsWanted = reader.ReadLine().Split(' ').Select(Int32.Parse).ToArray(),
                    };
                    order.TotalWeight = order.ItemsWanted.Sum(item => input.ProductTypes[item]);
                    Array.Sort(order.ItemsWanted);
                    input.Orders[i] = order;
                }
            }
            return input;
        }
Beispiel #4
0
        public static Input Parse(string fileName)
        {
            var input = new Input();
            using (var reader = new StreamReader(fileName))
            {
                input.NbTurns = ReadInt(reader);

                var nbSat = ReadInt(reader);
                for (int i = 0; i < nbSat; i++)
                {
                    var line = ReadMulti(reader);
                    var sat = new Satellite(
                        lat: line[0],
                        lon: line[1],
                        speed: line[2],
                        rotSpeed: line[3],
                        maxRot: line[4],
                        id: i);
                    input.Satellites.Add(sat);
                }

                var nbCollec = ReadInt(reader);
                var picId = 0;
                for (int i = 0; i < nbCollec; i++)
                {
                    var line = ReadMulti(reader);
                    var collec = new PicCollection(line[0], picId);
                    var nbLoc = line[1];
                    picId += nbLoc;
                    for (int j = 0; j < nbLoc; j++)
                    {
                        var loc = ReadMulti(reader);
                        collec.Locations.Add(new Coords {Lat = loc[0], Lon = loc[1]});
                    }
                    var nbRanges = line[2];
                    for (int j = 0; j < nbRanges; j++)
                    {
                        var time = ReadMulti(reader);
                        collec.TimeRanges.Add(new TimeRange(time[0], time[1]));
                    }
                    input.Collections.Add(collec);
                }
            }
            return input;
        }
Beispiel #5
0
        public static Solution Solve(Input input)
        {
            var takenPictures = new List<Snapshot>();

            var tree = new KdTree<float, PicCollection>(2, new FloatMath());

            foreach (var picCollection in input.Collections)
            {
                foreach (var pict in picCollection.Locations)
                {
                    tree.Add(new float[] { pict.Lat, pict.Lon }, picCollection);
                }
            }
            tree.Balance();

            var orderedSatellelites = input.Satellites.OrderByDescending(sat => sat.MaxRot).ToList();

            for (int s = 0; s < orderedSatellelites.Count; ++s)
            {
                var satellite = orderedSatellelites[s];

                for (int turn = 0; turn < input.NbTurns; ++turn)
                {
                    var node = tree.RadialSearch(new float[] { satellite.Pos.Lat, satellite.Pos.Lon }, satellite.MaxRot*SQRT2, 150).ToArray();

                    if (node.Length > 0)
                    {
                        var valids = node.Where(n => n.Value.PictureCanBeTaken(turn))
                            .Where(k => satellite.CanTakePicture((int)k.Point[0], (int)k.Point[1]))
                            .OrderByDescending(k => Math.Pow(k.Point[0] - satellite.Pos.Lat, 2) + Math.Pow(k.Point[1] - satellite.Pos.Lon, 2))
                            //.OrderByDescending(k => k.Value.TakenPictures.Count)
                            .ToList();

                        if (valids.Count > 0)
                        {
                            Console.WriteLine("Found {0} valid new positions", valids.Count);

                            var pict = valids[0];
                            var pictCoord = new Coords((int)pict.Point[0], (int)pict.Point[1]);

                            var snap = satellite.TakePicture(pictCoord);
                            takenPictures.Add(snap);
                            pict.Value.TakePicture(pictCoord);
                            pict.Value.Locations.Remove(pictCoord);
                            tree.RemoveAt(pict.Point);
                            Console.WriteLine("Satellite {1} Found {0} pict - Turn {2}", node.Length, satellite.Id, turn);

                            ////Console.WriteLine("Satellite Lat {0} Lon {1} Pict {2} {3} Rot {4} {5}", satellite.Pos.Lat,
                            //satellite.Pos.Lon, pict.Point[0], pict.Point[1], satellite.CurrentRot.Lat, satellite.CurrentRot.Lon);
                        }

                    }
                    satellite.NextTurn();
                }
            }

            var score = input.Collections.Where(c => c.Locations.Count == 0 && c.TakenPictures.Count > 0).Sum(p => p.Value);

            var solution = new Solution(takenPictures, score);

            return solution;
        }
Beispiel #6
0
        public static Solution Solve(Input input)
        {
            _multidroneMalus = 1.0 + Helper.Rand.NextDouble(); //choose a random malus between 1 and 2 for this run

            var solution = new Solution(input);

            var drones = new Drone[input.NbDrones];
            for (int d = 0; d < input.NbDrones; d++)
            {
                drones[d] = new Drone(input, d);
            }

            var iteration = 0; //to ease debuging a particular step
            while (true)
            {
                iteration++;

                //chooseDrone furthest in the past
                Drone chosen = drones[0];
                for (int d = 1; d < drones.Length; d++)
                {
                    if (drones[d].turn < chosen.turn)
                        chosen = drones[d];
                }
                if (chosen.turn > input.NbTurns)
                {
                    Console.WriteLine("end of times reached");
                    return solution; //can't do shit anymore
                }

                //choose order
                WareHouse wh;
                var order = GetBestOrder(chosen, input, out wh);
                if (order == null)
                {
                    return solution; //no more order to deliver
                }

                if (wh != null)
                {
                    //go to warehouse and load everything
                    for (int i = 0; i < order.ItemsWanted.Length; i++)
                    {
                        var itemType = order.ItemsWanted[i];
                        if(itemType < 0)
                            continue;

                        wh.Stock[itemType]--;
                        Helper.Assert(() => wh.Stock[itemType] >= 0);
                        chosen.Load(wh, itemType);
                        solution.LoadForDelivery(chosen, wh, order, itemType);
                    }
                    //everything is loaded
                    for (int dd = 0; dd < order.NbItemsRemaining; dd++)
                    {
                        chosen.Deliver(order);
                    }
                    solution.DoDeliver(chosen, order, orderComplete: true);
                    order.ItemsWanted = null;
                }
                else //we'll have to go to several warehouses to load stuff OR we'll need several drones
                {
                    var loadedToDeliver = new List<int>();
                    var itemsToDeliver = (int[]) order.ItemsWanted.Clone();
                    while(itemsToDeliver.Any(it => it >= 0))
                    {
                        //best warehouse with item in stock
                        double bestScore = Double.PositiveInfinity;
                        WareHouse bestwh = null;
                        List<int> availableItems = null;
                        for (int w = 0; w < input.NbWareHouses; w++)
                        {
                            var currentwh = input.WareHouses[w];
                            var items = currentwh.GetFulfillable(itemsToDeliver);
                            if (items.Count > 0)
                            {
                                var score = (double) Helper.Distance(chosen.X, chosen.Y, currentwh.X, currentwh.Y)/items.Count; //time per item
                                if (score < bestScore)
                                {
                                    bestScore = score;
                                    bestwh = currentwh;
                                    availableItems = items;
                                }
                            }
                        }
                        wh = bestwh;

                        for (int i = 0; i < availableItems.Count; i++)
                        {
                            var itemType = order.ItemsWanted[availableItems[i]];
                            if (itemType < 0) //already delivered
                                continue;

                            if (!chosen.CheckLoad(wh, itemType))
                            {
                                //drone passed end of turns or is full
                                goto deliver; //maybe we could stash one or two more small items, but whatever
                            }
                            wh.Stock[itemType]--;
                            itemsToDeliver[availableItems[i]] = -1;
                            chosen.Load(wh, itemType);
                            solution.LoadForDelivery(chosen, wh, order, itemType);
                            loadedToDeliver.Add(availableItems[i]);
                        }
                    }
                deliver:
                    for (int dd = 0; dd < loadedToDeliver.Count; dd++)
                    {
                        chosen.Deliver(order);
                    }
                    for (int i = 0; i < loadedToDeliver.Count; i++)
                    {
                        Helper.Assert(() => order.ItemsWanted[loadedToDeliver[i]] >= 0);

                        order.TotalWeight -= input.ProductTypes[order.ItemsWanted[loadedToDeliver[i]]];
                        order.ItemsWanted[loadedToDeliver[i]] = -1; //mark as delivered
                        order.NbItemsRemaining--;
                    }
                    var orderComplete = order.NbItemsRemaining == 0;
                    if (orderComplete)
                    {
                        Helper.Assert(() => order.ItemsWanted.All(it => it < 0));
                        order.ItemsWanted = null;
                    }
                    else
                    {
                        Helper.Assert(() => order.ItemsWanted.Any(it => it >= 0));
                    }
                    solution.DoDeliver(chosen, order, orderComplete);
                }
            }
        }
Beispiel #7
0
        private static Order GetBestOrder(Drone d, Input input, out WareHouse goThere)
        {
            goThere = null;

            int bestCost = Int32.MaxValue;
            Order best = null;
            foreach (var order in input.Orders)
            {
                if(order.ItemsWanted == null)
                    continue; //already delivered

                int cost = Int32.MaxValue;
                WareHouse bestWh = null;
                var totalWeight = order.TotalWeight;
                if (totalWeight < input.MaxPayload) //one drone can take care of this order
                {
                    var eligibleWareHouses = input.WareHouses.Where(wh => wh.CanFullfillOrder(order.ItemsWanted) == order.NbItemsRemaining);
                    if (eligibleWareHouses.Any()) //everything is in the same warehouse
                    {
                        foreach (var wh in eligibleWareHouses)
                        {
                            var dist = Helper.Distance(d.X, d.Y, wh.X, wh.Y) + Helper.Distance(wh.X, wh.Y, order.X, order.Y);
                            if (dist < cost)
                            {
                                cost = dist;
                                bestWh = wh;
                            }
                        }
                    }
                    else //one drone can do everything, but has to go to several warehouses
                    {
                        //simulate going to 3 different wh
                        int dist = 0;
                        var wh = input.WareHouses[Helper.Rand.Next(input.NbWareHouses)];
                        dist += Helper.Distance(d.X, d.Y, wh.X, wh.Y) * 3;
                        dist += Helper.Distance(order.X, order.Y, wh.X, wh.Y);
                        if (dist < cost)
                        {
                            cost = dist;
                        }
                    }
                }
                else //we'll need several drones to complete this order
                {
                    //simulate going to 3 different wh
                    int dist = 0;
                    var wh = input.WareHouses[Helper.Rand.Next(input.NbWareHouses)];
                    dist += Helper.Distance(d.X, d.Y, wh.X, wh.Y)*3;
                    dist += Helper.Distance(order.X, order.Y, wh.X, wh.Y);
                    dist = (int)(_multidroneMalus * dist * totalWeight/input.MaxPayload); //apply a malus for estimated nb of drones needed
                    if (dist < cost)
                    {
                        cost = dist;
                    }
                }

                if (cost < bestCost)
                {
                    bestCost = cost;
                    best = order;
                    goThere = bestWh;
                }
            }
            return best;
        }
Beispiel #8
0
        public static Solution Solve(Input input)
        {
            var tree = BuildTree(input);
            var satellites = input.Satellites.OrderBy(s => s.MaxRot).ToArray();
            var totalNbPic = tree.Count;
            var solution = new List<Snapshot>();

            var picturesConfirmed = new BitArray(totalNbPic);
            for (int s = 0; s < satellites.Length; s++)
            {
                var satellite = satellites[s];
                Console.WriteLine($"satellite {s+1}/{satellites.Length} (#{satellite.Id})");

                var state = new List<PartialSolution> {new PartialSolution(picturesConfirmed)};

                for (int t = 1; t < input.NbTurns; t++)
                {
                    if (t % 20000 == 0) Console.WriteLine(t);

                    Step(state, satellite);
                    SimplifyRanges(state);

                    //look for pictures to take
                    var candidates = tree.RadialSearch(new float[] {satellite.Pos.Lat, satellite.Pos.Lon}, satellite.MaxRot*SQRT2, 150); //TOO SLOW !
                    Helper.Assert(() => candidates.Length < 145, candidates.Length);
                    candidates = candidates.Where(node => !picturesConfirmed.Get(node.Value.Item1 + node.Value.Item2.BasePicId) && node.Value.Item2.PictureCanBeTaken(t)).ToArray();

                    var stopIdx = state.Count; //we're gonna add more, but we don't want to browse'em
                    for (int st = 0; st < stopIdx; st++)
                    {
                        var sol = state[st];
                        var range = sol.CurrentRange;
                        foreach (var candidate in candidates)
                        {
                            var collec = candidate.Value.Item2;
                            var picIdx = candidate.Value.Item1;
                            if(sol.PicturesTaken.Get(collec.BasePicId + picIdx))
                                continue;

                            var picLoc = collec.Locations[picIdx];
                            if (picLoc.IsInRange(range, satellite.Pos))
                            {
                                var newScore = sol.EstimatedValue + Score(collec, sol);
                                var newRange = new Range(satellite.Pos, picLoc);
                                if (!WorthTaking(newScore, newRange, state))
                                    continue;

                                var newCommands = new List<Snapshot>(sol.Snapshots);
                                newCommands.Add(new Snapshot(picLoc.Lat, picLoc.Lon, t, satellite.Id));
                                var taken = new BitArray(sol.PicturesTaken);
                                taken.Set(collec.BasePicId + picIdx, true);
                                state.Add(new PartialSolution (newScore, newRange, newCommands, taken));
                            }
                        }
                    }
                }

                PartialSolution best = null;
                foreach (var partialSolution in state)
                {
                    if (best == null || partialSolution.EstimatedValue > best.EstimatedValue)
                        best = partialSolution;
                }
                solution.AddRange(best.Snapshots);
                picturesConfirmed.Or(best.PicturesTaken); //union
            }

            int score = 0;
            foreach (var picCollection in input.Collections)
            {
                bool complete = true;
                var stop = picCollection.BasePicId + picCollection.Locations.Count;
                for (int i = picCollection.BasePicId; i < stop; i++)
                {
                    if (!picturesConfirmed.Get(i))
                    {
                        complete = false;
                        break;
                    }
                }
                if (complete)
                    score += picCollection.Value;
            }
            return new Solution(solution, score);
        }
Beispiel #9
0
        private static KdTree<float, Tuple<int, PicCollection>> BuildTree(Input input)
        {
            var tree = new KdTree<float, Tuple<int, PicCollection>>(2, new FloatMath());

            foreach (var picCollection in input.Collections)
            {
                for (int p = 0; p < picCollection.Locations.Count; p++)
                {
                    var pict = picCollection.Locations[p];
                    tree.Add(new float[] {pict.Lat, pict.Lon}, Tuple.Create(p, picCollection));
                }
            }
            tree.Balance();
            return tree;
        }