Как запустить Microsoft Solver Foundation в параллельных задачах - PullRequest
0 голосов
/ 16 марта 2020

Я бы хотел запускать Microsoft Solver Foundation в параллельных задачах. Я попытался с решением ниже, и он выдает исключение «ArgumentException: exePath должен быть указан, когда не работает внутри автономного exe.». Он работает нормально одна за другой, но мне нужно запустить несколько задач параллельно, чтобы ускорить процесс.

Это мой метод решения

public List<Decision> SolveDecisions(RaceWager raceWager)
        {
            _logger.Info("Start to solve decisions");
            EnsureInputIsNotNull(raceWager);

            var solver = SolverContext.GetContext(); // Exception throw here

            solver.ClearModel();

            var model = solver.CreateModel();
            _logger.Info("Generate decisions");
            var decisions = GenerateDecisions(Domain.RealNonnegative, "x", raceWager.RunWagers, raceWager.BankRoll);
            model.AddDecisions(decisions.ToArray());

            var decisionNames = decisions.Select(decision => decision.Name).ToList();

            var sumDecisionsExpression = string.Join(" + ", decisionNames);
            model.AddConstraint("budget", $"({sumDecisionsExpression}) <= {raceWager.BankRoll}");

            var expectedProfitFormula = GenerateExpectedProfitSolverExpression(decisionNames, raceWager);
            model.AddGoal("ExpectedProfit", GoalKind.Maximize, expectedProfitFormula);
            _logger.Info("Solve decisions");
            solver.Solve(
                new Directive
                {
                    TimeLimit = int.TryParse(ConfigurationManager.AppSettings["SolverTimeLimit"], out var timeLimit)
                        ? timeLimit
                        : DefaultTimeLimit,
                    WaitLimit = int.TryParse(ConfigurationManager.AppSettings["SolverWaitLimit"], out var waitLimit)
                        ? waitLimit
                        : DefaultWaitTimeLimit
                });
            _logger.Info("End solve decisions");
            return model.Decisions.ToList();
        }

Когда я пытаюсь обернуть его в несколько задач для параллельной работы.

var optimizeTasks = new List<Task>();
                for (var i = 0; i < 2; i++)
                {
                    optimizeTasks.Add(Task.Run(() =>
                    {
                        _optimizeService.SolveDecisions(new RaceWager
                        {
                            BetTypeId = BetTypes.WIN,
                            BankRoll = 50000,
                            UserDefinedOverround = 1,
                            TotalPool = 23529.0,
                            RunWagers = new List<RunWager>
                            {
                                new RunWager {ModelPercentage = 0.119796574f, MarketOdds = 11.5815125f, HorsePool = 1693},
                                new RunWager {ModelPercentage = 0.08600821f, MarketOdds = 12.5931282f, HorsePool = 1557},
                                new RunWager {ModelPercentage = 0.210860476f, MarketOdds = 3.56759453f, HorsePool = 5496},
                                new RunWager {ModelPercentage = 0.07284866f, MarketOdds = 8.792601f, HorsePool = 2230},
                                new RunWager {ModelPercentage = 0.08509313f, MarketOdds = 8.622472f, HorsePool = 2274},
                                new RunWager {ModelPercentage = 0.0636601746f, MarketOdds = 9.83325f, HorsePool = 1994},
                                new RunWager {ModelPercentage = 0.06863576f, MarketOdds = 31.4727135f, HorsePool = 623},
                                new RunWager {ModelPercentage = 0.0714284852f, MarketOdds = 11.4529791f, HorsePool = 1712},
                                new RunWager {ModelPercentage = 0.0970818f, MarketOdds = 7.305328f, HorsePool = 2684},
                                new RunWager {ModelPercentage = 0.0276215617f, MarketOdds = 25.2024422f, HorsePool = 778},
                                new RunWager {ModelPercentage = 0.0531845465f, MarketOdds = 14.7646837f, HorsePool = 1328},
                                new RunWager {ModelPercentage = 0.0437806025f, MarketOdds = 16.903017f, HorsePool = 1160},
                                new RunWager {ModelPercentage = 0.06345806025f, MarketOdds = 15.234017f, HorsePool = 1260, PGIScratching = true}
                            }
                        });
                    }));
                }
await Task.WhenAll(optimizeTasks);

В этой строке кода возникнет исключение

var solver = SolverContext.GetContext();
Exception: 'Microsoft Solver Foundation plugin solver configuration exception.'

Message: 'exePath must be specified when not running inside a stand alone exe'

StackTrace:
   at System.Configuration.ConfigurationManager.OpenExeConfigurationImpl(ConfigurationFileMap fileMap, Boolean isMachine, ConfigurationUserLevel userLevel, String exePath, Boolean preLoad)
   at Microsoft.SolverFoundation.Services.PluginSolverCollection.<GetPluginSolverSection>d__7.MoveNext()
   at Microsoft.SolverFoundation.Services.PluginSolverCollection.Initialize()
   at Microsoft.SolverFoundation.Services.PluginSolverCollection.CreatePluginSolverCollection()

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация. Заранее спасибо

1 Ответ

0 голосов
/ 16 марта 2020

Хорошо, я могу решить мою проблему. Я до сих пор не знаю, что является причиной root, но я могу это исправить, создав поле в конструкторе, а не в задаче.

Удалите это.

var solver = SolverContext.GetContext();

Использование это вместо

private readonly ILogger _logger;
private readonly SolverContext _solver;

public OptimizeService(ILogger logger)
{
     _logger = logger;
     _solver = SolverContext.GetContext();
}    
...