Ошибка OR-Tools: невозможно преобразовать лямбда-выражение в тип '...', поскольку оно не является делегатом
При попытке запустить пример: VrpTimeWindows из Google OR-Tools, следующий блок кода генерирует ошибку:
int transitCallbackIndex = routing.RegisterTransitCallback(
(long fromIndex, long toIndex) => {
// Convert from routing variable Index to time matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return data.GetTimeMatrix()[fromNode, toNode]; }
);
Ошибка CS1660: невозможно преобразовать лямбда-выражение в тип "SWIGTYPE_p_std__functionT_long_long_flong_long_long_longF_t", так как это не тип делегата
Я использую последнюю доступную версию: 7.0-бета.1
1 ответ
Последняя доступная версия ( 7.0-бета.1) пока не поддерживает использование лямбда-выражения в качестве аргумента функции транзитного обратного вызова. Тем не менее, он привязан к хранилищу кода и будет доступен в следующей версии.
На данный момент, до выхода новой версии, есть два возможных решения:
Первое решение заключается в том, что вы можете загрузить последнюю версию OR-Tools и скомпилировать ее на своем компьютере, следуя инструкциям по установке из Source.
Второе решение заключается в замене аргумента экземпляром производного класса из
Google.OrTools.ConstraintSolver.LongLongToLong
следующим образом:LongLongToLong timeCallback = new TimeCallback(data, manager); int transitCallbackIndex = routing.RegisterTransitCallback(timeCallback);
куда TimeCallback
Класс может иметь следующую реализацию:
class TimeCallback : LongLongToLong
{
private long[,] timeMatrix;
private RoutingIndexManager indexManager;
public TimeCallback(DataModel data, RoutingIndexManager manager)
{
timeMatrix = data.GetTimeMatrix();
indexManager = manager;
}
override public long Run(long fromIndex, long toIndex)
{
// Convert from routing variable Index to time matrix NodeIndex.
int fromNode = indexManager.IndexToNode(fromIndex);
int toNode = indexManager.IndexToNode(toIndex);
return timeMatrix[fromNode, toNode];
}
}
Примечание: для LongLongToLong timeCallback = new TimeCallback(Data, manager);
сборщик мусора может уничтожить этот объект, так как регистр не поддерживает его работу в C# (примечание: это будет изменено в финальной версии 7.0 с использованием делегата и правильного управления владением). Чтобы избежать GC, вы должны позвонить GC.KeepAlive
на TimeCallback
объект после SolveWithParameters
метод.
Вот пример использования вышеупомянутого: https://github.com/Muhammad-Altabba/workforce-distribution-sample/