#java #linear-programming #optaplanner
#java #линейное программирование #optaplanner
Вопрос:
Я изучаю, как использовать OptaPlanner, решая линейное программирование. Я знаю, что существует довольно много решателей LP, но я думаю, что это хорошая отправная точка для меня, чтобы понять моделирование.
Но когда я начал работать над этим, я столкнулся с проблемой, которая выглядит так, как будто переменная планирования сущности может быть только счетной.
Исключение выглядит следующим образом:
The selector is not countable, check the ValueRanges involved.
Verify that a ValueRangeProvider does not return ValueRange when it can return CountableValueRange or Collection.
Могу ли я знать:
- Каков «законный» способ использования «двойного значения»?
- Есть ли «лучшая практика» для LP в OptaPlanner?
Спасибо.
Мое решение:
@PlanningSolution
public class Solution {
@PlanningEntityProperty
private Entity entity;
@PlanningScore
private HardSoftScore score = HardSoftScore.ZERO;
public Solution(Entity entity) {
this.entity = entity;
}
@ValueRangeProvider(id = "x_1")
public ValueRange<Double> getX1Range() {
return ValueRangeFactory.createDoubleValueRange(0.0, 100.0);
}
@ValueRangeProvider(id = "x_2")
public ValueRange<Double> getX2Range() {
return ValueRangeFactory.createDoubleValueRange(0.0, 100.0);
}
...<getters setters>...
Моя сущность:
@PlanningEntity
public class Entity {
private long id;
@PlanningVariable(valueRangeProviderRefs = "x_1")
private Double x1;
@PlanningVariable(valueRangeProviderRefs = "x_2")
private Double x2;
...<getters setters>...
Мои ограничения:
...
private Constraint c1(ConstraintFactory constraintFactory) {
return constraintFactory.from(Entity.class)
.filter(e -> !(3.0 * e.getX1() 5.0 * e.getX2() < 5.0 ))
.penalize("C1", HardSoftScore.ONE_HARD);
}
private Constraint c2(ConstraintFactory constraintFactory) {
return constraintFactory.from(Entity.class)
.filter(e -> !(2.0 * e.getX1() - 6.0 * e.getX2() > 0.0 ))
.penalize("C2", HardSoftScore.ONE_HARD);
}
private Constraint min(ConstraintFactory constraintFactory) {
return constraintFactory.from(Entity.class)
.penalize("MIN", HardSoftScore.ONE_SOFT, e -> (int)(-e.getX1() 6.0 * e.getX2()));
}
...
Комментарии:
1. Решатели LP намного лучше решают LPS, чем OptaPlanner, который действительно является прославленной эвристикой (это неплохо: эти алгоритмы отлично подходят для задач, в которых точные методы исчерпаны). Хорошие решатели LP могут обрабатывать (редкие) проблемы с десятками миллионов переменных и ограничений.
Ответ №1:
Просматривая типы возвращаемых значений из набора методов createXXXValueRange() ValueRangeFactory, я замечаю, что все, кроме одного, возвращают счетный диапазон значений. Единственным исключением из этого правила является createDoubleValueRange() , который возвращает «простой» ValueRange (ValueRange).
Ваша ошибка указывает в том же направлении: ValueRange не считается допустимым счетным ValueRange. Для меня это имеет смысл: OptaPlanner хочет выбрать из набора дискретных значений для выполнения своих ходов. Так что я не думаю, что есть какой-либо «законный» способ использовать его для решающего хода OptaPlanner.
По причине, которую я не могу определить, я бы сам не выбрал OptaPlanner в качестве первого выбора для решения проблем LP, поскольку набор возможных решений может быть рассчитан. Но в любом случае, используя OptaPlanner (как в вашем случае), я бы тогда работал с кратными (10, 100, 1000, …) дискретными значениями (при вычислении результата деля их на 10, 100, 1000, …). И / НО в то же время я был бы крайне осторожен чтобы избежать коррупции в счетах, опасность которой никогда не будет очень далеко.
Ответ №2:
В настоящее время в OptaPlanner (версии 8.3 или ниже) нет селекторов перемещения для работы с DoubleValueRange
s. Смотрите Пример инвестиционного портфеля о том, как подключить свой собственный, чтобы иметь дело с диапазонами значений на основе границ, такими как DoubleValueRanges.
Это, как говорится. Если ваши диапазоны значений действительно непрерывны (то есть не дискретны), вам, вероятно, действительно лучше использовать LP. Обратите внимание, что в большинстве задач планирования диапазоны значений являются незаметными, потому что вы не можете отправить 0,75 транспортного средства / человека в местоположение A, а остальные 0,25 его / его / ее в местоположение B.
Смотрите также прекрасный ответ sudo.