在某些情况下,Microsoft Solver Foundation无法解决我的模型

时间:2014-12-03 05:41:35

标签: c# constraint-programming ms-solver-foundation

我正在进行生产计划项目,所以我想在某些机器(A,B)中找到订单生产开始时间。

为简化起见,我想我有2台机器(机器A和机器B) 我有以下约束:

  • 每台机器只能在一天中的某些时段工作(A_TimeLimitationB_TimeLimitation) 出于简化的目的,我认为

    • 机器A可以在以下范围内工作:

      (2014/12/4 00:00:00 - 2014/12/4 02:00:00)(2014/12/4 04:00:00 - 2014/12 / 4 06:00:00)

    • 机器B可以在以下范围内工作:

      (2014/12/4 02:00:00 - 2014/12/4 04:00:00)(2014/12/4 05:00:00 - 2014/12 / 4 07:00:00)

  • 每件产品必须经过机器A,然后经过机器B.

  • 每台产品每台产品需要一些时间(样品中需要60分钟)。
  • 机器A应该在机器A完成它的工作后启动。
  • B可以在A完成工作后最多10分钟开始工作。的 [更新]
  • 目标是最小化订单生产时间。

我使用以下代码将DateTime转换为分钟:

var minutes = new TimeSpan(dateTime.Ticks).TotalMinutes;

因此,使用上面的代码,我的DateTime范围转换为Double范围。

我正在使用Microsoft Solver Foundation来解决问题,因此我使用了以下代码:

var context = SolverContext.GetContext();
var model   = context.CreateModel();
var a_OperationTime = 60;
var b_OperationTime = 60;
var tolerance = 10;

//Decision
Decision A_StartTime = new Decision(Domain.IntegerNonnegative, "A_StartTime");
model.AddDecision(A_StartTime);
Decision B_StartTime = new Decision(Domain.IntegerNonnegative, "B_StartTime");
model.AddDecision(B_StartTime);

 //Constraints
model.AddConstraint("A_TimeLimitations" ,
                 (1059220800 <= A_StartTime <= 1059220860) | 
                 (1059221160 <= A_StartTime <= 1059221220));

model.AddConstraint("B_TimeLimitations" , 
                 (1059220920 <= B_StartTime <= 1059220980) | 
                 (1059221100 <= B_StartTime <= 1059221160));
model.AddConstraint("B_ContiguousLimitations" , 
                 B_StartTime - (A_StartTime + 60) <= tolerence);

//Goal
var A_StartTime = model.Decisions.First(x => x.Name == "A_StartTime");
var B_StartTime = model.Decisions.First(x => x.Name == "B_StartTime");
model.AddGoals("OrderDuration", GoalKind.Minimize, B_StartTime - A_StartTime);

//Solve
var directive = new ConstraintProgrammingDirective();
//directive.TimeLimit = 10000;
var solution = context.Solve(directive);

但是当我运行代码时,似乎进入无限循环,当我为TimeLimit指定directive时,在10000毫秒之后,solution.QualityUnknown这意味着MSF无法找到任何解决方案,如果我删除了机器DateTime中的第二个A范围,则代码可以找到解决方案。

有谁知道问题出在哪里?

1 个答案:

答案 0 :(得分:1)

我发现了问题

  1. 我应该在我的模型中定义更多约束
  2. 我的时间限制非常大,我使用hankank指南将DateTime更改为double转换方法
  3. 所以最终解决方案就在这里:

    //extention method for converting DateTime to normalized double
    public static double ToMinutes(this DateTime value)
    {
       return (value-new DateTime(2014, 12, 3)).TotalMinutes;
    }
    
    var a1_start = new DateTime(2014, 12, 4).ToMinutes();
    var a1_finish = new DateTime(2014, 12, 4, 2, 0, 0).ToMinutes();
    var a2_start = new DateTime(2014, 12, 4, 4, 0, 0).ToMinutes();
    var a2_finish = new DateTime(2014, 12, 4, 6, 0, 0).ToMinutes();
    var b1_start = new DateTime(2014, 12, 4,1,0,0).ToMinutes();
    var b1_finish = new DateTime(2014, 12, 4, 1, 55, 0).ToMinutes();
    var B2_start = new DateTime(2014, 12, 4, 5, 0, 0).ToMinutes();
    var B2_finish = new DateTime(2014, 12, 4, 6, 0, 0).ToMinutes();
    
    var context = SolverContext.GetContext();
    var model = context.CreateModel();
    var a_OperationTime = 60;
    var b_OperationTime = 60;
    var tolerance = 10;
    
    //Decision
    Decision A_StartTime = new Decision(Domain.IntegerNonnegative,"A_StartTime");
    model.AddDecision(A_StartTime);
    Decision B_StartTime = new Decision(Domain.IntegerNonnegative,"B_StartTime");
    model.AddDecision(B_StartTime);
    
    //Constraints
    model.AddConstraint("A_TimeLimitations",
                            ((a1_start <= A_StartTime <= a1_finish) & 
                             (a1_start + 60 <= A_StartTime + 60 <= a1_finish)) |
                            ((a2_start <= A_StartTime <= a2_finish) & 
                             (a2_start + 60 <= A_StartTime + 60 <= a2_finish)));
    
    model.AddConstraint("B_TimeLimitations",
                           ((b1_start <= B_StartTime <= b1_finish) & 
                            ((b1_start + 60 <= B_StartTime + 60 <= b1_finish))) |
                           ((B2_start <= B_StartTime <= B2_finish) & 
                            (B2_start + 60 <= B_StartTime + 60 <= B2_finish)));
    model.AddConstraint("B_ContiguousLimitations",
                              B_StartTime - (A_StartTime + 60) <= tolerance);
    
    model.AddConstraint("B_GreaterThan_A",
                         B_StartTime >= A_StartTime + 60);
    //Goal
    A_StartTime = model.Decisions.First(x => x.Name == "A_StartTime");
    B_StartTime = model.Decisions.First(x => x.Name == "B_StartTime");
    model.AddGoals("OrderDuration",GoalKind.Minimize, B_StartTime - A_StartTime);
    
    //Solve
    var directive = new ConstraintProgrammingDirective();
    var solution = context.Solve(directive);