Оптимизация тимбилдинга с использованием Microsoft Solver Foundation 3.0

Я работаю над приложением для создания команды студенческого проекта. Я знаком с оптимизацией, но раньше не использовал Microsoft Solver Foundation. У меня есть ограничения, но у меня проблемы с определением целей с помощью синтаксиса Solver. Вот краткое изложение приложения:

Профессора взвешивают определенные навыки для каждого проекта. Студенты перечисляют, какие навыки являются их сильными и слабыми сторонами, и ранжируют проекты, которыми они хотели бы заниматься. В проекте должно быть от 3 до 5 студентов. Каждому студенту должен быть назначен проект.

  • Основная цель - максимизировать количество удовлетворенных требований к навыкам.
  • Вторая цель - максимизировать предпочтения студентов.

Я играл с SimplexSolver Class на основе этого Учебник по смешанной целочисленной задаче, и я могу без проблем максимизировать предпочтения учащихся.

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>");

Я вижу, как я могу добавить строки для каждого требования к навыкам проекта, и установить коэффициенты для сильных / слабых сторон каждого учащегося для этого навыка и установить нижнюю границу для веса навыков этого проекта. Однако это дает мне 2 проблемы.

  1. Я не верю, что будут выполнены все требования к навыкам проекта. Вот почему я хотел бы поставить цель максимизировать количество требований к навыкам, которые подразумеваются, вместо того, чтобы устанавливать минимальный вес навыка в качестве ограничения. Даже если команде не хватает 1 очка по определенному навыку, это все равно лучше, чем у всех остальных, если этот навык указан как слабость.
  2. Если в команде 4 студента с весом навыков программирование, равным 3, и у 3 из них программирование указано как сильная сторона (+1), а у другого студента есть программирование указано как слабое место (-1), тогда моя модель будет неправильно показывать, что требование программирования не выполняется, потому что (1 + 1 + 1-1) ‹3.

У кого-нибудь есть идеи? SimplexSolver - лучший способ решить эту проблему? Похоже, у Solution Foundation много разных решателей / инструментов. У меня есть экспресс-версия Solution Foundation, но, возможно, при необходимости я могу получить версию Academic Enterprise.

Спасибо, - Грег

* В окончательной заявке потребуется решить модели с примерно 100 студентами, 20-30 проектами и ~ 30 потенциальными навыками (~ 5 на проект).


person Greg    schedule 08.10.2011    source источник


Ответы (1)


Да, вы можете решить эту проблему с помощью Simplex. Это стандартная «Задача назначения» с несколькими вариациями с точки зрения предпочтений и веса навыков.

Вы можете решить проблему 1 в своем вопросе, введя одну или несколько "фиктивных переменных" для устранения недостатка

Вместо того, чтобы писать ограничение навыков как:

Sum for all students (X_sp) >= NumMin_pk для каждого проекта p, для каждого навыка k.

ты пишешь

sum for all students (X_sp) > 0 + NumMin_pk * Dummy1_pk для каждого p, для каждого навыка k

А в целевой функции вы наказываете Dummy_pk (давая ему отрицательную стоимость для задачи максимизации). Таким образом, Simplex назначит ненулевой Dummy_pk только в том случае, если у него нет другой альтернативы.

Кроме того, предположим, что для одного навыка (программирование) проект имеет минимальный вес навыка 3, но если 5 студентов имеют программирование, это еще лучше. Вы можете добиться этого, введя вторую фиктивную переменную (Dummy2_pk).

Sum for all students (X_sp) > 0 + 3* Dummy_pk + 2 * Dummy_pk2 для каждого p, для каждого навыка k

В целевой функции присвойте высокую отрицательную стоимость Dummy_pk и меньшую, но отрицательную стоимость Dummy2_pk. Модель сначала попытается получить Dummy1_pk 0, и, если возможно, if приведет к нулевому значению Dummy2_pk. В результате к этому проекту будут назначены 5 студентов с навыками программирования.

Чтобы решить проблему 2 (отрицательные веса навыков): Разделите вектор навыков на два вектора, разделив единицы и -1.

Таким образом, [1,0,0,1, -1,0,1] становится [1,0,0,1,0,0,1] и [0,0,0,0, -1,0,0] . В зависимости от того, что вы хотите сделать со слабым навыком, вы можете написать ДВА ограничения для каждого проекта p, навыка k и избежать проблемы, когда слабость отменяет навык другого ученика.

person Ram Narasimhan    schedule 05.02.2012