I'm working on a student project team building application. I'm familiar with optimization but haven't used Microsoft Solver Foundation before. I have my constraints worked out but am having trouble identifying my goals with the Solver syntax. Here's a basic summary of the application:
Professors weight certain skills for each project. Students list which skills are their strengths and weaknesses and they rank projects they would like to do. A project must have between 3-5 students assigned to it. Each student must be assigned a project.
- Primary goal is to maximize number of satisfied skill requirements
- Secondary goal is to maximize student preferences
I have been playing around with the SimplexSolver Class based on this Mixed Integer Problem tutorial and am able to maximize student preferences without any problem.
using Microsoft.SolverFoundation.Solvers;
//This example has 2 projects and 6 students
SimplexSolver solver = new SimplexSolver();
//Student A wants to be in project 1, Student B is indifferent to project 1, Student C does not want to be in project 1, etc...
double[] studentprojectpref = new double[] { 1, 0, -1, 0, -1, 0, 0, 1, 0, 1, 0, 1 };
int[] choosestudentprojectPS = new int[12];
//GOAL - maximize student preferences
int sumpreferences;
solver.AddRow("sumpreferences", out sumpreferences);
solver.AddGoal(sumpreferences, 1, false);
//add a varaible (column) for each possible student/project pair
for (int i = 0; i < choosestudentprojectPS.GetUpperBound(0)+1; i++)
{
solver.AddVariable(projectstudent[i], out choosestudentprojectPS[i]);
solver.SetBounds(choosestudentprojectPS[i], 0, 1);
solver.SetIntegrality(choosestudentprojectPS[i], true);
solver.SetCoefficient(sumpreferences, choosestudentprojectPS[i], studentprojectpref[i]);
}
solver.Solve(new SimplexSolverParams());
Response.Write(solver.MipResult + "<br>");
Response.Write("<br>Project 1<br>");
for (int i = 0; i < 6; i++)
{
if (solver.GetValue(choosestudentprojectPS[i]) == 1) Response.Write(projectstudent[i] + "<br>");
}
Response.Write("<br>Project 2<br>");
for (int i = 6; i < 12; i++)
{
if (solver.GetValue(choosestudentprojectPS[i]) == 1) Response.Write(projectstudent[i] + "<br>");
}
Response.Write("<br>The total sumpreferences is: " + solver.GetValue(sumpreferences) + "<br>");
I see how I can add rows for each project skill requirement, and set coefficients for each student's strength/weakness for that skill and set a lower bound for that project's skill weight. This gives me 2 problems though.
- I don't believe that all project skill requirements are going to be met. That's why I would like to set a goal to maximize the number of skill requirements that are meant instead of setting the skill weight minimum as a constraint. Even if a team is 1 point short on a particular skill it is still better than all of them having that skill listed as a weakness.
- If there are 4 students on a team that has a programming skill weight of 3, and 3 of them have programming listed as a strength (+1) and the other student has programming listed as a weakness (-1) then my model would incorrectly show that the programming requirement is not met because (1+1+1-1)<3.
Anybody have any ideas? Is SimplexSolver the best way to go about this problem? It looks like Solution Foundation has a lot of different solvers/tools. I have the Express version of Solution Foundation but could probably get a hold of the Academic Enterprise version if needed.
Thanks, - Greg
*Final application will need to solve models with approximately 100 students, 20-30 projects, and ~30 potential skills (~5 per project).