Ошибка 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/

Другие вопросы по тегам