0

我正在尝试使用 Microsoft Solver Foundation 来解决我们的家庭圣诞节抽奖(类似于“秘密圣诞老人”或“kris kringle”)。

我有一些复杂的限制(例如,不能为您的兄弟姐妹购买),我已经使用这些限制来修剪每个参与者的域。

求解器工作,除了它没有一个人应该只收到一份礼物的约束(即,爱丽丝为鲍勃买东西意味着没有其他人为鲍勃买东西)。

我尝试添加一个“AllDifferent”约束,但得到一个参数异常-

“输入 Alice 和 Bob 具有不同的符号域。”

我也尝试将约束添加为 OML 表达式,但遇到了同样的错误。

  • 是否可以在具有不同域的决策之间应用任何约束?
  • 如果没有,并且我需要对所有决策使用相同的域,是否存在“包含”约束?(我尝试使用“ElementOf”,但无法让它工作。)

示例程序-

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SolverFoundation.Services;

namespace XmasDrawCSP
{
    public class Class1
    {
        public static void Main(string[] args)
        {

            SolverContext context = SolverContext.GetContext();
            Model model = context.CreateModel();

            Dictionary<string, string[]> PossiblyBuysFor = new Dictionary<string, string[]>();

            //Alice and Carol are sisters
            //Bob and David are brothers

            //Can't buy for siblings or yourself
            PossiblyBuysFor["Alice"] = new string[] { "Bob", "David", "Eve", };
            PossiblyBuysFor["Bob"] = new string[] { "Alice", "Carol", "Eve", };
            PossiblyBuysFor["Carol"] = new string[] { "Bob", "David", "Eve", };
            PossiblyBuysFor["David"] = new string[] { "Alice", "Carol", "Eve", };
            PossiblyBuysFor["Eve"] = new string[] { "Alice", "Bob", "Carol", "David", };

            foreach (var giver in PossiblyBuysFor.Keys)
            {
                Decision d = new Decision(Domain.Enum(PossiblyBuysFor[giver]), giver);
                model.AddDecision(d);
            }

            //Error thrown here- "Inputs Alice and Bob have different symbol domains."
            model.AddConstraint("one_present_each", Model.AllDifferent(model.Decisions.ToArray()));

            Solution solution = context.Solve(new ConstraintProgrammingDirective());

            int i = 0;
            while (solution.Quality != SolverQuality.Infeasible && i < 10)
            {
                Console.WriteLine(i);

                foreach (var d in solution.Decisions)
                {
                    Console.WriteLine(string.Format("{0} buys for {1}", d.Name, d.ToString() ));
                }

                Console.ReadLine();
                solution.GetNext();
                i++;
            }

            Console.ReadLine();
        }
    }   
}
4

1 回答 1

-1

我找到了解决方案。我对所有决策使用相同的域,然后将受限域添加为约束。

由于决策名称与解决方案值相同,我感到困惑。

这有点乱,但这是可行的解决方案-

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SolverFoundation.Services;

namespace XmasDrawCSP
{
    public class Class1
    {

        public static void Main(string[] args)
        {

            var Names = new string[] { 
                "Alice", "Bob", "Carol", "David", "Eve",
            };

            Domain Recipients = Domain.Enum(Names);

            SolverContext context = SolverContext.GetContext();
            Model model = context.CreateModel();

            Dictionary<string, string[]> PossiblyBuysFor = new Dictionary<string, string[]>();

            //Alice and Carol are sisters
            //Bob and David are brothers

            //Can't buy for siblings or yourself
            PossiblyBuysFor["Alice"] = new string[] { "Bob", "David", "Eve", };
            PossiblyBuysFor["Bob"] = new string[] { "Alice", "Carol", "Eve", };
            PossiblyBuysFor["Carol"] = new string[] { "Bob", "David", "Eve", };
            PossiblyBuysFor["David"] = new string[] { "Alice", "Carol", "Eve", };
            PossiblyBuysFor["Eve"] = new string[] { "Alice", "Bob", "Carol", "David", };

            foreach (var giver in PossiblyBuysFor.Keys)
            {
                Decision d = new Decision(Recipients, giver.ToLower());
                model.AddDecision(d);   
            }

            foreach (var giver in PossiblyBuysFor.Keys)
            {
                string term = "1 == 0 ";
                foreach (var valid in PossiblyBuysFor[giver])
                {
                    term += string.Format(" | {0} == \"{1}\"", giver.ToLower(), valid);
                }

                model.AddConstraint("domain_restriction_" + giver, term); 
            }

            model.AddConstraint("one_present_each", Model.AllDifferent(model.Decisions.ToArray()));

            Solution solution = context.Solve(new ConstraintProgrammingDirective());



            int i = 0;
            while (solution.Quality != SolverQuality.Infeasible && i < 10)
            {
                Console.WriteLine(i);

                foreach (var d in solution.Decisions)
                {

                    Console.WriteLine(string.Format("{0} buys for {1}", d.Name, d.ToString()));
                }

                Console.ReadKey();
                solution.GetNext();
                i++;
            }
            Console.WriteLine("The end");
            Console.ReadKey();

        }
于 2014-04-02T13:28:45.267 回答