7

I'm trying to find an algorithm that can arrange as many of these non-overlapping events into a schedule as possible (where any of these events can be added or removed from the schedule as needed). None of these events can overlap, but I want to fit as many of them into a daily schedule as possible:

12:00 PM - 12:45 PM: Lunch

1:00 AM - 3:00 AM: Math class 1

3:30 PM - 5:00 PM: Math class 2

7:00 PM - 10:00 PM: History class 1

9:00 PM - 11:00 PM: History class 2

Any time of day: Grocery shopping, 40 minutes

Any time of day: Study math for 30 minutes

Any time of day between 11:00 AM and 4:00 PM: Basketball practice for 2 hours

I've been thinking about this problem for a while, and I still have no idea about how I should solve it. What type of calendar-scheduling algorithm would be most effective in this case?

Anderson Green
  • 30,230
  • 67
  • 195
  • 328
  • I still don't know whether this would be a better fit for http://stackoverflow.com/ or http://math.stackexchange.com/. – Anderson Green May 20 '13 at 03:42
  • http://stackoverflow.com/questions/2746309/best-fit-scheduling-algorithm?rq=1 –  May 20 '13 at 03:44
  • @JarrodRoberson The description for that question is vague, and it isn't clear whether the OP actually wants to fit as many items into a schedule as possible. I'm not sure if it's really a duplicate. – Anderson Green May 20 '13 at 03:46
  • You might try to adapt heuristic solutions to the Knapsack problem – Jonathan Myers May 20 '13 at 05:36
  • Are the activities you flagged with time here must be scheduled into the calendar? – albusshin May 20 '13 at 09:09
  • @AlbusShin It may or may not be possible to fit all of the events into the calendar. I want to schedule as many of them into the calendar as possible. – Anderson Green May 20 '13 at 16:27
  • "where any of these events can be added or removed from the schedule as needed" Including the events with fixed times (e.g. remove Math class 1 from your schedule)? Or are only the "Any time of day" events removable? – mbeckish May 20 '13 at 20:51
  • @mbeckish All events are removable. – Anderson Green May 20 '13 at 20:52
  • "None of these events can overlap" - Does that mean "You are guaranteed that no two events given as input will overlap" or "A valid solution will not contain any overlapping events"? It's unclear, since your input does not contain any overlapping events. – mbeckish May 20 '13 at 20:55
  • @mbeckish I mean that a valid solution will contain no overlapping elements. – Anderson Green May 20 '13 at 22:02
  • @mbeckish: History Class 1 and History Class 2 overlap – slebetman May 21 '13 at 01:49
  • related: [maximize non-overlaping count -- O(n log n) algorithm in Python](http://stackoverflow.com/a/16314541/4279) – jfs Jun 13 '13 at 01:13

4 Answers4

3

You are bin packing periods into a single day length. You want to find the possible solutions for your problem and grade them according to the number of periods you manage to pack into it.

  1. Split your day in 15 mins intervals, so that from 1 am to 10 pm you have 21 * 4 frames.
  2. Generate every permutation possible with your constraints (no overlap of frames).
  3. For each valid permutation, count the number of periods you managed to fit in.
  4. Print the [x] permutations that scored the highest
Eric
  • 19,525
  • 19
  • 84
  • 147
  • Now I just need to figure out how to generate every possible permutation of events. I'm not really sure where to start, though - do you have any ideas? – Anderson Green May 20 '13 at 03:57
  • It looks like there are many different ways to [generate all permutations of a set of items](https://www.google.com/#hl=en&sclient=psy-ab&q=generate+all+permutations+of+a+list&oq=generate+all+permutations+of+a+&gs_l=hp.3.1.0l4.1655.7558.0.8774.26.20.2.4.4.0.174.1593.16j4.20.0...0.0...1c.1.14.psy-ab.vpkq349cqys&pbx=1&bav=on.2,or.r_cp.r_qf.&bvm=bv.46751780,d.dmg&fp=8be17aaf92ef5992&biw=1366&bih=631). – Anderson Green May 20 '13 at 04:25
  • +1 from me...five answers hers (so far) and this is the only one to recognize the combinatorial optimization pattern--bin packing in particular, or "knapsack" problem as i refer to them. – doug May 20 '13 at 09:07
  • @doug I only see three answers here. Where are the other two? – Anderson Green May 20 '13 at 18:09
  • @AndersonGreen: two have been deleted; there's some rep threshold to see deleted questions. – doug May 20 '13 at 19:20
2

I've written a function called generateCombination that takes an array of integer ranges as input, and generates all possible non-overlapping combinations of the events in the array. From this array, you can extract the largest arrays of ranges, which are the ranges that contain the greatest possible number of events.

http://jsfiddle.net/nvYZ8/1/

var theArray = generateCombination([[0, 2], [2, 3], [4, 5], [0, 9], [2, 50]]);
alert(JSON.stringify(theArray));

function generateCombination(theArray) {
    var theString = "";
    var tempArray = new Array();
    for (var i = 0; i < theArray.length; i++) {
        theString += "1";
    }
    var maximumNumber = convertFromBaseToBase(theString, 2, 10);

    for (var k = 0; k <= maximumNumber; k++) {
        theString = convertFromBaseToBase(k + "", 10, 2);
        while(theString.length != theArray.length){
            theString = "0" + theString;
        }
        var theResult = getArray(theArray, theString);
        if(theResult != false){
            tempArray[tempArray.length] = JSON.stringify(theResult);
        }
    }
    return tempArray;
}

function getArray(theArray, theString){
        var tempArray = new Array();
    for(var i = 0; i < theArray.length; i++){
        if(theString[i] == 1){
            tempArray[tempArray.length] = theArray[i];
        }
    }
        for (var i = 0; i < theArray.length; i++) {
            for (var j = i; j < theArray.length; j++) {
                if ((j != i) && (theString[i] == 1) && (theString[j] == 1)) {
                    //check whether theArray[i] overlaps with theArray[j]
                    var overlaps = rangesOverlap(theArray[i][0], theArray[i][1], theArray[j][0], theArray[j][1]);
                    //if overlaps is true, break out of the current loop
                    //otherwise, add theArray[j] to tempArray
                    if(overlaps == true){
                        return false;
                    }
                }
            }
        }
        return tempArray;
}

function convertFromBaseToBase(str, fromBase, toBase) {
    var num = parseInt(str, fromBase);
    return num.toString(toBase);
}

function rangesOverlap(x1, x2, y1, y2) {
    if (x1 <= y2 && y1 <= x2) {
        return true;
    } else {
        return false;
    }
}
Anderson Green
  • 30,230
  • 67
  • 195
  • 328
  • I wrote this answer before I was aware of constraint programming languages. There is a programming language called [MiniZinc](http://www.minizinc.org/) that makes it much easier to solve problems like this one. – Anderson Green Jan 07 '16 at 23:22
0

I think Dynamic Programming is the solution ..

For a, b as events: f(a) > f(b) ~ duration(a) < duration(b)

For x, y as schedules: g(x) > g(y) ~ Number-Of-Events(x) > Number-Of-Events(y)

Dynamic Programming with f(event) over g(schedule); to find the optimal schedule

Khaled.K
  • 5,828
  • 1
  • 33
  • 51
0

OTOH I can think of two suitable solutions, one with planning algorithms, PopPlan or GraphPlan; the other, you could use simulated annealing.

Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54
  • According to [this Google search](https://www.google.com/#output=search&sclient=psy-ab&q=popPlan&oq=popPlan&gs_l=hp.3..0j0i10j0j0i10.479.1502.0.1797.7.7.0.0.0.0.191.719.4j3.7.0.epsugrpqhmsignedin%2Chtma%3D120%2Chtmb%3D120..0.0.0..1.1.17.psy-ab.3P6Tq2ZSMTw&pbx=1&bav=on.2,or.r_cp.r_qf.&bvm=bv.48293060,d.dmg&fp=f0df6dbdb7c58c71&biw=1366&bih=631), "PopPlan" usually refers to "Premium only plan". Are you referring to something else? – Anderson Green Jun 23 '13 at 22:04