Ошибка MS Solver Foundation CSP - входные данные имеют другой домен символов

Я пытаюсь использовать Microsoft Solver Foundation, чтобы решить нашу семейную рождественскую розыгрыш (аналогично «секретный Санта» или «крис крингл ").

У меня есть некоторые сложные ограничения (например, я не могу купить для своих братьев и сестер), которые я уже использовал для сокращения доменов для каждого участника.

Решатель работает, за исключением того, что у него нет ограничения, согласно которому человек должен получить только один подарок (т.е. Алиса, покупающая для Боба, подразумевает, что никто другой не покупает для Боба).

Я попытался добавить ограничение «Все разные», но получаю исключение аргумента -

«Входные данные Алисы и Боба имеют разные домены символов».

Я также попытался добавить ограничение как выражение 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();
        }
    }   
}

person Spongeboy    schedule 02.04.2014    source источник


Ответы (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();

        }
person Spongeboy    schedule 02.04.2014