Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  How to model this situation

    Posted 03/07/16 04:13 AM

    Originally posted by: adelalb


    Hello,

    I'm a new to the OPL . I''m trying to model a scheduling problem as a constraint satisfaction problem.  I'm having a situation that I'm not able to address in the model :

    Situation:  We need to schedule a set of sub-project s and their internal/sub tasks with precedence constraints between tasks. 

    The characteristics of the problem are:

    workers have to assign to tasks.

    duration of tasks are in days
    workers can do multiple  tasks in parallel. However, they can't work more than 8 hours in a day.

    the contributions of each worker into each tasks are defined by percentage. For example, a manage can be allocated to task A for only 20% and that will cover the need of task A for a manger

    Question: how can write a constraint to ensure a worker can't work more than 8 hours per day for all activities are being assigned to him.


    #CPOptimizer
    #DecisionOptimization


  • 2.  Re: How to model this situation

    Posted 03/09/16 06:39 AM

    Originally posted by: PhilippeLaborie


    Hello,
    It is not completely clear what it means that a worker is needed only x% of the duration of a task.
    Lets take your example of a task 'T' of duration 5 days that requires a given resource 'R' for 55% of its duration.

    First question:
    In this case, resource R will be used during 5*24*0.55 = 66h, right ? Or is it assumed that a "day" work duration is 8h and thus that the resource R will be used during 5*8*0.55 = 22h ?

    Second question:
    What does it mean that a resource R is used x hours during a task? Can the working time of resource R on task T be split as one wants (as far as it respect the max of 8h a day), for instance if it requires 22h, it could be a solution that R is used 8h on day 1 of that task, is not used at all on day 2, then used 2h on day 3, 4h on day 4 and then finally 8h on day 5 ? Or should resource R be used continuously and with the same work time on each day for that task, so here 4.4h every day ? The first case will be difficult to solve in CP Optimizer because you will have 1 decision per time step (day) for each (resource,task) pair and this typically a situation where the interest of CP Optimizer compared with a MIP model is not clear. If you want to model the second case, you could use a cumul function: you would have a max level of 8h on the cumul function of resource R and the work of resource R on task T would contribute to the cumul function with a pulse of height 4.4h. Well, as cumul functions only handle integers, you would have to rescale, for example take 1mn as unit: so levelR = pulse(T,264)+... and levelR <=480. The actual unit you take will have no impact on the complexity.

     


    #CPOptimizer
    #DecisionOptimization


  • 3.  Re: How to model this situation

    Posted 03/10/16 12:05 AM

    Originally posted by: adelalb


    Hello Philippe, 

     

    answer to the first question:

    A resource R will be used during 5*24*0.55 = 66h. Question is now, as far as I know I'm not supposed to declare the task duration since the contribution of resources should sum up to the total of task duration.  

    Answer to second Question:

    It is the second case. I will take your approach

    Thanks


    #CPOptimizer
    #DecisionOptimization


  • 4.  Re: How to model this situation

    Posted 03/10/16 03:14 AM

    Originally posted by: PhilippeLaborie


    > Question is now, as far as I know I'm not supposed to declare the task duration since the contribution of resources should sum up to the total of task duration

    I'm not sure to understand but in any case you can use a variable size for a task:

    dvar interval task size SizeMin...SizeMax;
    

    And use expressions like sizeOf(task) or lengthOf(task) to post constraints on the task size/length.


    #CPOptimizer
    #DecisionOptimization


  • 5.  Re: How to model this situation

    Posted 03/10/16 05:35 AM

    Originally posted by: adelalb


    Philippe,

    I'm still struggling with this. I have been following an  example from the tutorial and not sure what went wrong with this.

    Data File

    SheetConnection file ( "..\\Data\\DModel21616try9.xls" );


    // Step 1: Feasible Schedule
    Tasks          from SheetRead (file, "Tasks!A2:E12");
    TopLevelTask   from SheetRead (file, "Tasks!A2");
    ParentLinks    from SheetRead (file, "Hierarchy!A2:B11");
    Precedences    from SheetRead (file, "Precedences!A2:D8");


    //Step 2: Assignments of Pesonnel Resources to Activities
    Capabilities   from SheetRead (file, "Capabilities!A2:B2");
    Workers        from SheetRead (file, "Workers!A2:D7");
    Proficiencies  from SheetRead (file, "Proficiencies!A2:C7");
    Requirements   from SheetRead (file, "Requirements!A2:C17");
    RequiredCapabilities from SheetRead (file, "RequiredCapabilities!A2:E17");

     

     

     

     using CP;

     

    /********

     * Data *

     ********/

    //--------------------------------------Tasks

    tuple Task {
      key int id;
      string  name;
      int     ptMin;
      int Cont_Max;
      int Cont_Min;
    };
    { Task } Tasks = ...;
    int TopLevelTask = ...;
    //-----------------------------------hierarchy data

    tuple ParentLink {
      int taskId;
      int parentId;
    };

    { ParentLink } ParentLinks = ...;
    { int } Parents = { p.parentId | p in ParentLinks };

    //-----------------------------------Precedence

    tuple Precedence {
      int    beforeId;
      int    afterId;
      string type;
      int    delay;
    };
    { Precedence } Precedences = ...;

    //----------------------------------Capabilities
    tuple Capability {
      key int id;
      string  name;
    };
    { Capability } Capabilities = ...;

    //--------------------------------Workers

    tuple WorkerDat {
      key int id;
      string name;
      string  type;
      int cap;
    };
    { WorkerDat } Workers = ...;
    {string} WorkersTypes = {w.name | w in Workers};

    //-------------------------------Proficiency
    tuple Proficiency {
      int workerId;
      int capabilityId;
      int level;
    };

    { Proficiency } Proficiencies = ...;
     
    //------------------------------Requirements

    tuple Requirement {
      key int id;
      int taskId;
      int fundedeffort;
    };

    { Requirement } Requirements = ...;

    //--------------------------------Required Capabilities

    tuple RequiredCapability {
      key int id;
      int capabilityId;
      int levelMin;
      int levelMax;
      int Funded;
    };

    { RequiredCapability } RequiredCapabilities = ...;

    //-----------------------------------Filter Expression

     

    { int } CandidateWorkers[r in Requirements] =
       { p.workerId| p in Proficiencies, n in RequiredCapabilities:
         (n.id==r.id) &&
         (p.capabilityId==n.capabilityId) &&
         (n.levelMin <= p.level) &&
         (p.level <= n.levelMax)
         };

    //--------------------------------Allocations

    tuple Alloc {
      int reqId;
      int workerId;
      string worker_name;
      string worker_type;
      string name;
      int Fundeds;
      int ptMin;
    };

    { Alloc } Allocations = { <r.id, i,w.name, w.type, t.name, r.fundedeffort, t.ptMin> | r in Requirements, c in RequiredCapabilities, w in Workers, t in Tasks,i in CandidateWorkers[r] :
             r.taskId==t.id && w.id ==i};

    int Horizon =5760;

     

    /**********************

     * Decision variables *

     **********************/
    dvar interval task[t in Tasks]  size t.Cont_Min.. t.Cont_Max;
    dvar interval alts[a in Allocations]  optional ; //possible allocation of worker to a task requirements
    dvar interval worker[w in Workers] optional;

    //---- Cumul Functions

     cumulFunction cumuls[wc in Workers]=
     sum(a in Allocations: a.workerId== wc.id ) pulse (alts[a],264);

    /***************

     * Constraints *

     ***************/


    subject to {  

        //Project Portfoilos: each parent spans all its children
      forall (t in Tasks : t.id in Parents)
        span(task[t], all(i in ParentLinks: i.parentId == t.id) task[<i.taskId>]);
        
     

      // Precedence constraints
      // start of task "beforeId" ends at least "delay" hours before start of task "afterId"
      forall (p in Precedences : p.type == "StartsAfterEnd")
          endBeforeStart(task[<p.beforeId>], task[<p.afterId>], p.delay);
          
           // start of task "beforeId" ends at least "delay" hours before start of task "afterId"
      forall (p in Precedences : p.type == "StartsAfterStart")
          startBeforeStart(task[<p.beforeId>], task[<p.afterId>], p.delay);

          // start of task "beforeId" start at task "afterId"
      forall (p in Precedences : p.type == "StartsAtStart")
          startAtStart(task[<p.beforeId>], task[<p.afterId>], p.delay);
          
           // Alternatives of workers who can fulfil task requirement (each requirement must be filled by one worker)
      forall (r in Requirements)
        alternative(task[<r.taskId>], all(a in Allocations: a.reqId==r.id) alts[a]);
        
           // worker must span all alts variable for that workers
      forall(w in Workers)
        span(worker [w], all(a in Allocations: a.workerId==w.id) alts[a]) ;
        
     
     forall( t in Tasks, r in Requirements)
      sum(a in Allocations: t.id==r.taskId) sizeOf(alts[a], a.ptMin)== t.ptMin;
     


    forall (wc in Workers) {
     
    cumuls[wc] <= 480;

    }
    }

     


    #CPOptimizer
    #DecisionOptimization


  • 6.  Re: How to model this situation

    Posted 03/11/16 10:28 AM

    Originally posted by: ChrisBr


    Hello Adel,

    Could you expand about what kind of problem you are encountering?

    Is it that no solution is found as you are sure there is one  (or several)? In this case, you may take advantage to use the conflict refiner.
    Doesn't the solution found look like what you expected?
    Does your model search indefinitely?
    Doesn't your model compile?

    Regards,

    Chris.


    #CPOptimizer
    #DecisionOptimization


  • 7.  Re: How to model this situation

    Posted 03/11/16 05:14 PM

    Originally posted by: adelalb


    Hello Chris,

     

    The problem is that no solution is found. Another error message I got is  " Oplrun process is not responding, you must relaunch the Run Configuration"

    This happened when I added the cumulFunction f = pulse(a, hmin, hmax)


    #CPOptimizer
    #DecisionOptimization


  • 8.  Re: How to model this situation

    Posted 03/14/16 09:58 AM

    Originally posted by: ChrisBr


    Hello Adel,

    "Oplrun process is not responding, you must relaunch the Run Configuration"

    If this error occurs again, we have to find what is happening.
    In this case, could you send us your model/data which causes it?
    (please, try to generate a ".dat" file instead of an excel file)

    Regards,

    Chris.

     


    #CPOptimizer
    #DecisionOptimization


  • 9.  Re: How to model this situation

    Posted 03/14/16 08:13 PM

    Originally posted by: adelalb


    Hello Chris,

     

    Thanks for you help

     

    Please see the attached files.


    #CPOptimizer
    #DecisionOptimization


  • 10.  Re: How to model this situation

    Posted 03/15/16 11:15 AM

    Originally posted by: ChrisBr


    Hello Adel,

    There is an error in the expression:

    sum(a in Allocations: a.workerId== rc.id ) pulse (alts[a],a.ptMin,246);

    Here are the different values of ptMin for all a in Allocations:
     {1920 2400 1440 960 2880 4800}
    all these values are > 246

    So you try to create a pulse(a, hmin, hmax)  with hmin > hmax which is forbidden.

    But it is true that despite this error, oplrun should finish properly; we have to investigate this malfunction.

    Regards,

    Chris.

     


    #CPOptimizer
    #DecisionOptimization