private static void CreateRooms(HostelAllocationDTO hostelAllocation, int hostelCapacity) { var random = new Random(); hostelAllocation.NumRooms = random.Next(5, 10); List <int> roomsCapacity = new List <int>(); for (var room = 0; room < hostelAllocation.NumRooms; room++) { if (room != hostelAllocation.NumRooms - 1) { var hostelActualCapacity = roomsCapacity.Sum(); var maxRoomSize = hostelCapacity - hostelActualCapacity > 10 + hostelAllocation.NumRooms - room ? 10 : hostelCapacity - hostelActualCapacity - hostelAllocation.NumRooms + room + 1; var roomSize = random.Next(1, maxRoomSize); roomsCapacity.Add(roomSize); } else { var freeSpaces = hostelCapacity - roomsCapacity.Sum(); var roomSize = freeSpaces > 10 ? 10 : freeSpaces; roomsCapacity.Add(roomSize); } } hostelAllocation.RoomCapacity = roomsCapacity.ToArray(); }
public static HostelAllocationDTO CreateRandomTest(string fileName) { Dictionary <int, int> groupsSizes = new Dictionary <int, int>(); HostelAllocationDTO hostelAllocation = new HostelAllocationDTO(); hostelAllocation.InitialAllocation = new List <Tuple <int, int> >(); hostelAllocation.GroupsDemands = new List <Tuple <int, int> >(); var random = new Random(); hostelAllocation.NumDays = random.Next(10, 20); //hostelAllocation.NumDays = 10; int hostelCapacity = random.Next(20, 50); //int hostelCapacity = 30; CreateRooms(hostelAllocation, hostelCapacity); hostelCapacity = hostelAllocation.RoomCapacity.Sum(); SetInitialHostelAllocation(groupsSizes, hostelAllocation); for (var day = 1; day <= hostelAllocation.NumDays; day++) { DesallocateGroupsByDay(hostelAllocation, groupsSizes, day); var dailyAllocatedGroups = hostelAllocation.GroupsDemands.Where(d => d.Item2 == day).Select(d => d.Item1).ToList(); int actualHostelCapacicity = dailyAllocatedGroups.Select(g => groupsSizes[g]).Sum(); while (actualHostelCapacicity < hostelCapacity) { int groupIndex = groupsSizes.Count; var actualHostelAllocation = hostelAllocation.GroupsDemands.Where(g => g.Item2 == day).Select(g => groupsSizes[g.Item1]).Sum(); var maxGroupSize = hostelCapacity - actualHostelAllocation > 10 ? 10 : hostelCapacity - actualHostelAllocation; if (maxGroupSize >= 1) { var groupSize = random.Next(1, maxGroupSize); groupsSizes.Add(groupIndex, groupSize); hostelAllocation.GroupsDemands.Add(new Tuple <int, int>(groupIndex, day)); actualHostelCapacicity += groupSize; } } } hostelAllocation.GroupsSizes = groupsSizes.Select(g => g.Value).ToArray(); using (StreamWriter file = File.CreateText(@"C:\\Users\\alanw\\OneDrive\\Documentos\\GitHub\\HostelAllocation\\HostelAllocationOptimization\\bin\\Debug\\netcoreapp2.0\\" + fileName)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(file, hostelAllocation); } return(hostelAllocation); }
private static void DesallocateGroupsByDay(HostelAllocationDTO hostelAllocation, Dictionary <int, int> groupsSizes, int day) { var random = new Random(); var previousGroupsAllocated = hostelAllocation.GroupsDemands.Where(d => d.Item2 == day - 1).Select(d => d.Item1).ToList(); var numGroupsToLeft = random.Next(0, previousGroupsAllocated.Count); for (var i = 0; i < numGroupsToLeft; i++) { var groupToLeft = random.Next(0, previousGroupsAllocated.Count - 1); previousGroupsAllocated.RemoveAt(groupToLeft); } foreach (var group in previousGroupsAllocated) { hostelAllocation.GroupsDemands.Add(new Tuple <int, int>(group, day)); } }
public List <DailyRoomAllocation> Post([FromBody] HostelAllocationDTO hostelAllocation) { return(HostelAllocationOptimizer.Optimize(hostelAllocation)); }
public static List <DailyRoomAllocation> Optimize(HostelAllocationDTO hostelAllocation) { try { int numDays = hostelAllocation.NumDays; int numRooms = hostelAllocation.NumRooms; int numGroups = hostelAllocation.GroupsSizes.Count(); int[] groupSize = hostelAllocation.GroupsSizes; int[] roomCapacity = hostelAllocation.RoomCapacity; List <Tuple <int, int> > groupsDemands = new List <Tuple <int, int> >(); // groupsDemands(group, day) groupsDemands = hostelAllocation.GroupsDemands; // Group 0 //groupsDemands.Add(new Tuple<int, int>(0, 0)); //groupsDemands.Add(new Tuple<int, int>(0, 1)); //groupsDemands.Add(new Tuple<int, int>(0, 2)); //// Group 1 //groupsDemands.Add(new Tuple<int, int>(1, 0)); //groupsDemands.Add(new Tuple<int, int>(1, 1)); //// Group 2 //groupsDemands.Add(new Tuple<int, int>(2, 0)); //groupsDemands.Add(new Tuple<int, int>(2, 1)); //groupsDemands.Add(new Tuple<int, int>(2, 2)); //// Group 3 //groupsDemands.Add(new Tuple<int, int>(3, 1)); //groupsDemands.Add(new Tuple<int, int>(3, 2)); //// Group 4 //groupsDemands.Add(new Tuple<int, int>(4, 1)); //groupsDemands.Add(new Tuple<int, int>(4, 2)); //// Group 5 //groupsDemands.Add(new Tuple<int, int>(5, 1)); //groupsDemands.Add(new Tuple<int, int>(5, 2)); //// Group 6 //groupsDemands.Add(new Tuple<int, int>(6, 2)); List <Tuple <int, int> > initialAllocation = new List <Tuple <int, int> >(); // initialAlocation<group, room> initialAllocation = hostelAllocation.InitialAllocation; //initialAllocation.Add(new Tuple<int, int>(0, 0)); //initialAllocation.Add(new Tuple<int, int>(1, 1)); //initialAllocation.Add(new Tuple<int, int>(2, 2)); GRBEnv env = new GRBEnv("hostel.log"); GRBModel model = new GRBModel(env); model.ModelName = "hostel"; //variável de decisão: xijk - se o grupo i está no quyarto j no dia k GRBVar[,,] x = new GRBVar[numGroups, numRooms, numDays]; for (int i = 0; i < numGroups; i++) { for (int j = 0; j < numRooms; j++) { for (int k = 0; k < numDays; k++) { x[i, j, k] = model.AddVar(0, 1, 0, GRB.BINARY, "Grupo " + x + " quarto " + j + " dia " + k); } } } //Initialize Rooms with initial alocation foreach (var alocation in initialAllocation) { x[alocation.Item1, alocation.Item2, 0].Set(GRB.DoubleAttr.LB, 1); } //variável de decisão: yik - se o grupo i mudou de quarto no dia k GRBVar[,] y = new GRBVar[numGroups, numDays]; for (int i = 0; i < numGroups; i++) { for (int k = 0; k < numDays; k++) { y[i, k] = model.AddVar(0, 1, 0, GRB.BINARY, "Grupo " + i + " mudou quarto no dia " + k); } } //Restrição 1: capacidade do quarto for (int j = 0; j < numRooms; j++) { for (int k = 0; k < numDays; k++) { GRBLinExpr roomAlocation = 0.0; for (int i = 0; i < numGroups; i++) { roomAlocation.AddTerm(groupSize[i], x[i, j, k]); } model.AddConstr(roomAlocation <= roomCapacity[j], "Capacity room " + j); } } //Restrição 2: todo grupo deverá estar alocado em algum quarto nos dias que demandou for (int i = 0; i < numGroups; i++) { for (int k = 0; k < numDays; k++) { GRBLinExpr demGroup = 0.0; if (groupsDemands.Any(d => d.Item1 == i && d.Item2 == k)) { for (int j = 0; j < numRooms; j++) { demGroup.AddTerm(1, x[i, j, k]); } model.AddConstr(demGroup == 1, "Alocação grupo " + i + " no dia " + k); } } } //Restrição 3: se o grupo i tivesse no quarto j no dia k e no dia k + 1 ele não estiver, ele mudou de quarto for (int i = 0; i < numGroups; i++) { for (int j = 0; j < numRooms; j++) { for (int k = 0; k < numDays - 1; k++) { if (k == 0 && initialAllocation.Any(d => d.Item1 == i) && groupsDemands.Any(d => d.Item1 == i && d.Item2 == k + 1)) { model.AddConstr((1 - x[i, j, k]) + x[i, j, k + 1] + y[i, k] >= 1, "Grupo " + i + " mudou de quarto dia " + k); } else if (groupsDemands.Any(d => d.Item1 == i && d.Item2 == k) && groupsDemands.Any(d => d.Item1 == i && d.Item2 == k + 1)) // O grupo tem demanda para o dia seguinte { model.AddConstr((1 - x[i, j, k]) + x[i, j, k + 1] + y[i, k] >= 1, "Grupo " + i + " mudou de quarto dia " + k); } } } } model.ModelSense = GRB.MINIMIZE; GRBLinExpr obj = 0; for (int i = 0; i < numGroups; i++) { for (int k = 0; k < numDays; k++) { obj.AddTerm(groupSize[i], y[i, k]); } } model.SetObjective(obj, GRB.MINIMIZE); // Optimize model model.Optimize(); if (model.Status == GRB.Status.INFEASIBLE) { throw new Exception("Infeasible model"); } var allocation = ListDailyGroupsAllocation(x, y, model.ObjVal); var roomsAllocation = ListDailyRoomAllocation(x, y, model.ObjVal); // Dispose of model and env model.Dispose(); env.Dispose(); return(roomsAllocation); } catch (GRBException e) { throw; //Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message); } }
private static void SetInitialHostelAllocation(Dictionary <int, int> groupsSizes, HostelAllocationDTO hostelAllocation) { var random = new Random(); var firstDayAllocation = random.Next(hostelAllocation.RoomCapacity.Sum() / 10, hostelAllocation.RoomCapacity.Sum()); var availableRoomsSpaces = hostelAllocation.RoomCapacity .Select(r => r - hostelAllocation.InitialAllocation.Where(i => i.Item2 == r).Select(i => groupsSizes[i.Item1]).Sum()).ToList(); while (firstDayAllocation > 0 && availableRoomsSpaces.Sum() >= firstDayAllocation && availableRoomsSpaces.Any(room => room > 0)) { var allocatedRooms = hostelAllocation.InitialAllocation.ToList(); var randomGroupSize = random.Next(1, availableRoomsSpaces.Max() - 1); var room = availableRoomsSpaces.Where(r => r >= randomGroupSize).First(); var roomIndex = availableRoomsSpaces.IndexOf(room); var group = groupsSizes.Count; groupsSizes.Add(group, randomGroupSize); hostelAllocation.InitialAllocation.Add(new Tuple <int, int>(group, roomIndex)); availableRoomsSpaces[roomIndex] -= randomGroupSize; firstDayAllocation -= randomGroupSize; //availableRoomsSpaces = hostelAllocation.RoomCapacity // .Select(r => r - hostelAllocation.InitialAllocation.Where(i => i.Item2 == r).Select(i => groupsSizes[i.Item1]).Sum()).ToList(); } }
private static int DailyAllocation(HostelAllocationDTO hostelAllocation, int day) { return(hostelAllocation.GroupsDemands.Where(g => g.Item2 == day).Select(g => g.Item1).Sum()); }