Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » An algo for a schedule problem

Credits go to StevenVI and William Labbett for helping out!
This thread is locked; no one can reply to it. rss feed Print
An algo for a schedule problem
Johan Halmén
Member #1,550
September 2001

I have no clue on what keywords I could use for searching. So perhaps someone here recognises this problem.

I have 18 courses that I have to put in a schedule of 3 blocks, 6 chourses per block. Every time I put two courses in one block, there might be a cost (one or more students want to attend both courses). I know how to calculate the whole cost.

I only need a clever algo that goes through some ways of placing the courses in the blocks. I guess I don't have resources to go through all possibilities. It could look like this:

A B C D E F
G H I J K L
M N O P Q R

I'd calculate the cost of this and save the schedule and the cost. Then I'd advance to the next combination, switching two courses from different rows, calculate the cost and save the combination, if the cost was smaller. Then advance, hopefully taking heuristic steps.

So first of all I'd need a simple algo for switching courses, secondly a more clever algo to not have to go through all possibilities.

<edit />

Brute force would mean going through all possibilities. Seems all possibilities would be too much. Picking 6 of 18 for the first row would be 13 million possibilities. Picking 6 of the 12 that are left, for the 2nd row, would be 665,280 possibilities. Alltogether 1012 possibilities, which is too much to parse through.

But I still need the parsing algo, because I can divide the problem into first sorting half of all the courses, like A, B, C, G, H, I, M, N and O, which gives me 60,000 possibilities to run through. After that I can fixate them, then I run another 60,000 possibilities for the remaining courses.

<edit />
I spent some time to find an algo for dealing with these three sets, until I saw the light. It's all about picking out k elements from n elements. I parse through all combinations of three out of nine. For each, I parse through all combinations of three out of the six remaining elements. And the search words were "Generating Combinations of a Set of Elements".

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

William Labbett
Member #4,486
March 2004
avatar

Picking 6 of 18 for the first row would be 13 million possibilities.

Why would that be a problem with a fast processor and a decent algo?

StevenVI
Member #562
July 2000
avatar

Why would that be a problem with a fast processor and a decent algo?

He was asking for a decent algo. :)

I parse through all combinations of three out of nine.

I'm not sure I'm following where your numbers come from -- perhaps I don't understand the problem being solved. My understanding was that the scoring was based just on the set that each course is in, but not their order. So for that you'd have 18C6 combinations for the first set, and 12C6 combinations remaining for the second. (The final set would then already be determined by this: 6C6=1.)

Assuming I ran my numbers correctly, you still have to build and score 17,153,136 permutations. While this can probably be run relatively quickly in the grand scheme of things, having a smarter algorithm might prove to be helpful.

And to derail this thread now, suppose that you had much large values that you wanted to optimize the problem for. For example, there are 6 sets and 36 courses. You're then looking at an impossible to brute-force problem to be solved. An approach that I've wanted to take for this in the past -- though never implemented -- was using a genetic algorithm to optimize the score. That might be something worth looking into.

__________________________________________________
Skoobalon Software
[ Lander! v2.5 ] [ Zonic the Hog v1.1 ] [ Raid 2 v1.0 ]

Johan Halmén
Member #1,550
September 2001

I have three sets, 6 + 6 + 6 courses. Any course can be in any of the sets. There are 18C6 ways to pick 6 courses for the first set. 18C6 is 18! / 12! which is 13E6. For each of them I have to check 12C6 ways to arrange the remaining two sets. 12C6 is 12! / 6! which is 665,280. Multiply them and you get 8E12, not 17E6. 8E12 is way too much for brute force.

I will face much larger problems of the same kind in a few weeks. For that I might try some way of scoring partial sets. I could skip over millions and millions of combinations, if only a part of a new combination shows a cost that exceeds a previous best score. But I have no idea how to implement it. Some tree structure.

Here's an output from a simple three-out-of-nine situation:

#SelectExpand
1... 22 3 7 32 3 8 42 3 9 52 4 5 62 4 6 72 4 7 82 4 8 92 4 9 102 5 6 112 5 7 122 5 8 13...

If my least cost until line 2 in the listing is say 50, and if I checked that 2 and 4 on line 5 together already would cause a cost over 50, I wouldn't have to check lines 6 to 9. I could jump straight to line 10. In my real problem, I could jump over millions of combinations.

My actual problem is about creating schedules for next year. Students have chosen courses and the courses have to be placed in three sets. Each student has only one course in each set. There are 10 to 20 students in each course. But some courses are so popular that we run them in two or three groups. So in my letter schedule in the OP, D and Q might actually be the same course, but two different groups, with the possibility for a student to switch from D to Q to enable participatin in another course in the first row. The cost that I'm talking about is how many collisions there are between two courses, how many students have selected both courses.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

StevenVI
Member #562
July 2000
avatar

18C6 is 18! / 12! which is 13E6.

I believe you are mistaken. The algorithm for the binomial coefficient "n choose k" is:

<math>\left({^n_k}\right) = \frac{n!}{k!(n-k)!}</math>

With that in mind, it sounds like you're taking the same approach here that I did. So for the first set you have this many combinations:

<math>\begin{split}
\left(^{18}_6\right) &= \frac{18!}{6!(18-6!)}\\
 &= \frac{18!}{6!12!}\\
 &= \frac{18\times17\times16\times15\times14\times13}{6\times5\times4\times3\times2}\\
 &= 3\times17\times4\times7\times13\\
 &= 18564
\end{split}</math>

Then you have 12C6 combinations for the remaining two sets:

<math>\begin{split}
\left(^{12}_6\right) &= \frac{12!}{6!6!}\\
 &=\frac{12\times11\times10\times9\times8\times7}{6\times5\times4\times3\times2}\\
 &=2\times11\times2\times3\times7\\
 &=924
\end{split}</math>

Multiplying these together, you get the total number of permutations to examine:

<math>18564\times924=17,153,136</math>

Regarding the actual problem that you have to solve, I haven't put any thought into it yet. :)

__________________________________________________
Skoobalon Software
[ Lander! v2.5 ] [ Zonic the Hog v1.1 ] [ Raid 2 v1.0 ]

William Labbett
Member #4,486
March 2004
avatar

Stephen's right.

Johan's logic was

18 possibilities for 1st choice
17 for second
16 for third.
...
..
13 for last.

Hence there are 18*17*16*15*14*13 ways of choosing.

....

BUT

: many of these choices are the same

e.g
1st choice = 4
2nd choice = 11
3rd choice = 10
4th choice = 3
5th choice = 8
6th choice = 2

is the same in the end as:

e.g
1st choice = 11
2nd choice = 2
3rd choice = 4
4th choice = 3
5th choice = 10
6th choice = 8

There's a nice way of deducing how many are the same.

I can't think of it now and for that reason and the fact that I didn't spot Johan's mistake, I feel ashamed because I am a mathematician :-[

/* EDIT */

Please admire my bravery :

Johan and my (I confess) logic was

18!/12!

If the answer is divided by 6! the correct answer is arrived at. This tells me that
6! are the same but I can't tell you why.

:-[

/* EDIT 2 */

No, the amount the same isn't 6!.

It's (18!/12!) - (18!/(6!)(12!)).

I think. :-[ :-/ :)

<will goes to get another beer>

StevenVI
Member #562
July 2000
avatar

Go pick up a book on combinatorics. :)
I don't have time to explain it all right now. :P

__________________________________________________
Skoobalon Software
[ Lander! v2.5 ] [ Zonic the Hog v1.1 ] [ Raid 2 v1.0 ]

Johan Halmén
Member #1,550
September 2001

Thanks, guys. I believe you, Steven. And I can run a simple check, if I'm in doubt. But most of all, I'm going to do the brute force on those 17 million. I have one algo already. The rest is just coding. Clever use of pointers should make it fast enough.

And William, 6! are the same, because 6 elements can be rearranged in 6! ways, right?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

William Labbett
Member #4,486
March 2004
avatar

And William, 6! are the same, because 6 elements can be rearranged in 6! ways, right?

I've thought about this deeply. I found 'the same' to be a confusing way of thinking
about the problem.
So, not really disagreeing or agreeing, but I can give a fairly clear overview of the situation :-

For each unique Choice of Six Courses , which is a set of 6 numbers, there are 6! = 720 different versions of copies of the Set, each with the numbers arranged in a different order.

The 6! comes from what you said :

Quote:

6 elements can be rearranged in 6! ways

NOW

Total ways of choosing 6 - not discounting a 'way', if the numbers are the same as another way but ordered differently :

18*17*16*15*14*13 = 13366080

One Unique way is included in the count 6! = 720 times

13366080 = 18564 * 720

i.e There are 18564 lots of 720 sets of six numbers which are the same sets because only the order of numbers is different.

So there are 18564 Unique sets of 6 different numbers (or courses).

Does that help?

/* EDIT */

I guess, you might not like the different context of the word set here (I mean mathematical set, not set at a school).

Johan Halmén
Member #1,550
September 2001

What is a mathematical set? And a school set? I've used the word to mean 6 particular elements in no particular order. A B C is the same set as A C B and C B A etc. If I'd want to make the distinction between A B C and A C B, I'd call them arrays or vectors. But I'm not a matematician, nor am I an expert on terminology in computer science. I only use the stuff.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

William Labbett
Member #4,486
March 2004
avatar

In maths, a set is defined with curly brackets and a set of n elements is the same set regardless of what order the elements are in.

So for example the mathemtical set of 3 elements { 3, 6, 7 } is the same as { 7, 3, 6}.

When I was at school there were two sets for all the sciences. Set 1 and Set 2.
The brighter students where in set 1.

Essentially though a school set and a set of numbers are both mathematical sets
: a collection of objects.

Johan Halmén
Member #1,550
September 2001

Ok, so I'm going to write this thing for a situation where I go through 17 million combinations. And another situation where I go through 400 million combination. But I'm going to make some shortcuts, some simple optimizing. If I'd have 9 courses, three in each block, I'd check for:

123
456
789

123
457
689
...

And so on. At some point I'd check for

456
123
789

...but that's unnecessary. In a case of nine courses in three blocks, I'd pick out three of nine for the first set. Then I'd pick out three of six for the second set. My first discovery is that the algo/code I'm using is picking three of nine in this order for the first set:

3 6 8    60
3 6 9    61
3 7 8    62
3 7 9    63
3 8 9    64
4 5 6    65
4 5 7    66
4 5 8    67
4 5 9    68
4 6 7    69

At line 64 I've picked the last combination including element 1, 2 or 3. I don't have to try line 65 for the first set, because every line from line 65 and on, I have already have as set 2 or set 3. So anything from line 65 and on, are only permutations. Without tracking down these permutations, I'd check each combination 6 times (3!).

My second optimization, which I mentioned earlier, is about the two step thing. First step: pick 3 of 9 for the first set. Second step: pick 3 of 6 for the second set and put the remaining three to the third set. Now you can calculate the whole cost for the whole combination. But after first step I can calculate the cost for only the first set. There will be lots of combinations, where only the first set costs more than the cheapest found combination.

Quote:

<will goes to get another beer>

As long as it's an Allegro Brew!

{"name":"597586","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/0\/906ea3d8bdac63084a064e842ce4845f.jpg","w":816,"h":612,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/0\/906ea3d8bdac63084a064e842ce4845f"}597586

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

William Labbett
Member #4,486
March 2004
avatar

Are those stickers still available?

Johan Halmén
Member #1,550
September 2001

Here...

<edited />

Mission complete. I finished my program and got my schedules done. Seems I got very good combinations. Before I did this, I had a spreadsheet that calculated the costs after I tried to arrange the courses by hand. My program now creates combinations with costs lower than anything I managed to do manually.

Arranging 18 courses in three blocks took some 10 seconds. Arranging 21 courses took 155 seconds. I guess I'd need heavy code optimization, if I need to arrange more complex systems than these. As well as more heuristic technique in the algos.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

William Labbett
Member #4,486
March 2004
avatar

Great.

Hope things work out well.

weapon_S
Member #7,859
October 2006
avatar

I think this is an interesting problem, and many, many educational institutions seem to be needing something like this. (Their schedules suck.) What I don't quite grasp are the constraints and costs. Were you scheduling for the courses students already attended? Feel free to ignore my dumb questions >_>;

Johan Halmén
Member #1,550
September 2001

It started with students choosing courses for next year. They chose three courses plus some in reserve. According to their choices, we decide which courses to run and which to skip. We can't afford courses with only 2 or 3 students.

After that I ended up in 18 groups to be placed in 3 blocks, 6 groups in each block. Most groups are individual courses, but some are one course divided in two groups (finally there were about 12 different courses).

At this point, my algo kicks in. I pick 6 groups for each block and calculate the cost. One cost unit is one student that have chosen two courses that are placed in the same block. The more such students, the more it costs to put those two groups in same block. If one of the courses runs in another group in another block, too, it halves the cost. If both courses run in another groups in other blocks, the cost is again halved. So when I have 6 groups in one block, I check each combination of two groups (6C2) and add the total cost. And add it to the costs of the other two blocks.

After finding the optimal combination of blocks and groups, we let the students pick one group from each block (everyone has to pick three courses). This seems to cause a mess. Actually we do have software that could optimize this step, placing each student in the right group according to their choices, but our headmaster decided to let the students pick their groups. Before we've got everything sorted, I'm afraid we will have to ignore the choices the students did in this second turn and try to optimize the groups using the software we have. But the software we have couldn't do this first step that I did with my algo.

<edit />

Ok, it went well. The students picked their courses from the three blocks. It looked like this:

{"name":"609284","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/3\/8350036aaacf3557ccb548c46f1e4e5b.png","w":393,"h":207,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/3\/8350036aaacf3557ccb548c46f1e4e5b"}609284

The black boxes mark the selected courses for one student. (Red and blue are only code colours for different types of courses. Irrelevant.)

It worked very well for one school. But my next project will be to use same ideas for another school, where one student has to select about 25 courses for one year. For each schedule they pick 5-6 courses. Compared to the three block schedule above, these students have 7 blocks. Each block can hold 6-8 courses. No way I could use same algo!

I'd need a different approach, some heuristic algo. I'd start by placing courses in blocks, one by one. For each course, I'd place the course in a block with least costs. If there are several blocks with no cost at all, I'd place the course in the one with most courses. Because we aim to fill blocks with as many students as possible.

After all courses are placed, there would still be much to check and try out. Now each course costs something! Even the ones that costed nothing in the first place, because now the cost is caused by courses added later. I'd like to try the following:

  1. Pick away one course that causes the biggest reduction of the total cost

  2. Place the course in a new block, where it causes the least cost

  3. Repeat from #1 until the course that you try to place would go back into the same block

  4. Try further rescheduling with other courses causing large costs

In #1 I could create an ordered list of say 5 courses causing the biggest costs and I'd operate with the first course. In #4 I'd pick the second course from the list.
This could go on forever, don't know. But at any time, the next step should give a solution with a little bit improved schedule.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Go to: