public Solution CreateInitSolution(Problem problem, Random rnd) { var cacheLoads = new CacheLoad[problem.C]; for (var c = 0; c < problem.C; c++) { var videos = new HashSet <int>(); var size = 0ul; while (true) { var video = problem.Videos.Where(v => v.Size <= problem.X - size).RandomElement(rnd, false); if (video == null) { break; } videos.Add(video.VideoId); size += video.Size; } cacheLoads[c] = new CacheLoad { CacheId = c, VideoIds = videos }; } return(new Solution { CacheLoads = cacheLoads }); }
public Solution GetNeighboor(Problem problem, Solution solution, Random rnd) { var cacheLoads = solution.CacheLoads; while (true) { var p = rnd.NextDouble(); if (p < 0.25) { // Add video var cacheLoadIndex = cacheLoads.RandomIndex(rnd); var cacheLoad = cacheLoads[cacheLoadIndex]; var size = cacheLoad.VideoIds.Select(v => problem.Videos[v].Size).Sum(); var video = problem.Videos.Where(v => v.Size <= problem.X - size).RandomElement(rnd, false); if (video != null) { var newLoads = cacheLoads.ShallowClone(); newLoads[cacheLoadIndex] = new CacheLoad { CacheId = cacheLoad.CacheId, VideoIds = cacheLoad.VideoIds.ToHashSet(), }; newLoads[cacheLoadIndex].VideoIds.Add(video.VideoId); return(new Solution { CacheLoads = newLoads }); } } else if (p < 0.5) { // Swap video between server and pool var cacheLoadIndex = cacheLoads.RandomIndex(rnd); var cacheLoad = cacheLoads[cacheLoadIndex]; if (cacheLoad.VideoIds.Count == 0) { continue; } var solVideoId = cacheLoad.VideoIds.RandomElement(rnd); var size = cacheLoad.VideoIds.Select(v => problem.Videos[v].Size).Sum() - problem.Videos[solVideoId].Size; var poolVideo = problem.Videos.Where(v => v.Size <= problem.X - size).RandomElement(rnd, false); if (poolVideo == null) { continue; } var newLoads = cacheLoads.ShallowClone(); newLoads[cacheLoadIndex] = new CacheLoad { CacheId = cacheLoad.CacheId, VideoIds = cacheLoad.VideoIds.ToHashSet(), }; newLoads[cacheLoadIndex].VideoIds.Remove(solVideoId); newLoads[cacheLoadIndex].VideoIds.Add(poolVideo.VideoId); return(new Solution { CacheLoads = newLoads }); } else if (p < 0.85) { // Swap video between servers var cacheLoadIndexOne = cacheLoads.IndicesWhere(c => c.VideoIds.Count > 0).RandomElement(rnd, false); var cacheLoadIndexTwo = cacheLoads.IndicesWhere(c => c.VideoIds.Count > 0).RandomElement(rnd, false); if (cacheLoadIndexOne == cacheLoadIndexTwo || cacheLoads[cacheLoadIndexOne].VideoIds.Count == 0 || cacheLoads[cacheLoadIndexTwo].VideoIds.Count == 0) { continue; } var cacheLoadOne = cacheLoads[cacheLoadIndexOne]; var cacheLoadTwo = cacheLoads[cacheLoadIndexTwo]; var videoOneId = cacheLoadOne.VideoIds.RandomElement(rnd); var videoOneSize = problem.Videos[videoOneId].Size; var sizeOne = cacheLoadOne.VideoIds.Select(v => problem.Videos[v].Size).Sum() - videoOneSize; var sizeTwoAll = cacheLoadTwo.VideoIds.Select(v => problem.Videos[v].Size).Sum(); var videoTwo = cacheLoadTwo.VideoIds.Select(v => problem.Videos[v]).Where(v => sizeTwoAll - v.Size + videoOneSize <= problem.X).RandomElement(rnd, false); if (videoTwo == null) { continue; } if (sizeOne + videoTwo.Size > problem.X) { continue; } var newLoads = cacheLoads.ShallowClone(); newLoads[cacheLoadIndexOne] = new CacheLoad { CacheId = cacheLoadOne.CacheId, VideoIds = cacheLoadOne.VideoIds.ToHashSet(), }; newLoads[cacheLoadIndexTwo] = new CacheLoad { CacheId = cacheLoadTwo.CacheId, VideoIds = cacheLoadTwo.VideoIds.ToHashSet(), }; newLoads[cacheLoadIndexOne].VideoIds.Remove(videoOneId); newLoads[cacheLoadIndexOne].VideoIds.Add(videoTwo.VideoId); newLoads[cacheLoadIndexTwo].VideoIds.Remove(videoTwo.VideoId); newLoads[cacheLoadIndexTwo].VideoIds.Add(videoOneId); return(new Solution { CacheLoads = newLoads }); } else { // Remove video var cacheLoadIndex = cacheLoads.RandomIndex(rnd); var cacheLoad = cacheLoads[cacheLoadIndex]; if (cacheLoad.VideoIds.Count > 0) { var removeVideoId = cacheLoad.VideoIds.RandomElement(rnd); var newLoads = cacheLoads.ShallowClone(); newLoads[cacheLoadIndex] = new CacheLoad { CacheId = cacheLoad.CacheId, VideoIds = cacheLoad.VideoIds.ToHashSet(), }; newLoads[cacheLoadIndex].VideoIds.Remove(removeVideoId); return(new Solution { CacheLoads = newLoads }); } } } }