1 | using System.Linq;
|
---|
2 |
|
---|
3 | namespace Push.Thesis {
|
---|
4 | using System;
|
---|
5 | using System.Collections.Generic;
|
---|
6 | using System.Globalization;
|
---|
7 | using System.IO;
|
---|
8 | using System.Threading.Tasks;
|
---|
9 |
|
---|
10 | using HeuristicLab.Common;
|
---|
11 | using HeuristicLab.Data;
|
---|
12 | using HeuristicLab.Optimization;
|
---|
13 | using HeuristicLab.Persistence.Default.Xml;
|
---|
14 |
|
---|
15 | public class JobResult {
|
---|
16 | public bool IsWithOffspringSelection { get; set; }
|
---|
17 | public string Name { get; set; }
|
---|
18 | public double Best { get; set; }
|
---|
19 | public double AverageBest { get; set; }
|
---|
20 | public double StandardDeviation { get; set; }
|
---|
21 | public int SolvedCount { get; set; }
|
---|
22 | public double SolvedRelative { get; set; }
|
---|
23 | public int TotalCount { get; set; }
|
---|
24 | }
|
---|
25 |
|
---|
26 | public class RunGrouper {
|
---|
27 |
|
---|
28 | public void WriteJobResults(string jobRoot, string outputPath) {
|
---|
29 | Console.WriteLine("Write job results from {0} to {1}", jobRoot, outputPath);
|
---|
30 |
|
---|
31 | var jobResults = GetJobResults(jobRoot);
|
---|
32 |
|
---|
33 | var lines = jobResults
|
---|
34 | .Select(GetJobResultLine)
|
---|
35 | .ToList();
|
---|
36 |
|
---|
37 | File.WriteAllLines(outputPath, lines);
|
---|
38 | Console.WriteLine("JobResults written");
|
---|
39 | }
|
---|
40 |
|
---|
41 | public void WriteJobResult(string jobRoot, string outputPath) {
|
---|
42 | var jobResult = GetJobResult(jobRoot);
|
---|
43 | var line = GetJobResultLine(jobResult);
|
---|
44 |
|
---|
45 | File.WriteAllText(outputPath, line);
|
---|
46 | }
|
---|
47 |
|
---|
48 | private static string GetJobResultLine(JobResult jobResult) {
|
---|
49 | var solvedPercentage = Math.Round(jobResult.SolvedRelative * 100, 2);
|
---|
50 |
|
---|
51 | var prefix = jobResult.IsWithOffspringSelection
|
---|
52 | ? "[OSGA]"
|
---|
53 | : "[GA] ";
|
---|
54 |
|
---|
55 | return string.Format(
|
---|
56 | @"{7} {0} {1} {2} {3} {4} {5} {6}\%",
|
---|
57 | jobResult.Name.PadRight(28),
|
---|
58 | jobResult.Best.ToString("N4", CultureInfo.InvariantCulture).PadLeft(12),
|
---|
59 | jobResult.AverageBest.ToString("N4", CultureInfo.InvariantCulture).PadLeft(12),
|
---|
60 | jobResult.StandardDeviation.ToString("N4", CultureInfo.InvariantCulture).PadLeft(12),
|
---|
61 | jobResult.SolvedCount.ToString().PadLeft(4),
|
---|
62 | jobResult.TotalCount.ToString().PadLeft(4),
|
---|
63 | solvedPercentage.ToString("N2").PadLeft(6),
|
---|
64 | prefix
|
---|
65 | );
|
---|
66 | }
|
---|
67 |
|
---|
68 | protected virtual bool CanFileBeRead(string path) {
|
---|
69 | return !IsFileLocked(path);
|
---|
70 | }
|
---|
71 |
|
---|
72 | protected virtual bool IsFileLocked(string path) {
|
---|
73 | var fileInfo = new FileInfo(path);
|
---|
74 |
|
---|
75 | return IsFileLocked(fileInfo);
|
---|
76 | }
|
---|
77 |
|
---|
78 | protected virtual bool IsFileLocked(FileInfo file) {
|
---|
79 | FileStream stream = null;
|
---|
80 |
|
---|
81 | try {
|
---|
82 | stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
|
---|
83 | }
|
---|
84 | catch (IOException) {
|
---|
85 | //the file is unavailable because it is:
|
---|
86 | //still being written to
|
---|
87 | //or being processed by another thread
|
---|
88 | //or does not exist (has already been processed)
|
---|
89 | return true;
|
---|
90 | }
|
---|
91 | finally {
|
---|
92 | if (stream != null)
|
---|
93 | stream.Close();
|
---|
94 | }
|
---|
95 |
|
---|
96 | //file is not locked
|
---|
97 | return false;
|
---|
98 | }
|
---|
99 |
|
---|
100 | public IReadOnlyList<JobResult> GetJobResults(string rootPath) {
|
---|
101 | Console.WriteLine("GetJobResults from {0}", rootPath);
|
---|
102 |
|
---|
103 | if (!Directory.Exists(rootPath)) {
|
---|
104 | Console.WriteLine("Directory {0} not found", rootPath);
|
---|
105 | throw new FileNotFoundException(rootPath);
|
---|
106 | }
|
---|
107 |
|
---|
108 | var jobResults = Directory
|
---|
109 | .EnumerateDirectories(rootPath)
|
---|
110 | .AsParallel()
|
---|
111 | .Select(GetJobResult)
|
---|
112 | .OrderBy(jr => jr.Name)
|
---|
113 | .ToList();
|
---|
114 |
|
---|
115 | Console.WriteLine("JobResults read");
|
---|
116 | return jobResults;
|
---|
117 | }
|
---|
118 |
|
---|
119 | public JobResult GetJobResult(string rootPath) {
|
---|
120 | if (!Directory.Exists(rootPath)) {
|
---|
121 | Console.WriteLine("Directory {0} not found\n", rootPath);
|
---|
122 | throw new FileNotFoundException(rootPath);
|
---|
123 | }
|
---|
124 |
|
---|
125 | var directoryInfo = new DirectoryInfo(rootPath);
|
---|
126 | var name = GetJobName(directoryInfo.Name);
|
---|
127 |
|
---|
128 | Console.WriteLine("Get job {0}", name);
|
---|
129 |
|
---|
130 | var runs = this.GetRuns(rootPath);
|
---|
131 |
|
---|
132 | var bestResults = runs.Select(r => (r.Results["BestQuality"] as DoubleValue).Value).ToList();
|
---|
133 | var best = bestResults.Min();
|
---|
134 | var avg = bestResults.Average();
|
---|
135 | var stdDeviation = StandardDeviation(bestResults);
|
---|
136 | var solvedCount = bestResults.Count(x => x.IsAlmost(0));
|
---|
137 | var totalCount = runs.Count;
|
---|
138 | var solvedRelative = solvedCount / (double)totalCount;
|
---|
139 | var isWithOffspringSelection = directoryInfo.Name.Contains("[Offspring GA]");
|
---|
140 |
|
---|
141 | return new JobResult {
|
---|
142 | Name = name,
|
---|
143 | Best = best,
|
---|
144 | AverageBest = avg,
|
---|
145 | StandardDeviation = stdDeviation,
|
---|
146 | SolvedCount = solvedCount,
|
---|
147 | SolvedRelative = solvedRelative,
|
---|
148 | TotalCount = totalCount,
|
---|
149 | IsWithOffspringSelection = isWithOffspringSelection
|
---|
150 | };
|
---|
151 | }
|
---|
152 |
|
---|
153 | private static string GetJobName(string totalName) {
|
---|
154 | var start = totalName.LastIndexOf(']') + 2;
|
---|
155 | var end = totalName.IndexOf('-') - 1;
|
---|
156 | var length = end - start;
|
---|
157 |
|
---|
158 | var name = length > 0
|
---|
159 | ? totalName.Substring(start, length)
|
---|
160 | : totalName;
|
---|
161 |
|
---|
162 | return name;
|
---|
163 | }
|
---|
164 |
|
---|
165 | public static double StandardDeviation(IEnumerable<double> values) {
|
---|
166 | var avg = values.Average();
|
---|
167 | return Math.Sqrt(values.Average(v => Math.Pow(v - avg, 2)));
|
---|
168 | }
|
---|
169 |
|
---|
170 | public void DoAllJobs(string rootPath) {
|
---|
171 | if (!Directory.Exists(rootPath)) {
|
---|
172 | throw new FileNotFoundException(rootPath);
|
---|
173 | }
|
---|
174 |
|
---|
175 | var jobDirs = Directory.EnumerateDirectories(rootPath);
|
---|
176 | Parallel.ForEach(jobDirs, DoSingleJob);
|
---|
177 | }
|
---|
178 |
|
---|
179 | public void DoSingleJob(string rootPath) {
|
---|
180 | if (!Directory.Exists(rootPath)) {
|
---|
181 | throw new FileNotFoundException(rootPath);
|
---|
182 | }
|
---|
183 |
|
---|
184 | var directoryInfo = new DirectoryInfo(rootPath);
|
---|
185 | var fileName = "Grouped - " + directoryInfo.Name;
|
---|
186 | var outputPath = Path.Combine(directoryInfo.Parent.FullName, fileName + ".hl");
|
---|
187 |
|
---|
188 | if (File.Exists(outputPath)) {
|
---|
189 | Console.WriteLine(@"Experiment {0} already exists", fileName);
|
---|
190 | return;
|
---|
191 | }
|
---|
192 |
|
---|
193 | var runs = GetRuns(rootPath);
|
---|
194 |
|
---|
195 | var runCollection = new RunCollection();
|
---|
196 | runCollection.AddRange(runs);
|
---|
197 |
|
---|
198 | ContentManager.Save(runCollection, outputPath, true);
|
---|
199 | }
|
---|
200 |
|
---|
201 | public IReadOnlyList<Run> GetRuns(string rootPath) {
|
---|
202 | var runs = Directory
|
---|
203 | .EnumerateFiles(rootPath)
|
---|
204 | .AsParallel()
|
---|
205 | .Where(CanFileBeRead)
|
---|
206 | .Select(XmlParser.Deserialize)
|
---|
207 | .Where(x => x is IAlgorithm)
|
---|
208 | .Cast<IAlgorithm>()
|
---|
209 | .Select(alg => new Run(alg))
|
---|
210 | .ToList();
|
---|
211 |
|
---|
212 | return runs;
|
---|
213 | }
|
---|
214 | }
|
---|
215 | }
|
---|