C# 微软Sover基金会在某些情况下无法解决我的模型

C# 微软Sover基金会在某些情况下无法解决我的模型,c#,constraint-programming,ms-solver-foundation,C#,Constraint Programming,Ms Solver Foundation,我正在做一个生产计划项目,所以我想在一些机器(a,B)中找到订单生产开始时间 为了简化起见,我假设我有两台机器(机器A和机器B) 我有以下限制: 每台机器只能在一天中的某些时间工作(A\u timesimulation,B\u timesimulation) 为了简化起见,我想 机器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可以在以下范围内工作

我正在做一个生产计划项目,所以我想在一些机器(a,B)中找到订单生产开始时间

为了简化起见,我假设我有两台机器(机器A和机器B) 我有以下限制:

  • 每台机器只能在一天中的某些时间工作(
    A\u timesimulation
    B\u timesimulation
    ) 为了简化起见,我想

    • 机器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分钟)
  • 机器B应该在机器A完成工作后启动
  • B可以开始工作,最多在A完成工作后10分钟[更新]
  • 目标是使订单生产时间最小化
我使用以下代码将日期时间转换为分钟:

var minutes=newtimespan(dateTime.Ticks).TotalMinutes

因此,使用上述代码将my
DateTime
范围转换为
Double
范围

我正在使用来解决这个问题,所以我使用了以下代码:

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);
var context=SolverContext.GetContext();
var model=context.CreateModel();
var a_操作时间=60;
var b_运行时间=60;
var公差=10;
//决断
Decision A_StartTime=新决策(Domain.integernonegative,“A_StartTime”);
模型。添加决策(A_StartTime);
Decision B_StartTime=新决策(Domain.integernonegative,“B_StartTime”);
模型添加决策(B_StartTime);
//约束条件
model.AddConstraint(“A_TimelSimulations”,
(1059220800我发现了问题

  • 我应该在模型中定义更多约束
  • 我的时间限制很大,我在指导下将
    DateTime
    s转换为
    double
    转换方法
  • 因此,最终的解决方案是:

    //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);
    
    //将DateTime转换为规范化双精度的扩展方法
    公共静态双ToMinutes(此日期时间值)
    {
    return(value new DateTime(2014,12,3)).TotalMinutes;
    }
    var a1_start=new DateTime(2014,12,4).ToMinutes();
    var a1_finish=新的日期时间(2014,12,4,2,0,0);
    var a2_start=new DateTime(2014,12,4,4,0,0).ToMinutes();
    var a2_finish=新的日期时间(2014,12,4,6,0,0);
    var b1_start=new DateTime(2014,12,4,1,0,0).ToMinutes();
    var b1_finish=新的日期时间(2014,12,4,1,55,0);
    var B2_start=new DateTime(2014,12,4,5,0,0);
    var B2_finish=新的日期时间(2014,12,4,6,0,0);
    var context=SolverContext.GetContext();
    var model=context.CreateModel();
    var a_操作时间=60;
    var b_运行时间=60;
    var公差=10;
    //决断
    Decision A_StartTime=新决策(Domain.integernonegative,“A_StartTime”);
    模型。添加决策(A_StartTime);
    Decision B_StartTime=新决策(Domain.integernonegative,“B_StartTime”);
    模型添加决策(B_StartTime);
    //约束条件
    model.AddConstraint(“A_TimelSimulations”,
    
    ((a1_)首先,问题可能是时间的大值。如果将大的时间限制更改为更小的值,会发生什么情况,例如,时间1059220800表示为时间0(或其他一些小值),而另一个则相应更改。@hakank:我使用
    var minutes=(dateTime-new dateTime)将时间限制更改为更小的值(2014,01,01)).TotalMinutes;
    改为
    var minutes=new TimeSpan(dateTime.Ticks)。TotalMinutes
    但问题没有解决。修复后的时间限制是什么?它们可能仍然太大…@hakank:我能看到的大约是500000(使用完全不同的系统)这就是问题的解决方案。我怀疑解算器花费这么长时间的原因是a和B的域太大了。你能将所有限制降低到最小值(1059220800)并看看它是否更快吗?太好了。约束编程的一个重要原则是定义域尽可能小(但不能更小)。