Beispiel #1
0
 public static void AddFixedConstraints(List <NodesConstraint> fixedConstraints, IDictionary <NodeId, NodeDecision> nodeDecisions, IModel solverModel)
 {
     foreach (var constraint in fixedConstraints)
     {
         var toNodeDecision   = nodeDecisions[constraint.Node1];
         var fromNodeDecision = nodeDecisions[constraint.Node2];
         solverModel.AddConstraints(
             SolverUtils.MakeValidSolverIdentifierFromString(string.Format("fixed-diff-{0}-{1}", constraint.Node1, constraint.Node2)),
             new OperatorExpr()
         {
             Op   = OperatorExpr.OpType.Eq,
             Left = new OperatorExpr()
             {
                 Op   = OperatorExpr.OpType.Sub,
                 Left = new TermExpr()
                 {
                     Variable = toNodeDecision.Decision
                 },
                 Right = new TermExpr()
                 {
                     Variable = fromNodeDecision.Decision
                 },
             },
             Right = new ConstantExpr()
             {
                 Value = constraint.Value.Ticks
             }
         }
             );
         toNodeDecision.UsedInConstraint();
         fromNodeDecision.UsedInConstraint();
     }
 }
 private static void AddMessagingConstraints(List <InternodeMessage> messages, IDictionary <NodeId, NodeDecision> nodeDecisions, IModel solverModel)
 {
     foreach (var message in messages)
     {
         var toNodeDecision   = nodeDecisions[message.To.NodeId];
         var fromNodeDecision = nodeDecisions[message.From.NodeId];
         solverModel.AddConstraints(
             SolverUtils.MakeValidSolverIdentifierFromString(message.Id),
             new OperatorExpr()
         {
             Op   = OperatorExpr.OpType.Get,
             Left = new OperatorExpr()
             {
                 Op   = OperatorExpr.OpType.Sub,
                 Left = new TermExpr()
                 {
                     Variable = toNodeDecision.Decision,
                 },
                 Right = new TermExpr()
                 {
                     Variable = fromNodeDecision.Decision,
                 },
             },
             Right = new ConstantExpr()
             {
                 Value = (message.FromTimestamp - message.ToTimestamp).Ticks + 1
             }
         }
             );
         toNodeDecision.UsedInConstraint();
         fromNodeDecision.UsedInConstraint();
     }
 }
        private static void AddMessagingConstraints(List <InternodeMessage> messages, IModel solverModel, Dictionary <Message, MessageDecision> msgDecisions, Dictionary <NodeId, NodeDecision> nodeDecisions)
        {
            Func <Message, Expr> getTerm = m =>
            {
                Expr ret = new TermExpr()
                {
                    Variable = nodeDecisions[m.Node.NodeId].Decision
                };
                for (; m != null; m = m.Prev)
                {
                    MessageDecision d;
                    if (msgDecisions.TryGetValue(m, out d))
                    {
                        ret = new OperatorExpr()
                        {
                            Op    = OperatorExpr.OpType.Sub,
                            Left  = ret,
                            Right = new TermExpr()
                            {
                                Variable = d.Decision
                            }
                        }
                    }
                    ;
                }
                return(ret);
            };

            foreach (var message in messages)
            {
                var toNodeDecision   = getTerm(message.IncomingMessage);
                var fromNodeDecision = getTerm(message.OutgoingMessage);

                solverModel.AddConstraints(
                    SolverUtils.MakeValidSolverIdentifierFromString("MessageConstraint_" + message.Id),
                    new OperatorExpr()
                {
                    Op   = OperatorExpr.OpType.Get,
                    Left = new OperatorExpr()
                    {
                        Op    = OperatorExpr.OpType.Sub,
                        Left  = toNodeDecision,
                        Right = fromNodeDecision,
                    },
                    Right = new ConstantExpr()
                    {
                        Value = (message.FromTimestamp - message.ToTimestamp).Ticks + 1
                    }
                }
                    );
                nodeDecisions[message.IncomingMessage.Node.NodeId].UsedInConstraint();
                nodeDecisions[message.OutgoingMessage.Node.NodeId].UsedInConstraint();
            }
        }
        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
                                   )
                               )
                           ));
            }
        }
Beispiel #6
0
 public DecisionBase(IModel model, string decisionName)
 {
     this.Decision = model.CreateDecision(SolverUtils.MakeValidSolverIdentifierFromString(decisionName));
 }
Beispiel #7
0
        public static void AddUnboundNodesConstraints(
            InternodeMessagesMap map,
            IDictionary <NodeId, NodeDecision> nodeDecisions,
            IModel solverModel)
        {
            for (int i = 0; i < map.NodeIndexes.Count; ++i)
            {
                for (int j = 0; j < map.NodeIndexes.Count; ++j)
                {
                    if (i > j && (map.Map[i, j] != 0) != (map.Map[j, i] != 0))                     // if all internode messages between nodes i and j flow in one direction
                    {
                        var n1 = map.Nodes[i];
                        var n2 = map.Nodes[j];

                        // find the least "steep" internode message
                        var message =
                            n1.Messages
                            .Where(m => m.InternodeMessage != null && m.InternodeMessage.GetOppositeMessage(m).Node == n2)
                            .Where(m => !(m.InternodeMessage.OutgoingMessage.Event is ResponselessNetworkMessageEvent))
                            .Select(m => m.InternodeMessage)
                            .Aggregate(new { D = TimeSpan.MaxValue, M = (InternodeMessage)null }, (rslt, m) =>
                        {
                            var d = m.FromTimestamp - m.ToTimestamp;
                            return(d < rslt.D ? new { D = d, M = m } : rslt);
                        }, rslt => rslt.M);
                        if (message == null)
                        {
                            continue;
                        }

                        // add the constraint that emulates instantaneous response to the found message.
                        // this allows finding solution for the two nodes that would be impossible otherwise.
                        var toNodeDecision   = nodeDecisions[message.To.NodeId];
                        var fromNodeDecision = nodeDecisions[message.From.NodeId];
                        solverModel.AddConstraints(
                            SolverUtils.MakeValidSolverIdentifierFromString(message.Id) + "_reverse",
                            new OperatorExpr()
                        {
                            Op   = OperatorExpr.OpType.Get,
                            Left = new OperatorExpr()
                            {
                                Op   = OperatorExpr.OpType.Sub,
                                Left = new TermExpr()
                                {
                                    Variable = fromNodeDecision.Decision
                                },
                                Right = new TermExpr()
                                {
                                    Variable = toNodeDecision.Decision
                                }
                            },
                            Right = new ConstantExpr()
                            {
                                Value = (message.ToTimestamp - message.FromTimestamp).Ticks - 1
                            }
                        }
                            );
                    }
                }
            }
        }
Beispiel #8
0
        public static void AddIsolatedRoleInstancesConstraints(
            InternodeMessagesMap map,
            IDictionary <NodeId, NodeDecision> nodeDecisions,
            HashSet <string> allowedRoles,
            IModel solverModel)
        {
            var handledBadDomains = new HashSet <ISet <int> >();

            foreach (var roleGroup in map.NodeIndexes
                     .Where(x => allowedRoles.Contains(x.Key.NodeId.Role))
                     .GroupBy(x => x.Key.NodeId.Role))
            {
                // domain -> [{node, node index}]  where all nodes are instances of to one role
                var domainGroups = roleGroup
                                   .GroupBy(inst => map.NodeDomains[inst.Value])
                                   .ToDictionary(domainGroup => domainGroup.Key, domainGroup => domainGroup.ToList());

                // skip the role if all instances of it belong to one domain
                if (domainGroups.Count < 2)
                {
                    continue;
                }

                // good is the domain that consists of more than one node
                var goodDomain = domainGroups.FirstOrDefault(d => d.Key.Count > 1);
                if (goodDomain.Key == null)
                {
                    continue;
                }

                foreach (var badDomain in domainGroups
                         .Where(d => d.Key.Count == 1)
                         .Where(d => !handledBadDomains.Contains(d.Key)))
                {
                    var goodDomainDecision = nodeDecisions[goodDomain.Value[0].Key.NodeId];
                    var badDomainDecision  = nodeDecisions[badDomain.Value[0].Key.NodeId];
                    solverModel.AddConstraints(
                        "isolated_domain_link_" + SolverUtils.MakeValidSolverIdentifierFromString(string.Join("_", badDomain.Key)),
                        new OperatorExpr()
                    {
                        Op   = OperatorExpr.OpType.Eq,
                        Left = new OperatorExpr()
                        {
                            Op   = OperatorExpr.OpType.Sub,
                            Left = new TermExpr()
                            {
                                Variable = goodDomainDecision.Decision
                            },
                            Right = new TermExpr()
                            {
                                Variable = badDomainDecision.Decision
                            }
                        },
                        Right = new ConstantExpr()
                        {
                            Value = 0
                        }
                    }
                        );
                    handledBadDomains.Add(badDomain.Key);
                }
            }
            ;
        }