public static SolutionResult Solve(
            ISolver solver,
            IDictionary <NodeId, Node> nodes,
            InternodeMessagesMap map, List <InternodeMessage> messages,
            List <NodesConstraint> fixedConstraints,
            HashSet <string> allowInstancesMergingForRoles)
        {
            using (var solverModel = solver.CreateModel())
            {
                var msgDecisions = messages
                                   .SelectMany(interNodeMsg => new [] { interNodeMsg.IncomingMessage, interNodeMsg.OutgoingMessage })
                                   .ToDictionary(m => m, m => new MessageDecision(solverModel, m));
                var nodeDecisions = nodes
                                    .ToDictionary(n => n.Key, n => new NodeDecision(solverModel, n.Value));

                AddMessagingConstraints(messages, solverModel, msgDecisions, nodeDecisions);
                SolverUtils.AddFixedConstraints(fixedConstraints, nodeDecisions, solverModel);
                SolverUtils.AddUnboundNodesConstraints(map, nodeDecisions, solverModel);
                SolverUtils.AddIsolatedRoleInstancesConstraints(map, nodeDecisions, allowInstancesMergingForRoles, solverModel);
                AddGoals(solverModel, msgDecisions);

                var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20));

                var solution = solverModel.Solve(cancellation.Token);

                /*Func<Message, bool> mok = m => messages.Any(im => im.IncomingMessage == m || im.OutgoingMessage == m);
                 * var nodeToMsg = nodes.Values.Select(n => new
                 * {
                 *      Node = n.NodeId.ToString(),
                 *      Msgs =
                 *              string.Join("\n", n.Messages.Where(mok).Select(m => m.Key.ToString()).ToArray())
                 * }).ToArray();*/

                if (solution.IsInfeasible)
                {
                    return(new SolutionResult(cancellation.IsCancellationRequested ? SolutionStatus.Timeout : SolutionStatus.Infeasible, null));
                }

                return(new SolutionResult(
                           SolutionStatus.Solved,
                           nodeDecisions.ToDictionary(
                               d => d.Key,
                               d => new NodeSolution(
                                   d.Value.TimeDelta,
                                   GetNonmonotonicTimeDeltasForNode(msgDecisions, d.Value),
                                   d.Value.NrOnConstraints
                                   )
                               )
                           ));
            }
        }
        public static ISolutionResult Solve(
            ISolver solver,
            IDictionary <NodeId, Node> nodes, InternodeMessagesMap map, List <InternodeMessage> messages,
            List <NodesConstraint> fixedConstraints, HashSet <string> allowInstancesMergingForRoles)
        {
            using (var solverModel = solver.CreateModel())
            {
                var decisions = nodes.ToDictionary(n => n.Key, n => new NodeDecision(solverModel, n.Value));

                AddMessagingConstraints(messages, decisions, solverModel);
                SolverUtils.AddFixedConstraints(fixedConstraints, decisions, solverModel);
                SolverUtils.AddUnboundNodesConstraints(map, decisions, solverModel);
                SolverUtils.AddIsolatedRoleInstancesConstraints(map, decisions, allowInstancesMergingForRoles, solverModel);
                AddGoals(decisions, solverModel);

                var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10));

                var solution = solverModel.Solve(cancellation.Token);

                if (solution.IsInfeasible)
                {
                    return(new SolutionResult(cancellation.IsCancellationRequested ? SolutionStatus.Timeout : SolutionStatus.Infeasible));
                }

                return(new SolutionResult(
                           SolutionStatus.Solved,
                           decisions.ToDictionary(
                               d => d.Key,
                               d => new NodeSolution(
                                   d.Value.TimeDelta,
                                   new List <TimeDeltaEntry>(),
                                   d.Value.NrOnConstraints
                                   )
                               )
                           ));
            }
        }