static void Main(string[] args) { string folder = args.Length != 1 ? @"..\..\Resources\" : args[0]; Console.WriteLine($"{GetTimeStamp()} Files must be in folder {folder}. Use the first argument to specify another folder."); Console.Write($"{GetTimeStamp()} Enter # of neighbors [50-10000]: "); int neighbors; if (!int.TryParse(Console.ReadLine(), out neighbors)) { Console.Write("Unable to parse input."); } else { neighbors = neighbors < 50 ? 50 : (neighbors > 10000 ? 10000 : neighbors); } Console.WriteLine($"{GetTimeStamp()} neighbors set to: {neighbors}"); Console.WriteLine($"{GetTimeStamp()} Loading data..."); const string moviesFile = "movie_titles.txt"; const string trainingRatingsFile = "TrainingRatings.txt"; const string testRatingsFile = "TestingRatings.txt"; // ReSharper disable once UnusedVariable MovieData movies = ParseMoviesData(File.ReadAllLines(Path.Combine(folder, moviesFile))); RatingData trainingRatings = ParseRatingData(File.ReadAllLines(Path.Combine(folder, trainingRatingsFile))); RatingData testRatings = ParseRatingData(File.ReadAllLines(Path.Combine(folder, testRatingsFile))); Console.WriteLine($"{GetTimeStamp()} Done."); DateTime now = DateTime.Now; long index = 0; var results = new List <Tuple <double /*predicted*/, double /*actual*/> >(); //Parallel.ForEach(testRatings.GetUsers().TakeWhile(x => Interlocked.Read(ref index) < 5000), userId => Parallel.ForEach(testRatings.GetUsers(), userId => { if (Interlocked.Add(ref index, 1) % 100 == 0) { PrintProgress(index, now, testRatings.GetUsersCount()); } var ratings = testRatings.GetUserRatings(userId); foreach (var movieRating in ratings) { double actual = movieRating.Value; double predicted = trainingRatings.PredictMovieRating(userId, movieRating.Key, neighbors); lock (results) results.Add(new Tuple <double, double>(predicted, actual)); } }); PrintProgress(index, now, testRatings.GetUsersCount()); double mae = CalculateMAE(results); double mape = CalculateMAPE(results); double rmsd = CalculateRMSD(results); Console.WriteLine(); Console.WriteLine($"{GetTimeStamp()} MAE={mae} (Mean Absolute Error)"); Console.WriteLine($"{GetTimeStamp()} MAPE={mape} (Mean Absolute Percentage Error)"); Console.WriteLine($"{GetTimeStamp()} RMSD={rmsd} (Root-mean-square deviation)"); }