Examples : WriteSolutionExample.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using VRSolver;
namespace Examples
{
/// <summary>
/// Shows how to get detailed information about each Resource's route,
/// such as arrival times, departure times, idle time, load constraints
/// etc.
/// </summary>
class WriteSolutionExample
{
/// <summary>
/// Writes the routes for each Resource to a file. (Shows how to use
/// The RouteItem, RouteMetrics and SolutionMetrics classes)
/// </summary>
internal static void WriteSolution(Solution solution, string fileName)
{
using (StreamWriter sw = new StreamWriter(fileName))
{
//
// First write a summary for the Solution
//
SolutionMetrics solutionMetrics = solution.GetSolutionMetrics();
sw.WriteLine("--------");
sw.WriteLine("Solution");
sw.WriteLine("--------");
sw.WriteLine("Resources used " + solutionMetrics.ResourceCount);
sw.WriteLine("Total distance " + solutionMetrics.TotalDistance.ToString("0.00"));
sw.WriteLine("Total work time " + GetDurationLabel((int)Math.Round(solutionMetrics.WorkTimeTotal.TotalMinutes)));
sw.WriteLine("Total idle time " + GetDurationLabel((int)Math.Round(solutionMetrics.IdleTimeTotal.TotalMinutes)));
sw.WriteLine("Jobs not assigned " + solutionMetrics.UnassignedJobsCount);
sw.WriteLine("Obj. Func. Value " + solution.ObjectiveFunctionValue.ToString("0.00"));
sw.WriteLine();
//
// Now write the summary and schedule for each route for each resource
//
int r = 0;
foreach (Resource resource in solution.Problem.Resources)
{
// Get the route information for this Resource
RouteItem[] routeItems = solution.GetDetailedRoute(resource);
// Nothing is assigned to the Resource if the length is less than three (only the start and end location)
if (routeItems.Length <= 2)
continue;
sw.WriteLine("R" + r++ + " (Resource " + resource.ID + ", Capacity "
+ GetLoadLabel(resource.MaxLoad)
+ ", Weight " + resource.UseCost + ")");
//
// Get the Metrics for this Resource's route
//
RouteMetrics routeMetrics = solution.GetRouteMetrics(resource);
//
// Write the summary header
//
sw.WriteLine("Distance" + "\t" +
"Duty time" + "\t" +
"Drive time" + "\t" +
"Idle" + "\t" +
"Late" + "\t" +
"Distance cost" + "\t" +
"Min duty cost" + "\t" +
"Max duty cost" + "\t" +
"Value" + "\t");
sw.WriteLine(routeMetrics.TotalDistance.ToString("0.00") + "\t"
+ GetDurationLabel((int)routeMetrics.WorkTimeTotal.TotalMinutes) + "\t"
+ GetDurationLabel((int)routeMetrics.DrivingTimeTotal.TotalMinutes) + "\t"
+ GetDurationLabel((int)routeMetrics.IdleTimeTotal.TotalMinutes) + "\t"
+ GetDurationLabel((int)routeMetrics.LateTimeTotal.TotalMinutes) + "\t"
+ routeMetrics.DistanceCost.ToString("0.00") + "\t"
+ routeMetrics.MinWorkTimeCost.ToString("0.00") + "\t"
+ routeMetrics.MaxWorkTimeCost.ToString("0.00") + "\t"
+ routeMetrics.JobWeightTotal.ToString("0.00") + "\t"
);
// Write the route header
string[] header = new string[] { " ", "Location", "Window", "Target Window", "Job Load", "Service Time",
"Arrive", "Idle", "Late", "Depart", "Journey", "Break", "Current Load", "Distance", "Value" };
foreach (string str in header)
sw.Write(str + "\t");
sw.WriteLine();
int previousLocation = -1;
int locationChangeCounter = -1;
for (int i = 0; i < routeItems.Length; i++)
{
RouteItem item = routeItems[i];
if (item.JobPart.Loc.Index != previousLocation)
locationChangeCounter++;
previousLocation = item.JobPart.Loc.Index;
string name;
string window = GetTime(item.JobPart.WindowOpen) + "-" + GetTime(item.JobPart.WindowClose);
string softwindowend = item.JobPart.SoftWindowIsUsed ? GetTime(item.JobPart.SoftWindowClose) : "-";
string load = " ";
string service = " ";
string idle = " ";
string late = " ";
string arrival = " ";
string depart = " ";
string journey = " ";
string location = " ";
string distance = "0.0";
string jobvalue = " ";
string breakTime = GetDurationLabel((int)item.Break.TotalMinutes);
long previousBreakTime = i > 0 ? routeItems[i - 1].Break.Ticks : 0;
string currentload = GetLoadLabel(item.CurrentLoad);
if (string.IsNullOrEmpty(currentload))
currentload = "-";
if (item.ItemType == RouteItemType.Start)
{
name = "start";
depart = GetTime(item.DepartureTime);
journey = GetDurationLabel((int)item.TravelTimeToNext.TotalMinutes);
distance = item.DistanceToNext.ToString("0.0");
location = "[S] " + item.JobPart.Loc.Index.ToString("000");
}
else if (item.ItemType == RouteItemType.End)
{
name = "end";
arrival = GetTime(item.ArrivalTime);
location = "[E] " + item.JobPart.Loc.Index.ToString("000");
}
else
{
name = "j [" + item.JobPartIndex + "]" + " (" + item.JobPart.ID + ")";
load = GetLoadLabel(item.JobPart.LoadChange);
service = GetDurationLabel((int)item.ServiceTime.TotalMinutes);
idle = GetDurationLabel((int)Math.Ceiling(item.IdleTime.TotalMinutes));
late = GetDurationLabel((int)Math.Ceiling(item.LateTime.TotalMinutes));
arrival = GetTime(item.ArrivalTime);
depart = GetTime(item.DepartureTime);
journey = GetDurationLabel((int)item.TravelTimeToNext.TotalMinutes);
distance = item.DistanceToNext.ToString("0.0");
location = "[" + locationChangeCounter + "] " + item.JobPart.Loc.Index.ToString("000");
if (item.JobPartIndex == 0)
jobvalue = item.Job.UnassignedWeight.ToString();
}
sw.WriteLine(name + "\t" +
location + "\t" +
window + "\t" +
softwindowend + "\t" +
load + "\t" +
service + "\t" +
arrival + "\t" +
idle + "\t" +
late + "\t" +
depart + "\t" +
journey + "\t" +
breakTime + "\t" +
currentload + "\t" +
distance + "\t" +
jobvalue);
}
}
}
}
internal static void WriteSolutionBasicFormat(Solution solution, string fileName)
{
try
{
StreamWriter sw = new StreamWriter(fileName);
foreach (Resource resource in solution.Problem.Resources)
{
RouteItem[] routeSchedule = solution.GetDetailedRoute(resource);
sw.WriteLine(resource.ID);
foreach (RouteItem item in routeSchedule)
{
sw.Write(item.ItemType + "\t");
sw.Write(item.ID + "\t");
sw.Write(item.ArrivalTime + "\t");
sw.Write(item.IdleTime + "\t");
sw.Write(item.ServiceTime + "\t");
sw.Write(item.DepartureTime + "\t");
sw.Write(item.TravelTimeToNext + "\t");
sw.Write(item.Break + "\t");
sw.Write(item.DistanceToNext + "\t");
sw.WriteLine();
}
sw.WriteLine();
sw.WriteLine();
}
sw.WriteLine();
Console.WriteLine("Written : " + fileName);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// Converts a load constraint to a string description
/// </summary>
internal static string GetLoadLabel(Dictionary<string, double> load)
{
StringBuilder sb = new StringBuilder();
int c = 0;
foreach (var kvp in load)
{
if (++c == load.Count)
sb.Append(kvp.Key + ":" + kvp.Value);
else
sb.Append(kvp.Key + ":" + kvp.Value + ",");
}
return sb.ToString();
}
internal static string GetDurationLabel(int totalMinutes)
{
int hrs = totalMinutes / 60;
int mins = totalMinutes % 60;
if (hrs > 0)
{
if (mins > 0)
return hrs + "h" + mins.ToString("00");
else
return hrs + "h";
}
else
return mins.ToString();
}
internal static string GetTime(DateTime dateTime)
{
return dateTime.ToString("HHmm");
}
internal static string GetVersion()
{
Version version = System.Reflection.Assembly.GetAssembly(typeof(VRSolver.Solver)).GetName().Version;
return version.Major + "." + version.Minor;
}
}
}