SFS挂gurobi,解决TSP问题,免费的数目有限制。
下面的是核心code.
public static void Run()
{
SolverContext context = SolverContext.GetContext();
context.ClearModel();
Model model = context.CreateModel();
// Parameters
Set city = new Set(Domain.IntegerNonnegative, "city");
Parameter dist = new Parameter(Domain.Real, "dist", city, city);
var arcs = from p1 in data
from p2 in data
select new Arc { City1 = p1.Name, City2 = p2.Name, Distance = p1.Distance(p2) };
dist.SetBinding(arcs, "Distance", "City1", "City2");
model.AddParameters(dist);
// Decisions
Decision assign = new Decision(Domain.IntegerRange(0, 1), "assign", city, city);
Decision rank = new Decision(Domain.RealNonnegative, "rank", city);
model.AddDecisions(assign, rank);
// Goal: minimize the length of the tour.
Goal goal = model.AddGoal("TourLength", GoalKind.Minimize,
Model.Sum(Model.ForEach(city, i => Model.ForEachWhere(city, j => dist[i, j] * assign[i, j], j => i != j))));
// Enter and leave each city only once.
int N = data.Length;
model.AddConstraint("assign1",
Model.ForEach(city, i => Model.Sum(Model.ForEachWhere(city, j => assign[i, j],
j => i != j)) == 1));
model.AddConstraint("assign2",
Model.ForEach(city, j => Model.Sum(Model.ForEachWhere(city, i => assign[i, j], i => i != j)) == 1));
model.AddConstraint("A1", Model.ForEach(city, i => Model.Sum(Model.ForEachWhere(city, j => assign[i, j], j => i != j)) == 1));
model.AddConstraint("A2", Model.ForEach(city, j => Model.Sum(Model.ForEachWhere(city, i => assign[i, j], i => i != j)) == 1));
// Forbid subtours (Miller, Tucker, Zemlin - 1960...)
model.AddConstraint("nosubtours",
Model.ForEach(city,
i => Model.ForEachWhere(city,
j => rank[i] + 1 <= rank[j] + N * (1 - assign[i, j]),
j => Model.And(i != j, i >= 1, j >= 1)
)
)
);
Solution solution = context.Solve();
// Retrieve solution information.
Console.WriteLine("Cost = {0}", goal.ToDouble());
Console.WriteLine("Tour:");
var tour = from p in assign.GetValues() where (double)p[0] > 0.9 select p;
foreach (var i in tour)
{
Console.Write("{0} -> {1} ",i[1],i[2]);
}
Console.WriteLine();
}