2016-10-14 1 views
0

Je souhaite planifier des tâches avec le Microsoft Solver Framework. Pour l'instant j'ai l'objectif simple de simplement ordonner les tâches dans une file d'attente afin que j'aie un temps de projet minimal. (plus tard, je veux avoir plus d'une file d'attente). J'ai essayé d'aborder cela avec la configuration suivante:Tâches de planification C# avec MS Solver Framework

  • Décision:
    • projectFinish
    • début
    • finition
  • Paramètre:
    • durée
  • Constraint:
    • début + durée = finition
    • pas plus d'une tâche à la fois
    • projectFinish après toutes les tâches terminées
  • Goal :
    • minimiser projectFinish

Voici mon code jusqu'à présent

static void Main(string[] args) { 
     var data = new List<Task>() { 
      new Task(){ Duration = 1, Name = "task0"}, 
      new Task(){ Duration = 1, Name = "task1"}, 
      new Task(){ Duration = 1, Name = "task2"}, 
     }; 

     SolveScheduling(data); 
    } 

    public class Task { 
     private static int id_counter = 0; 
     public Task() { ID = id_counter++; } 
     public int ID { get; private set; } 
     public string Name { get; set; } 
     public double Duration { get; set; } 
    } 

    private static void SolveScheduling(IEnumerable<Task> data) { 

     SolverContext context = SolverContext.GetContext(); 
     Model model = context.CreateModel(); 

     var set = new Set(Domain.Any,"TaskSet"); 


     var projectFinish = new Decision(Domain.IntegerNonnegative, "projectFinish"); 
     model.AddDecision(projectFinish); 

     var taskSet = new Set(Domain.Any, "tasks"); 

     var durations = new Parameter(Domain.RealNonnegative, "durations", taskSet); 
     durations.SetBinding(data, "Duration", "Name"); 
     var ids = new Parameter(Domain.Integer, "ids", taskSet); 
     ids.SetBinding(data, "ID", "Name"); 
     var starts = new Decision(Domain.RealNonnegative, "starts", taskSet); 
     var finishs = new Decision(Domain.RealNonnegative, "finishs", taskSet); 

     model.AddDecisions(starts, finishs); 
     model.AddParameters(durations, ids); 

     // Constraints 

     // start + duration = finish 
     model.AddConstraint("constraint0", Model.ForEach(taskSet, (t) => starts[t] + durations[t] == finishs[t])); 
     // Tasks after each other 
     model.AddConstraint("constraint1", Model.ForEach(taskSet, t => 
      Model.ForEachWhere(taskSet, t2 => Model.Or(finishs[t] < starts[t2] , starts[t] > finishs[t2]), (t2) => ids[t] != ids[t2]))); 
     // projectFinish after all tasks finished 
     model.AddConstraint("constraint2", Model.ForEach(taskSet, t => projectFinish >= finishs[t])); 

     // Goals 
     model.AddGoal("goal0", GoalKind.Minimize, projectFinish); 


     Solution solution = context.Solve();//new SimplexDirective()); 

     Report report = solution.GetReport(); 
     Console.WriteLine(@"===== report ====="); 
     Console.Write("{0}", report); 
     Console.ReadLine(); 
    } 

Maintenant, le problème est qu'il faut à jamais pour résoudre ce (même si ce ne sont que trois tâches et 1 file d'attente). Qu'est-ce que je manque ici et comment puis-je améliorer la vitesse de résolution.

Mise à jour

J'ai trouvé une solution pour mon problème. Si vous avez des améliorations, n'hésitez pas à commenter. Voici mon code:

 SolverContext context = SolverContext.GetContext(); 
     Model model = context.CreateModel(); 

     // === Sets === 
     var taskSet = new Set(0,data.Count(), 1); 

     // === Parameters === 
     var duration = new Parameter(Domain.RealNonnegative, "durations", taskSet); 
     var id = new Parameter(Domain.RealNonnegative, "id", taskSet); 
     duration.SetBinding(data, "Duration", "ID"); 
     id.SetBinding(data, "ID", "ID"); 

     model.AddParameters(duration, id); 

     // === Decisions === 
     var projectFinish = new Decision(Domain.RealNonnegative, "projectFinish"); 
     var start = new Decision(Domain.RealNonnegative, "starts", taskSet); 
     var finish = new Decision(Domain.RealNonnegative, "finishs", taskSet); 

     model.AddDecisions(projectFinish, start, finish); 

     // === Constraints === 
     model.AddConstraint("constraint0", start[0] == 0); 
     // start + duration = finish 
     model.AddConstraint("constraint1", Model.ForEach(taskSet, (t) => start[t] + duration[t] == finish[t]));   
     // projectFinish after all tasks finished 
     model.AddConstraint("constraint2", Model.ForEach(taskSet, t => projectFinish >= finish[t])); 
     // not more than one task at a time 
     model.AddConstraint("constraint3", Model.ForEach(taskSet, t => 
      Model.ForEachWhere(taskSet, t2 => Model.Or(finish[t] < start[t2], start[t] > finish[t2]), (t2) => id[t] != id[t2]))); 


     // === Goals === 
     model.AddGoal("goal0", GoalKind.Minimize, projectFinish); // minimieren der projekt zeit 

     // === Solve === 
     context.CheckModel(); 
     Solution solution = context.Solve(); 

Répondre

0

J'ai trouvé une solution qui fonctionne pour moi. J'ai changé le taskset

var taskSet = new Set(0, data.Count(), 1); 

et a ajouté une nouvelle contrainte

model.AddConstraint("constraint", starts[0] == 0); 

Je mis à jour la question