protected bool ArcReduce(BinaryConstraint <T> arc)
        {
            var x = arc.VariableA;
            var y = arc.VariableB;

            bool change = false;

            for (var i = 0; i < x.Domain.Count; i++)
            {
                var valueX = x.Domain[i];
                x.Current = valueX;

                bool satisfactionFound = false;
                foreach (var valueY in y.Domain)
                {
                    y.Current = valueY;
                    if (arc.Check())
                    {
                        satisfactionFound = true;
                        break;
                    }
                }

                if (!satisfactionFound)
                {
                    Console.WriteLine("Reduced xd");
                    x.Domain.Remove(valueX);
                    change = true;
                }

                y.Current = default;
            }

            x.Current = default;

            return(change);
        }
        // Pseudokod xDxD
        // https://en.wikipedia.org/wiki/AC-3_algorithm
        protected bool Ac3()
        {
            //List<(IVariable<T>, IVariable<T>)> workList = new List<(IVariable<T>, IVariable<T>)>();
            List <BinaryConstraint <T> > workList = new List <BinaryConstraint <T> >();

            foreach (var constraint in Constraints)
            {
                var cast = constraint as BinaryConstraint <T>;
                if (cast != null)
                {
                    workList.Add(cast);
                    BinaryConstraint <T> reverseConstraint = new BinaryConstraint <T>()
                    {
                        Check     = cast.Check,
                        VariableA = cast.VariableB,
                        VariableB = cast.VariableA
                    };
                    workList.Add(reverseConstraint);
                }
            }

            while (workList.Count > 0)
            {
                var arc = workList[0];
                workList.RemoveAt(0);
                if (ArcReduce(arc))
                {
                    if (arc.VariableA.Domain.Count == 0)
                    {
                        return(false);
                    }
                    else
                    {
                        Constraints.ForEach(c =>
                        {
                            var cast            = c as BinaryConstraint <T>;
                            IVariable <T> other = null;
                            if (cast.VariableA == arc.VariableA)
                            {
                                other = cast.VariableB;
                            }
                            if (cast.VariableB == arc.VariableA)
                            {
                                other = cast.VariableA;
                            }

                            if (other != null && other != arc.VariableB)
                            {
                                workList.Add(cast);
                                BinaryConstraint <T> reverseConstraint = new BinaryConstraint <T>()
                                {
                                    Check     = cast.Check,
                                    VariableA = cast.VariableB,
                                    VariableB = cast.VariableA
                                };
                                workList.Add(reverseConstraint);
                            }
                        });
                    }
                }
            }

            return(true);
        }