///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        private void _InitRestrictions(SolveInfo settings,
                                       UserSolveInfo userSettings)
        {
            // user restrictions
            if (userSettings.SolverSettingsInfo.RestrictionsInfo == null)
            {
                userSettings.SolverSettingsInfo.RestrictionsInfo = new UserRestrictionsInfo();
            }

            if (userSettings.SolverSettingsInfo.RestrictionsInfo.Restrictions == null)
            {
                userSettings.SolverSettingsInfo.RestrictionsInfo.Restrictions = new List <RestrictionInfo>();
            }

            _userRestrictions = userSettings.SolverSettingsInfo.RestrictionsInfo.Restrictions;

            // default (read-only) restrictions
            if (settings.SolverSettingsInfo != null &&
                settings.SolverSettingsInfo.RestrictionsInfo != null &&
                settings.SolverSettingsInfo.RestrictionsInfo.Restrictions != null)
            {
                _defaultRestrictions = new List <RestrictionInfo>(
                    settings.SolverSettingsInfo.RestrictionsInfo.Restrictions);
            }

            if (_defaultRestrictions == null)
            {
                _defaultRestrictions = new List <RestrictionInfo>();
            }

            // fill merged names list
            _AddRestrictionNames(_defaultRestrictions);
            _AddRestrictionNames(_userRestrictions);
        }
Example #2
0
        public override bool FindPattern(GameBoard board)
        {
            Board = board;
            Cell solutionCell = Board
                                .GetAllLines(Coord.ROWS)
                                .SelectMany(t => t)
                                .FirstOrDefault(cell => cell.PencilMarkCount == 1);

            if (solutionCell == null)
            {
                return(false);
            }

            int pmMask = solutionCell.PMSignature;
            int pm     = pmMask.ListOfBits()[0];

            Solution = new SolveInfo();
            Solution.AddAction(solutionCell, CellRole.Pattern,
                               new PMFinding(pm, PMRole.Solution));

            solutionCell
            .ShadowedCells
            .Where(c => c.IsPencilmarkSet(pm))
            .ToList()
            .ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                GetPmFindings(cell, pmMask, PMRole.Remove)));


            string csvPattern = CellsInCsvFormat(solutionCell);

            Solution.Description = $"Only possible value for cell {csvPattern} is {pm}.";

            return(true);
        }
Example #3
0
        private void btnOk_Click(object sender, EventArgs e)
        {
            String inputString = inputTextBox.Text;

            try
            {
                Term      goal   = new Struct("dExpr", Term.createTerm(inputString), new Var("Der"));
                SolveInfo answer = engine.solve(goal);
                if (answer.isSuccess())
                {
                    Term derivata = answer.getTerm("Der");
                    lblRes.Text = derivata.toString();
                }
                else
                {
                    lblRes.Text = "Error: no solution";
                }
            }
            catch (InvalidTermException e3)
            {
                Console.WriteLine("The esxpression is not a valid Prolog Term.");
            }
            catch (UnknownVarException e4)
            {
                Console.WriteLine("Variable not valid.");
            }
            catch (NoSolutionException e5)
            {
                Console.WriteLine("No solutions.");
            }
        }
        private void PreAnalizeToSolve(Circuit cir, List <Node> nodos, SolveInfo solveinfo)
        {
            nodos.AddRange(cir.Nodes.Values);
            nodos.Remove(cir.Reference);

            //guardo para futuro los nodos de los componentes especiales
            if (cir.OriginalCircuit != null)
            {
                foreach (var comp in cir.OriginalCircuit.Components)
                {
                    if (comp is ControlledDipole)
                    {
                        foreach (var nodo in comp.Nodes)
                        {
                            if (!nodo.IsReference)
                            {
                                SpecialComponentInfo info = new SpecialComponentInfo(comp);
                                info.ImportantOutputNodes.Add(nodo);
                                solveinfo.specialcomponents.Add(info);
                                if (!solveinfo.nortonnodes.Contains(nodo))
                                {
                                    solveinfo.nortonnodes.Add(nodo);
                                }
                                //especialcomponents.Add(nodo, comp);
                            }
                        }
                    }
                }
            }

            foreach (var compo in cir.Components)
            {
                if (compo is Branch)
                {
                    solveinfo.ramas.Add((Branch)compo);
                }
            }

            foreach (var nodo in nodos)
            {
                //los nodos de salida de un dispositivo VcV deben resolverse mediante matrices

                if (solveinfo.nortonnodes.Contains(nodo))
                {
                    continue;
                }
                if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                    nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode
                    )
                {
                    solveinfo.nortonnodes.Add(nodo);
                }
                else if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode ||
                         nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    solveinfo.calculablenodes.Add(nodo);
                }
            }
        }
Example #5
0
 public bool hasSolutionWithOutput()
 {
     output = "";
     engine.addOutputListener(new StringOutputListener(output));
     result = engine.solve(query);
     engine.removeAllOutputListeners();
     return(result.isSuccess());
 }
        public bool Solve(Components.Circuit cir, BasicAnalysis ana)
        {
            List <Node> nodos = new List <Node>();

            Voltages = new Dictionary <double, Dictionary <string, double> >();
            Currents = new Dictionary <double, Dictionary <string, double> >();
            circuit  = cir;

            SolveInfo solveinfo = new SolveInfo();

            //nodos.AddRange(cir.Nodes.Values);
            //nodos.Remove(cir.Reference);

            PreAnalizeToSolve(cir, nodos, solveinfo);

            TransientAnalysis analis = ana as TransientAnalysis;
            double            t, tf, deltat;

            deltat          = StringUtils.DecodeString(analis.Step);
            tf              = StringUtils.DecodeString(analis.FinalTime);
            t               = 0;
            cir.CircuitTime = t;
            cir.Reset();

            while (t < tf)
            {
                //Calculo de tensiones de nodos
                Calculate(solveinfo, t);

                Dictionary <string, double> result = new Dictionary <string, double>();

                #region almacenamiento temporal

                foreach (var nodo in nodos)
                {
                    result.Add(nodo.Name, nodo.Voltage.Real);
                }

                if (!Voltages.ContainsKey(t))
                {
                    Voltages.Add(t, result);
                }
                #endregion

                //calculo las corrientes:
                CalculateCurrents(cir, t);
                Dictionary <string, double> currents = new Dictionary <string, double>();
                StorageCurrents(cir, currents);
                Currents.Add(t, currents);


                cir.CircuitTime = t;
                t += deltat;
            }
            cir.State = Circuit.CircuitState.Solved;

            return(true);
        }
Example #7
0
        private bool FindXYWing(Cell cell1, Cell cell2)
        {
            Cell       Pincer1           = cell1;
            Cell       Pincer2           = cell2;
            int        commonPMSignature = (cell1.PMSignature & cell2.PMSignature);
            List <int> commonPMs         = commonPMSignature.ListOfBits();
            int        pivotSignature    = cell1.PMSignature ^ cell2.PMSignature;

            if (cell1 == cell2 || commonPMs.Count != 1 || pivotSignature.NumberOfBitsSet() != 2)
            {
                return(false);
            }

            IEnumerable <Cell> shadowedZone = cell1.ShadowedCells
                                              .Intersect(cell2.ShadowedCells);

            affectedCells = shadowedZone.Where(c => (c.PMSignature & commonPMSignature) != 0).ToList();
            if (affectedCells.Count == 0)
            {
                return(false);
            }

            Cell Pivot       = null;
            bool returnValue =
                (cell1.PMSignature | cell2.PMSignature).NumberOfBitsSet() == 3 &&
                cell1.ColIndex != cell2.ColIndex && cell1.RowIndex != cell2.RowIndex &&
                cell1.GroupIndex != cell2.GroupIndex &&
                (Pivot = shadowedZone.FirstOrDefault(c => c.PMSignature == pivotSignature)) != null;

            patternCells = new List <Cell> {
                Pincer1, Pivot, Pincer2
            };
            if (returnValue)
            {
                Solution = new SolveInfo();
                new List <Cell> {
                    Pincer1, Pincer2
                }
                .ForEach(cell => Solution.AddAction(cell, CellRole.Pattern2,
                                                    GetPmFindings(cell, commonPMSignature, PMRole.Pattern)));

                Solution.AddAction(Pivot, CellRole.Pattern, GetPmFindings(Pivot, pivotSignature, PMRole.Pattern));

                affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                 GetPmFindings(cell, commonPMSignature, PMRole.Remove)));

                string     csvPivot    = CellsInCsvFormat(Pivot);
                string     csvAffected = CellsInCsvFormat(affectedCells);
                string     csvPincers  = CellsInCsvFormat(Pincer1, Pincer2);
                List <int> pivotPMs    = pivotSignature.ListOfBits().ToList();
                Solution.Description = $"XY-Wing Rule:  No matter what the value of cell {csvPivot} is " +
                                       $"(either {pivotPMs[0]} or {pivotPMs[1]}), cell {csvAffected} cannot possibly have value {csvPincers} " +
                                       $"because one of cells {csvPincers} will have that value.";
            }

            return(returnValue);
        }
Example #8
0
 internal void HighlightCells(SolveInfo solveInfo)
 {
     HighlightedCells.Clear();
     foreach (RuleFinding action in solveInfo.Actions)
     {
         UICell uiCell = UICellFromCell(action.Cell);
         uiCell.Highlight(action.CellRole, action.PencilmarkDataList);
         HighlightedCells.Add(uiCell);
     }
 }
Example #9
0
        public bool Success()
        {
            Prolog engine = new Prolog();

            OOLibrary.OOLibrary lib = new OOLibrary.OOLibrary();
            engine.unloadLibrary("alice.tuprolog.lib.JavaLibrary");
            engine.loadLibrary(lib);
            SolveInfo info = engine.solve(goal);

            return(info.isSuccess());
        }
Example #10
0
 public bool hasAnotherSolution()
 {
     try
     {
         result = engine.solveNext();
         return(result.isSuccess());
     }
     catch (PrologException e)
     {
         return(false);
     }
 }
Example #11
0
        private void InputButton_Click(object sender, EventArgs e)
        {
            OutputTextBox.Clear();
            try
            {
                if (prolog == null)
                {
                    labelError.Text = "Please Select Theory";
                    return;
                }
                if (prolog is Perm)
                {
                    Term      goal = new Struct("perm", Term.createTerm(InputTextBox.Text), new Var("R"));
                    SolveInfo SI   = prolog.solve(goal);

                    if (!SI.isSuccess())
                    {
                        OutputTextBox.AppendText("no");
                    }

                    while (SI.isSuccess())
                    {
                        OutputTextBox.AppendText(SI.getTerm("R").toString() + "\n");
                        if (prolog.hasOpenAlternatives())
                        {
                            SI = prolog.solveNext();
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else if (prolog is PrologDerivate)
                {
                    Term      goal = new Struct("dExpr", Term.createTerm(InputTextBox.Text), new Var("DT"));
                    SolveInfo SI   = prolog.solve(goal);

                    if (!SI.isSuccess())
                    {
                        OutputTextBox.AppendText("no");
                    }
                    else
                    {
                        OutputTextBox.AppendText(SI.getTerm("DT").toString() + "\n");
                    }
                }
            }
            catch (MalformedGoalException ex) {
                OutputTextBox.AppendText("Malformed Goal\n");
            }
        }
        public override bool FindPattern(GameBoard board)
        {
            Board = board;
            for (int coord = Coord.ROW; coord <= Coord.SECTION; coord++)
            {
                List <List <Cell> > allLines = board.GetAllLines(coord);
                bool inSections = coord == Coord.SECTION;
                int  secCoord   = inSections ? Coord.ROW : 1 - coord;
                int  thirdCoord = inSections ? Coord.COL : Coord.SECTION;
                for (int iValue = 1; iValue <= board.Dimension; iValue++)
                {
                    Solution = new SolveInfo();
                    List <Cell> singleLine =
                        allLines.FirstOrDefault(line => HasLockedCells(line, iValue, thirdCoord) ||
                                                (coord == Coord.SECTION && HasLockedCells(line, iValue, secCoord)));

                    if (singleLine != null)
                    {
                        int    pmMask             = 1 << iValue;
                        string csvCells           = CellsInCsvFormat(patternCells);
                        string csvAffected        = CellsInCsvFormat(affectedCells);
                        int    involvedCoordinate = coord;
                        int    lineIndex          = singleLine[0].GetCoordinate(coord);

                        affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                         GetPmFindings(cell, pmMask, PMRole.Remove)));

                        patternCells.ForEach(cell => Solution.AddAction(cell, RuleData.CellRole.Pattern,
                                                                        GetPmFindings(cell, pmMask, PMRole.Pattern)));

                        Board.GetLine(involvedCoordinate, lineIndex)
                        .Except(patternCells)
                        .ToList()
                        .ForEach(cell => Solution.AddAction(cell, RuleData.CellRole.InvolvedLine));

                        Solution.Description = string.Format("Locked Cells Rule: One of cells {0} must have " +
                                                             "solution value {3}.  All cells share a {1} " +
                                                             " and a {2}. Therefore no other cell in that {2} could possibly have that " +
                                                             "value (or else no cell in the {1} could have the value). " +
                                                             "This means value {3} can be ruled out for cells {4}.",
                                                             csvCells, LineNames[coord], LineNames[thirdCoord], iValue, csvAffected);

                        return(true);
                    }
                }
            }

            return(false);
        }
Example #13
0
 public bool hasAnotherSolutionWithOutput()
 {
     output = "";
     engine.addOutputListener(new StringOutputListener(output));
     try
     {
         result = engine.solveNext();
         engine.removeAllOutputListeners();
         return(result.isSuccess());
     }
     catch (PrologException e)
     {
         return(false);
     }
 }
        private void _InitAttrParameters(SolveInfo settings,
                                         UserSolveInfo userSettings)
        {
            // user parameters
            if (userSettings.SolverSettingsInfo.AttributeParamsInfo == null)
            {
                userSettings.SolverSettingsInfo.AttributeParamsInfo = new UserRouteAttrsInfo();
            }

            if (userSettings.SolverSettingsInfo.AttributeParamsInfo.AttributeParams == null)
            {
                userSettings.SolverSettingsInfo.AttributeParamsInfo.AttributeParams = new List <RouteAttrInfo>();
            }

            _userParams = userSettings.SolverSettingsInfo.AttributeParamsInfo.AttributeParams;

            // default (read-only) parameters
            if (settings.SolverSettingsInfo != null &&
                settings.SolverSettingsInfo.AttributeParamsInfo != null &&
                settings.SolverSettingsInfo.AttributeParamsInfo.AttributeParams != null)
            {
                _defaultParams = new List <RouteAttrInfo>(
                    settings.SolverSettingsInfo.AttributeParamsInfo.AttributeParams);
            }

            if (_defaultParams == null)
            {
                _defaultParams = new List <RouteAttrInfo>();
            }

            // fill merged list
            _mergedParams = new List <RouteAttrInfo>(_userParams);
            foreach (RouteAttrInfo defParam in _defaultParams)
            {
                if (!String.IsNullOrEmpty(defParam.AttrName) &&
                    !String.IsNullOrEmpty(defParam.ParamName))
                {
                    RouteAttrInfo param = _FindAttrParameter(defParam.AttrName,
                                                             defParam.ParamName,
                                                             _mergedParams);

                    if (param == null)
                    {
                        _mergedParams.Add(defParam);
                    }
                }
            }
        }
Example #15
0
        public IHttpActionResult SolveMaze(SolveRequest solveRequest)
        {
            string searchAlgo = "1";

            if (solveRequest.SearchAlgo == "BFS")
            {
                searchAlgo = "0";
            }
            SolveInfo       solveInfo       = Model.SolveMaze(solveRequest.Name, searchAlgo);
            SolutionAdapter solutionAdapter = new SolutionAdapter(solveInfo.Solution);
            string          strSolution     = solutionAdapter.CreateString();

            JObject solutionObj = new JObject();

            solutionObj["Name"]     = solveRequest.Name;
            solutionObj["Solution"] = strSolution;

            return(Ok(solutionObj));
        }
        /// <summary>
        /// Initialize services.
        /// </summary>
        /// <param name="settings">Configuration settings.</param>
        private void _InitServices(SolveInfo settings)
        {
            // Initialize VRP and Sync VRP services.
            _vrpService         = _GetFirstServiceInfo(settings.VrpInfo);
            this.SyncVrpService = _GetFirstServiceInfo(settings.SyncVrpInfo);

            // Initialize route service.
            if (settings.RoutingInfo != null &&
                settings.RoutingInfo.ServiceInfo != null &&
                settings.RoutingInfo.ServiceInfo.Length > 0)
            {
                _routeService = settings.RoutingInfo.ServiceInfo[0];
            }

            // Initialize discovery service.
            if (settings.DiscoveryInfo != null &&
                settings.DiscoveryInfo.ServiceInfo != null)
            {
                _discoveryService = settings.DiscoveryInfo.ServiceInfo.FirstOrDefault();
            }
        }
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        public SolveInfoWrap(SolveInfo settings, UserSolveInfo userSettings)
        {
            Debug.Assert(settings != null);
            Debug.Assert(userSettings != null);

            if (userSettings.SolverSettingsInfo == null)
            {
                userSettings.SolverSettingsInfo = new UserSolverSettingsInfo();
            }

            // restrictions
            _InitRestrictions(settings, userSettings);

            // parameters
            _InitAttrParameters(settings, userSettings);

            // services
            _InitServices(settings);

            _settings     = settings;
            _userSettings = userSettings;
        }
Example #18
0
        public static void Main(string[] args)
        {
            //OpenFileDialog dialog = new OpenFileDialog();
            //dialog.ShowDialog();

            OOLibrary   lib    = new OOLibrary();
            InputStream stream = new FileInputStream(@"Test.pl");
            // InputStream stream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.pl");


            Prolog engine = new Prolog();
            //engine.unloadLibrary("alice.tuprolog.lib.JavaLibrary");
            //engine.loadLibrary(lib);

            Theory th = new Theory(stream);

            engine.addTheory(th);
            SolveInfo info = engine.solve("testInteroperation(X).");

            System.Console.WriteLine(info.isSuccess());
            System.Console.WriteLine(info.isHalted());

            //info = engine.solve("testBasicsWithJava.");
            //System.Console.WriteLine(info.isSuccess());
            //System.Console.WriteLine(info.isHalted());


            //java.util.List[] primitives = lib.getPrimitives();

            //for (int i = 0; i < primitives.Length; i++)
            //{
            //    PrimitiveInfo p = (PrimitiveInfo)primitives[i];
            //}



            System.Console.ReadLine();
        }
        public override bool Solve(Circuit cir, BasicAnalysis ana)
        {
            List <Node> nodos = new List <Node>();

            Voltages = new Dictionary <double, Dictionary <string, Complex32> >();
            Currents = new Dictionary <double, Dictionary <string, Complex32> >();

            //List<Node> nodosnorton;
            //List<Node> nodoscalculables;
            //List<SpecialComponentInfo> specialcomponents;
            SolveInfo solveinfo = new SolveInfo();

            PreAnalizeToSolve(cir, nodos, solveinfo);

            ACAnalysis analis = ana as ACAnalysis;
            double     w, wi, wf, deltaw, wx, pow = 1;

            wi = StringUtils.DecodeString(analis.StartFrequency);
            wf = StringUtils.DecodeString(analis.EndFrequency);
            w  = wi;
            int i = (int)Math.Log10(wi) + 1;

            wx = Math.Pow(10, i);
            if (analis.ScanType == ACAnalysis.ACAnalysisScan.Linear)
            {
                deltaw = (wf - wi) / analis.Points;
            }
            else
            {
                deltaw = 1.0d / analis.Points;
                pow    = Math.Pow(10, deltaw);
            }

            while (w < wf)
            {
                //Calculo de tensiones de nodos
                Complex32 W = new Complex32(0, (float)w);
                Calculate(solveinfo, W);

                Dictionary <string, Complex32> result = new Dictionary <string, Complex32>();

                #region almacenamiento temporal

                foreach (var nodo in nodos)
                {
                    result.Add(nodo.Name, nodo.Voltage);
                }

                if (!Voltages.ContainsKey(w))
                {
                    Voltages.Add(w, result);
                }
                #endregion

                //calculo las corrientes:
                CalculateCurrents(cir, W);
                Dictionary <string, Complex32> currents = new Dictionary <string, Complex32>();
                StorageCurrents(cir, currents);
                Currents.Add(w, currents);


                if (analis.ScanType == ACAnalysis.ACAnalysisScan.Linear)
                {
                    w += deltaw;
                }
                else
                {
                    w = w * pow;
                    if (w > 0.95 * wx)
                    {
                        i++;
                        wi = wx;
                        wx = Math.Pow(10, i);
                        w  = wi;
                    }
                }
            }

            cir.State = Circuit.CircuitState.Solved;
            return(true);
        }
        protected static void Calculate(SolveInfo solveinfo, Complex32 W)
        {
            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
            {
                return;
            }

            //existen nodos donde la tension se puede calcular directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is ACVoltageGenerator))
                        {
                            nodo.Voltage = compo.voltage(nodo, W);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Calculo de tensions mediante matrices

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0, max;
                //cada componente especial agrega 0, 1 o 2 variable mas, dependiendo del tipo
                max = solveinfo.MatrixDimension;
                var v = Vector <Complex32> .Build.Dense(max);

                var A = Matrix <Complex32> .Build.DenseOfArray(new Complex32[max, max]);

                //primero la ecuacion de transferencia del VcV
                foreach (var info in solveinfo.specialcomponents)
                {
                    //foreach (var item in info.Component)
                    //{

                    //}
                    //int entrada = especialcomponents.IndexOf(info);
                    //fila = nodosnorton.Count - 1 + entrada;
                    columna          = 1;
                    A[fila, columna] = 1;
                }

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    Complex32 Z, V;
                    if (
                        nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.VoltageFixedNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is PasiveComponent)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                {
                                    V = ((Branch)rama).NortonCurrent(nodo, W);
                                }
                                else
                                {
                                    V = rama.Current(nodo, W);
                                }

                                v[fila]          += V;
                                Z                 = rama.Impedance(W);
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference)
                                {
                                    columna           = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator)
                            {
                                V        = rama.Current(nodo, W);
                                v[fila] += V;
                            }
                            else if (rama is VoltageControlledGenerator)
                            {
                                //int entrada = especialcomponents.Values.ToList().IndexOf(rama);
                                //columna = nodosnorton.Count -1 + entrada;

                                ////un nodo es positva la corriente, en el otro es negativa
                                //if (entrada % 2 == 0)
                                //    A[fila, columna] = 1;
                                //else
                                //    A[fila, columna] = -1;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator))
                        {
                            compo = nodo.Components[1];
                        }
                        v[fila]          = compo.Voltage.Real;
                        A[fila, columna] = 1;
                        columna          = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    //else if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                    //{
                    //    foreach (var rama in nodo.Components)
                    //    {
                    //        if (rama is VoltageControlledGenerator)
                    //        {

                    //        }
                    //    }
                    //}
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                var x = A.Solve(v);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila         = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = x[fila];
                }
            }

            #endregion

            //existen nodos donde la tension se puede calcular indirectamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node   nodo1  = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br     = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    Complex32 v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = Complex32.Zero;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo,
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, W, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, W, ref v2, ref z2);
                    nodo.Voltage = (z2 * v1 + v2 * z1) / (z1 + z2);
                }
            }
        }
        public override bool Solve(Circuit cir, BasicAnalysis ana)
        {
            List<Node> nodos = new List<Node>();
            Voltages = new Dictionary<double, Dictionary<string, Complex32>>();
            Currents = new Dictionary<double, Dictionary<string, Complex32>>();

            //List<Node> nodosnorton;
            //List<Node> nodoscalculables;
            //List<SpecialComponentInfo> specialcomponents;
            SolveInfo solveinfo = new SolveInfo();

            PreAnalizeToSolve(cir, nodos, solveinfo);

            ACAnalysis analis = ana as ACAnalysis;
            double w, wi, wf, deltaw, wx, pow = 1;

            wi = StringUtils.DecodeString(analis.StartFrequency);
            wf = StringUtils.DecodeString(analis.EndFrequency);
            w = wi;
            int i = (int)Math.Log10(wi) + 1;
            wx = Math.Pow(10, i);
            if (analis.ScanType == ACAnalysis.ACAnalysisScan.Linear)
                deltaw = (wf - wi) / analis.Points;
            else
            {
                deltaw = 1.0d / analis.Points;
                pow = Math.Pow(10, deltaw);
            }

            while (w < wf)
            {
                //Calculo de tensiones de nodos
                Complex32 W = new Complex32(0, (float)w);
                Calculate(solveinfo, W);

                Dictionary<string, Complex32> result = new Dictionary<string, Complex32>();

                #region almacenamiento temporal
 
                foreach (var nodo in nodos)
                {
                    result.Add(nodo.Name, nodo.Voltage);
                }

                if (!Voltages.ContainsKey(w))
                    Voltages.Add(w, result);
                #endregion

                //calculo las corrientes:
                CalculateCurrents(cir, W);
                Dictionary<string, Complex32> currents = new Dictionary<string, Complex32>();
                StorageCurrents(cir, currents);
                Currents.Add(w, currents);


                if (analis.ScanType == ACAnalysis.ACAnalysisScan.Linear)
                    w += deltaw;
                else
                {
                    w = w * pow;
                    if (w > 0.95 * wx)
                    {
                        i++;
                        wi = wx;
                        wx = Math.Pow(10, i);
                        w = wi;
                    }
                }
            }

            cir.State = Circuit.CircuitState.Solved;
            return true;
        }
        protected static void Calculate(SolveInfo solveinfo, double t)
        {
            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
            {
                return;
            }

            //tensiones que se calculan directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is VoltageGenerator || compo is Capacitor))
                        {
                            nodo.Voltage = new Complex32((float)compo.voltage(nodo, t), 0);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Tensiones de nodos que se calculan mediante matriz

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0;
                var Currs = Vector <double> .Build.Dense(solveinfo.MatrixDimension);

                var A = Matrix <double> .Build.DenseOfArray(new double[solveinfo.MatrixDimension, solveinfo.MatrixDimension]);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    double Z, I;
                    if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is Resistor)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                {
                                    I = ((Branch)rama).NortonCurrent(nodo, t);
                                }
                                else
                                {
                                    I = rama.Current(nodo, t);
                                }

                                Currs[fila]      += I;
                                Z                 = rama.Impedance().Real;
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference && solveinfo.nortonnodes.Contains(nodo2))
                                {
                                    columna           = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator || rama is Inductor)
                            {
                                I            = rama.Current(nodo, t);
                                Currs[fila] += I;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator || compo is Capacitor))
                        {
                            compo = nodo.Components[1];
                        }
                        Currs[fila]      = compo.voltage(nodo, t);
                        A[fila, columna] = 1;
                        columna          = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                var x = A.Solve(Currs);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila         = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = new Complex32((float)x[fila], 0);
                }
            }
            #endregion

            //existen nodos donde la tension se puede calcular casi directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node   nodo1  = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br     = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    double v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = 0;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo,
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, t, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, t, ref v2, ref z2);
                    nodo.Voltage = new Complex32((float)((z2 * v1 + v2 * z1) / (z1 + z2)), 0);
                }
            }

            //parto del extremo de la rama
            foreach (var rama in solveinfo.ramas)
            {
                Node nodo1 = null;
                //busco nodos ya calculados en la rama
                foreach (var nodo in rama.InternalNodes)
                {
                    if (!solveinfo.calculablenodes.Contains(nodo) && !solveinfo.nortonnodes.Contains(nodo))
                    {
                        nodo1 = nodo;
                        break;
                    }
                }
                if (nodo1 == null)
                {
                    continue;
                }

                double i = 0;
                //encuentro la corriente impuesta de la rama si es que la hay
                //nodo1 = rama.Nodes[0];

                i = rama.Current(nodo1, t);
                Dipole compo1 = null;
                foreach (var compo in rama.Components)
                {
                    //busco el componente hubicado en un extremo de la rama
                    if (compo.Nodes[0] == nodo1 || compo.Nodes[1] == nodo1)
                    {
                        compo1 = compo;
                        break;
                    }
                }
                Node nodo2 = compo1.OtherNode(nodo1);
                if (compo1 is VoltageGenerator)
                {
                    //nodo de tension vinculada
                    nodo1.Voltage = nodo2.Voltage + new Complex32((float)compo1.voltage(nodo2, t), 0);
                }
                else if (compo1 is Resistor)
                {
                    //nodo interno, pero conocemos la corriente
                    nodo1.Voltage = nodo2.Voltage - new Complex32((float)i * compo1.Impedance().Real, 0);
                }
                else
                {
                    throw new NotImplementedException();
                }
                //if (nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                //{
                //}
            }
        }
        protected static void Calculate(SolveInfo solveinfo, double t)
        {

            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
                return;

            //tensiones que se calculan directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is VoltageGenerator || compo is Capacitor))
                        {
                            nodo.Voltage = new Complex32((float)compo.voltage(nodo, t), 0);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Tensiones de nodos que se calculan mediante matriz

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0;
                var Currs = Vector<double>.Build.Dense(solveinfo.MatrixDimension);
                var A = Matrix<double>.Build.DenseOfArray(new double[solveinfo.MatrixDimension, solveinfo.MatrixDimension]);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    double Z, I;
                    if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is Resistor)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                    I = ((Branch)rama).NortonCurrent(nodo, t);
                                else
                                    I = rama.Current(nodo, t);
                                
                                Currs[fila] += I;
                                Z = rama.Impedance().Real;
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference && solveinfo.nortonnodes.Contains(nodo2))
                                {
                                    columna = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator || rama is Inductor)
                            {
                                I = rama.Current(nodo, t);
                                Currs[fila] += I;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator || compo is Capacitor))
                            compo = nodo.Components[1];
                        Currs[fila] = compo.voltage(nodo, t);
                        A[fila, columna] = 1;
                        columna = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    else
                        throw new NotImplementedException();
                }
                var x = A.Solve(Currs);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = new Complex32((float)x[fila], 0);
                }
            }
            #endregion

            //existen nodos donde la tension se puede calcular casi directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
               
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node nodo1 = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    double v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = 0;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo, 
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, t, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, t, ref v2, ref z2);
                    nodo.Voltage = new Complex32((float) ((z2 * v1 + v2 * z1) / (z1 + z2)),0);
                }
            }

            //parto del extremo de la rama
            foreach (var rama in solveinfo.ramas)
            {
                Node nodo1 = null;
                //busco nodos ya calculados en la rama
                foreach (var nodo in rama.InternalNodes)
                {
                    if (!solveinfo.calculablenodes.Contains(nodo) && !solveinfo.nortonnodes.Contains(nodo))
                    {
                        nodo1 = nodo;
                        break;
                    }
                }
                if (nodo1 == null)
                    continue;

                double i = 0;
                //encuentro la corriente impuesta de la rama si es que la hay
                //nodo1 = rama.Nodes[0];
                
                i = rama.Current(nodo1, t);
                Dipole compo1 = null;
                foreach (var compo in rama.Components)
	            {
                    //busco el componente hubicado en un extremo de la rama
                    if (compo.Nodes[0] == nodo1 || compo.Nodes[1] == nodo1)
                    {
                        compo1 = compo;
                        break;
                    }
	            }
                Node nodo2 = compo1.OtherNode(nodo1);
                if (compo1 is VoltageGenerator)
                {
                    //nodo de tension vinculada
                    nodo1.Voltage = nodo2.Voltage + new Complex32((float) compo1.voltage(nodo2, t), 0);
                }
                else if (compo1 is Resistor)
                {
                    //nodo interno, pero conocemos la corriente
                    nodo1.Voltage = nodo2.Voltage - new Complex32((float) i * compo1.Impedance().Real, 0);
                }
                else
                {
                    throw new NotImplementedException();
                }
                //if (nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                //{
                //}
            }

        }
Example #24
0
        public override bool FindPattern(GameBoard board)
        {
            Board = board;
            var allALS = new List <AlmostLockedSet>();

            for (int coord = Coord.ROW; coord <= Coord.SECTION; coord++)
            {
                Board.GetAllLines(coord)
                .ForEach(line => allALS.AddRange(
                             AlmostLockedSet.CreateALSsFromLine(line, coord)));
            }

            int      alsCount = allALS.Count;
            ALSMatch match;

            for (int i = 0; i < alsCount; i++)
            {
                for (int j = i + 1; j < alsCount; j++)
                {
                    if ((match = AlmostLockedSet.AreAlsXZ(allALS[i], allALS[j])) == null)
                    {
                        continue;
                    }

                    Solution = new SolveInfo();
                    int commonMask     = 1 << match.commonPencilmark;
                    int restrictedMask = 1 << match.commonRestrictedPencilmark;

                    match.AffectedCells
                    .ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                        GetPmFindings(cell, commonMask, PMRole.Remove)));

                    int pmMask = commonMask | restrictedMask;
                    match.Als1.Cells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                        GetPmFindings(cell,
                                                                                      new int[] { commonMask, restrictedMask },
                                                                                      new PMRole[] { PMRole.ChainColor1, PMRole.ChainColor2 })));

                    match.Als2.Cells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern2,
                                                                        GetPmFindings(cell,
                                                                                      new int[] { commonMask, restrictedMask },
                                                                                      new PMRole[] { PMRole.ChainColor1, PMRole.ChainColor2 })));

                    string csvALS1            = CellsInCsvFormat(match.Als1.Cells);
                    string csvALS2            = CellsInCsvFormat(match.Als2.Cells);
                    string csvAffected        = CellsInCsvFormat(match.AffectedCells);
                    string csvCommonCellsAls1 = CellsInCsvFormat(match.Als1.Cells
                                                                 .Where(cell => cell.IsPencilmarkSet(match.commonPencilmark))
                                                                 .ToList());

                    string csvCommonCellsAls2 = CellsInCsvFormat(
                        match.Als2.Cells
                        .Where(cell => cell.IsPencilmarkSet(match.commonPencilmark))
                        .ToList());

                    int pmCount1 = match.Als1.Cells.Count + 1;
                    int pmCount2 = match.Als2.Cells.Count + 1;

                    Solution.Description = string.Format("ALS - XZ Rule: Cells {0} have a total " +
                                                         "of {1} pencilmarks.  Cells {2} have a total of {3} pencilmarks. " +
                                                         "Pencilmark {4} is common and exclusive to both groups since they all " +
                                                         "can see each other.  Pencilmark {5} will either be in cells {6} or cells {7}." +
                                                         "Since cell(s) {8} are shadowed by all these, then option {5} can be removed " +
                                                         "in these cells.", csvALS1, pmCount1, csvALS2, pmCount2,
                                                         match.commonRestrictedPencilmark, match.commonPencilmark,
                                                         csvCommonCellsAls1, csvCommonCellsAls2, csvAffected);

                    return(true);
                }
            }

            return(false);
        }
Example #25
0
        /* Meters */

        public bool hasSolution()
        {
            result = engine.solve(this.query);
            return(result.isSuccess());
        }
Example #26
0
 public string Solve(SolveInfo si)
 {
     return(model.SolveGame(si.Name, si.Algo));
 }
        public override bool Solve(Circuit cir, BasicAnalysis ana)
        {
            List<Node> nodos = new List<Node>();
            CurrentAnalysis = ana as ComplexPlainAnalysis;
            CurrentCircuit = cir;

            //List<Node> nodosnorton = new List<Node>();
            //List<Node> nodoscalculables = new List<Node>();
            //List<SpecialComponentInfo> especialcomponents;
            Voltages = new Dictionary<Complex32, Dictionary<string, Complex32>>();
            Currents = new Dictionary<Complex32, Dictionary<string, Complex32>>();
            WfromIndexes = new Dictionary<Tuple<int, int>, Complex32>();
            SolveInfo solveinfo = new SolveInfo();

            PreAnalizeToSolve(cir, nodos, solveinfo);


            ComplexPlainAnalysis analis = ana as ComplexPlainAnalysis;
            double w, sig, wi, wf, deltaw, deltasig, sigmamin, sigmamax;

            wi = analis.WMin;
            wf = analis.WMax;
            sigmamax = analis.SigmaMax;
            sigmamin = analis.SigmaMin;
            w = wi;
            sig = sigmamin;
            deltaw = (wf - wi) / analis.Points;
            deltasig = (sigmamax - sigmamin) / analis.Points;

            Complex32 W = Complex32.Zero;

            for (int i = 0; i <= analis.Points; i++)
            {

                for (int j = 0; j <= analis.Points; j++)
                {
                    //Calculo de tensiones de nodos
                    W = new Complex32((float)(sigmamin + j * deltasig), (float)(wi + i * deltaw));
                    ACSweepSolver.Calculate(solveinfo, W);
                    
                    //          Node    Voltage
                    Dictionary<string, Complex32> result = new Dictionary<string, Complex32>();

                    #region almacenamiento temporal
                  
                    foreach (var nodo in nodos)
                    {
                        result.Add(nodo.Name, nodo.Voltage);
                    }
                    if (!Voltages.ContainsKey(W))
                    {
                        Voltages.Add(W, result);
                        WfromIndexes.Add(new Tuple<int, int>(i, j), W);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                   // Results[i,j] = new Tuple<Complex32,Complex32>(W, 

                    #endregion

                    //calculo las corrientes:
                    CalculateCurrents(cir, W);
                    Dictionary<string, Complex32> currents = new Dictionary<string, Complex32>();
                    StorageCurrents(cir, currents);
                    Currents.Add(W, currents);

                }
            }
            cir.State = Circuit.CircuitState.Solved;

            return true;
        }
        public bool Solve(Components.Circuit cir, BasicAnalysis ana)
        {
            List<Node> nodos = new List<Node>();
            Voltages = new Dictionary<double, Dictionary<string, double>>();
            Currents = new Dictionary<double, Dictionary<string, double>>();
            circuit = cir;

            SolveInfo solveinfo = new SolveInfo();

            //nodos.AddRange(cir.Nodes.Values);
            //nodos.Remove(cir.Reference);
           
            PreAnalizeToSolve(cir, nodos, solveinfo);
       
            TransientAnalysis analis = ana as TransientAnalysis;
            double t, tf, deltat;

            deltat = StringUtils.DecodeString(analis.Step);
            tf = StringUtils.DecodeString(analis.FinalTime);
            t = 0;
            cir.CircuitTime = t;
            cir.Reset();

            while (t < tf)
            {
                //Calculo de tensiones de nodos
                Calculate(solveinfo, t);

                Dictionary<string, double> result = new Dictionary<string, double>();

                #region almacenamiento temporal

                foreach (var nodo in nodos)
                {
                    result.Add(nodo.Name, nodo.Voltage.Real);
                }

                if (!Voltages.ContainsKey(t))
                    Voltages.Add(t, result);
                #endregion

                //calculo las corrientes:
                CalculateCurrents(cir, t);
                Dictionary<string, double> currents = new Dictionary<string, double>();
                StorageCurrents(cir, currents);
                Currents.Add(t, currents);


                cir.CircuitTime = t;
                t += deltat;
            }
            cir.State = Circuit.CircuitState.Solved;

            return true;
        }
        private void PreAnalizeToSolve(Circuit cir, List<Node> nodos, SolveInfo solveinfo)
        {
            nodos.AddRange(cir.Nodes.Values);
            nodos.Remove(cir.Reference);

            //guardo para futuro los nodos de los componentes especiales
            if (cir.OriginalCircuit != null)
            {
                foreach (var comp in cir.OriginalCircuit.Components)
                {
                    if (comp is ControlledDipole)
                    {
                        foreach (var nodo in comp.Nodes)
                        {
                            if (!nodo.IsReference)
                            {
                                SpecialComponentInfo info = new SpecialComponentInfo(comp);
                                info.ImportantOutputNodes.Add(nodo);
                                solveinfo.specialcomponents.Add(info);
                                if (!solveinfo.nortonnodes.Contains(nodo))
                                    solveinfo.nortonnodes.Add(nodo);
                                //especialcomponents.Add(nodo, comp);
                            }
                        }
                    }
                }
            }

            foreach (var compo in cir.Components)
            {
                if (compo is Branch)
                    solveinfo.ramas.Add((Branch)compo);
            }

            foreach (var nodo in nodos)
            {
                //los nodos de salida de un dispositivo VcV deben resolverse mediante matrices
              
                if (solveinfo.nortonnodes.Contains(nodo))
                    continue;
                if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                    nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode
                    )
                    solveinfo.nortonnodes.Add(nodo);
                else if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode ||
                        nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    solveinfo.calculablenodes.Add(nodo);
                }
            }

        }
Example #30
0
        private bool MakesUniqueRectangle(List <Cell> firstTwo)
        {
            int    keySignature = firstTwo[0].PMSignature;
            string csvAffected, csvPattern, csvHalf2;
            int    commonCoord;
            int    lineIndex;

            if ((lineIndex = firstTwo[0].RowIndex) == firstTwo[1].RowIndex)
            {
                commonCoord = Coord.ROW;
            }
            else if ((lineIndex = firstTwo[0].ColIndex) == firstTwo[1].ColIndex)
            {
                commonCoord = Coord.COL;
            }
            else
            {
                return(false);
            }

            int        diffCoord   = 1 - commonCoord;
            List <int> cellIndexes = firstTwo
                                     .Select(cell => cell.GetCoordinate(diffCoord))
                                     .ToList();

            List <List <Cell> > workLine = (commonCoord == Coord.ROW) ? allRows : allColumns;
            List <List <Cell> > secondHalfLineCandidates = workLine
                                                           .Where(line => line[0].GetCoordinate(commonCoord) != lineIndex &&
                                                                  (line[cellIndexes[0]].PMSignature & keySignature) == keySignature &&
                                                                  (line[cellIndexes[1]].PMSignature & keySignature) == keySignature)
                                                           .ToList();

            foreach (List <Cell> half2Line in secondHalfLineCandidates)
            {
                int         half2PencilmarkCount = 0;
                List <Cell> half2 = new List <Cell> {
                    half2Line[cellIndexes[0]], half2Line[cellIndexes[1]]
                };
                if (firstTwo.Union(half2)
                    .Select(cell => cell.GetCoordinate(Coord.SECTION))
                    .Distinct()
                    .Count() != 2)
                {
                    continue;
                }

                List <Cell> half2ManyPMs = half2.Where(cell => cell.PencilMarkCount > 2).ToList();
                half2.ForEach(cell => half2PencilmarkCount += cell.PencilMarkCount);
                int pmOtherMask;

                // Unique Rectangle - Type 1
                // 3 cells in the rectangle have 2 options, and the 4th cell has more.
                // In the 4th cell, the 2 common options should be turned off.
                if (half2ManyPMs.Count == 1)
                {
                    Solution = new SolveInfo();
                    Cell solutionCell = half2ManyPMs[0];

                    patternCells = new List <Cell>(firstTwo);
                    patternCells.AddRange(half2.Except(half2ManyPMs).ToList());
                    patternCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                    GetPmFindings(cell, keySignature, PMRole.Pattern)));

                    affectedCells = half2ManyPMs;
                    Solution.AddAction(solutionCell, CellRole.Pattern,
                                       GetPmFindings(solutionCell, keySignature, PMRole.Remove));

                    patternCells.Add(solutionCell);  // to include in description
                    csvPattern  = CellsInCsvFormat(patternCells);
                    csvAffected = CellsInCsvFormat(affectedCells);
                    string csvValues       = PMsInCsvFormat(keySignature.ListOfBits());
                    string csvSolutionCell = CellsInCsvFormat(solutionCell);
                    Solution.Description = $"Unique Rectangle - Type 1 : Cell {csvAffected} cannot " +
                                           $"have values {csvValues}. Otherwise a deadly pattern would form in cells {csvPattern}. " +
                                           $"Therefore these values can be ruled out for that cell.";

                    return(true);
                }

                // Possible case of Unique Rectangle - Type 2
                // 2 cells have 3 pencilmarks set (the same 3 for both), so one of the
                // 2 cells must be the 3rd value.   No other cells in the line (and section)
                // can hold that value.
                if (half2PencilmarkCount == 6 &&
                    half2[0].PMSignature == half2[1].PMSignature)
                {
                    Solution = new SolveInfo();
                    int mask = half2[0].PMSignature ^ keySignature;
                    affectedCells = half2Line.Except(half2)
                                    .Where(cell => (cell.PMSignature & mask) != 0)
                                    .ToList();

                    if (affectedCells.Count != 0)
                    {
                        List <Cell> affectedInGroup = Board
                                                      .GetLine(Coord.SECTION, half2[0].GetCoordinate(Coord.SECTION))
                                                      .Except(half2)
                                                      .Where(cell => (cell.PMSignature & mask) != 0)
                                                      .ToList();

                        affectedCells.AddRange(affectedInGroup);
                        patternCells = new List <Cell>(firstTwo);
                        patternCells.AddRange(half2);
                        affectedCells
                        .ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                            GetPmFindings(cell, mask, PMRole.Remove)));

                        Board.GetLine(commonCoord, lineIndex)
                        .Except(affectedCells)
                        .ToList()
                        .ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine));

                        int iValue = mask.ListOfBits()[0];
                        csvPattern  = CellsInCsvFormat(patternCells);
                        csvAffected = CellsInCsvFormat(affectedCells);
                        csvHalf2    = CellsInCsvFormat(half2);

                        Solution.Description = $"Unique Rectangle - Type 2: Value {iValue} has to " +
                                               $"be present in one of cells {csvHalf2} to avoid a deadly pattern (where the  puzzle " +
                                               $"would have 2 solutions). Therefore, value 2 cannot be present in any of " +
                                               $"cells {csvAffected}.";

                        return(true);
                    }
                }

                // Possible case of Unique Rectangle - Type 3
                // 2 cells have 3 or 4 pencilmarks.  The extra pencilmarks are treated as if
                // they were all in a single cell, and a naked pattern is searched for in the line
                // using these extra values.
                // Example: 4 cells have pencilmarks 3,9 - 3,9 - 1,5,3,9 - 1,5,3,9 .  The extra
                // values (1 and 5) are treated as being in a single cell, and a naked pattern is
                // searched for.  If 2 other cells have (1,4) and (4,5), then the 2 cells and the
                // virtual cell form a naked cell group of size 3 with values 1, 4, 5, and the naked
                // rule is applied accordingly on the line.
                if (half2PencilmarkCount >= 6 && half2PencilmarkCount <= 8)
                {
                    do
                    {
                        int pmsVirtualCell = 0;
                        half2.ForEach(cell => pmsVirtualCell |= cell.PMSignature);
                        pmsVirtualCell ^= firstTwo[0].PMSignature;
                        if (pmsVirtualCell.NumberOfBitsSet() != 2)
                        {
                            continue;
                        }

                        // clear one of the virtual cells completely
                        List <Cell> virtualLine = half2Line.Select(t => t.Clone()).ToList();

                        // change the pencilmarks in the other cell to match the virtual definition
                        virtualLine[cellIndexes[0]].SetValue(0);  // clear pencilmarks
                        virtualLine[cellIndexes[1]].SetValue(0);
                        virtualLine[cellIndexes[1]].SetMultiplePencilMarks(pmsVirtualCell);

                        // Now perform a search for a naked rule set
                        NakedHiddenFinder finder = new NakedHiddenFinder();
                        finder.MapBits   = NakedValuesRule.CreateMapBitsFromLine(virtualLine);
                        finder.MapLength = virtualLine.Count;
                        if (!finder.Search(2 /*goal*/) && !finder.Search(3 /*goal*/))
                        {
                            continue;
                        }

                        int pmsVirtualGroup = finder.ActionIndexes
                                              .Select(i => half2Line[i].PMSignature)
                                              .ToList()
                                              .BitMerge();

                        affectedCells = new List <Cell>();
                        Solution      = new SolveInfo();

                        pmOtherMask   = finder.ActionBits.BitMerge();
                        affectedCells = half2Line
                                        .Except(finder.ActionIndexes.Select(i => half2Line[i]).ToList())
                                        .Except(half2)
                                        .Where(cell => (cell.PMSignature & pmOtherMask) != 0)
                                        .ToList();

                        affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                         GetPmFindings(cell, pmOtherMask, PMRole.Remove)));

                        int deadlySignature = firstTwo[0].PMSignature;
                        firstTwo.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                    GetPmFindings(cell, deadlySignature, PMRole.Pattern)));

                        half2.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                 GetPmFindings(cell,
                                                                               new int[] { deadlySignature, pmsVirtualCell },
                                                                               new PMRole[] { PMRole.Pattern, PMRole.ChainColor1 })));

                        List <Cell> virtualGroup = finder.ActionIndexes
                                                   .Except(cellIndexes)
                                                   .Select(i => half2Line[i])
                                                   .ToList();

                        virtualGroup.ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine,
                                                                        GetPmFindings(cell, pmsVirtualGroup, PMRole.ChainColor1)));

                        List <Cell> deadlyCells = firstTwo.Union(half2).ToList();
                        patternCells = deadlyCells
                                       .Union(finder.ActionIndexes.Select(indexCell => half2Line[indexCell]))
                                       .ToList();

                        List <Cell> line = Board.GetLine(commonCoord, half2[0].GetCoordinate(commonCoord));
                        line
                        .Except(affectedCells)
                        .Except(half2)
                        .Except(virtualGroup)
                        .ToList()
                        .ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine));

                        csvAffected = CellsInCsvFormat(affectedCells);
                        csvPattern  = CellsInCsvFormat(patternCells);
                        csvHalf2    = CellsInCsvFormat(half2);
                        string csvDeadly       = CellsInCsvFormat(deadlyCells);
                        string csvValues       = PMsInCsvFormat(pmOtherMask.ListOfBits());
                        string csvPmVirtual    = PMsInCsvFormat(pmsVirtualCell.ListOfBits());
                        string commonCoordName = (commonCoord == Coord.ROW) ? "row" : "column";
                        string csvNakedGroup   = PMsInCsvFormat((pmOtherMask | pmsVirtualCell).ListOfBits());

                        Solution.Description = string.Format("Unique Rectangle Type 3: Cells {0} form a single " +
                                                             "virtual cell with pencilmarks {1}. A deadly pattern in cells {2} cannot take " +
                                                             "place.  One of values {1} has to be present in cells {0} (Naked rule applied " +
                                                             "using virtual cell for pencilmarks {3}) .  Options {5} can be removed from cells " +
                                                             "{6}.", csvHalf2, csvPmVirtual, csvDeadly, csvNakedGroup, commonCoordName,
                                                             csvValues, csvAffected);

                        return(true);
                    }while (false);  // builds a common exit point
                }

                // Last case: Unique Rectangle - Type 4
                // 2 cells have many more pencilmarks set. One of the extra values HAS to be
                // the solution for one of the cells.  Then the 4th cell cannot hold the other
                // value (of the deadly rectangle) or else a deadly pattern would form
                if (half2PencilmarkCount < 6)
                {
                    continue;
                }

                List <Cell> analysisCells = half2Line
                                            .Except(half2)
                                            .ToList();

                List <int> pmAnalysis = keySignature.ListOfBits();
                int        pmWork     = pmAnalysis.FirstOrDefault(pm => analysisCells.FirstOrDefault(
                                                                      cell => cell.IsPencilmarkSet(pm)) == null);

                if (pmWork == 0)
                {
                    continue;
                }

                Solution = new SolveInfo();
                int pmOther = pmAnalysis.FirstOrDefault(t => t != pmWork);
                affectedCells = half2.Where(cell => cell.IsPencilmarkSet(pmOther)).ToList();
                patternCells  = firstTwo.Union(half2).Except(affectedCells).ToList();
                pmOtherMask   = 1 << pmOther;
                int pmWorkMask = 1 << pmWork;

                affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                 GetPmFindings(cell,
                                                                               new int[] { pmOtherMask, pmWorkMask }, new PMRole[] { PMRole.Remove, PMRole.Pattern })));

                patternCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                GetPmFindings(cell, pmWorkMask | pmOtherMask, PMRole.Pattern)));

                lineIndex = half2[0].GetCoordinate(commonCoord);
                Board.GetLine(commonCoord, lineIndex)
                .Except(affectedCells)
                .ToList()
                .ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine));

                patternCells.AddRange(affectedCells);  // to build description
                csvAffected = CellsInCsvFormat(affectedCells);
                csvPattern  = CellsInCsvFormat(patternCells);
                csvHalf2    = CellsInCsvFormat(half2);
                string lineName = (commonCoord == Coord.ROW) ? "row" : "column";
                Solution.Description = string.Format("Unique Rectangle - Type 4: Either one of cells {0}" +
                                                     "must have value {1}.  If the other cell of the two had value {2}, the 4 cells {3} " +
                                                     "would form a deadly pattern.  Since this cannot happen, cell {4} cannot hold value {2}.",
                                                     csvHalf2, pmWork, pmOther, csvPattern, csvAffected, lineName);

                return(true);
            }

            return(false);
        }
        public override bool Solve(Circuit cir, BasicAnalysis ana)
        {
            List <Node> nodos = new List <Node>();

            CurrentAnalysis = ana as ComplexPlainAnalysis;
            CurrentCircuit  = cir;

            //List<Node> nodosnorton = new List<Node>();
            //List<Node> nodoscalculables = new List<Node>();
            //List<SpecialComponentInfo> especialcomponents;
            Voltages     = new Dictionary <Complex32, Dictionary <string, Complex32> >();
            Currents     = new Dictionary <Complex32, Dictionary <string, Complex32> >();
            WfromIndexes = new Dictionary <Tuple <int, int>, Complex32>();
            SolveInfo solveinfo = new SolveInfo();

            PreAnalizeToSolve(cir, nodos, solveinfo);


            ComplexPlainAnalysis analis = ana as ComplexPlainAnalysis;
            double w, sig, wi, wf, deltaw, deltasig, sigmamin, sigmamax;

            wi       = analis.WMin;
            wf       = analis.WMax;
            sigmamax = analis.SigmaMax;
            sigmamin = analis.SigmaMin;
            w        = wi;
            sig      = sigmamin;
            deltaw   = (wf - wi) / analis.Points;
            deltasig = (sigmamax - sigmamin) / analis.Points;

            Complex32 W = Complex32.Zero;

            for (int i = 0; i <= analis.Points; i++)
            {
                for (int j = 0; j <= analis.Points; j++)
                {
                    //Calculo de tensiones de nodos
                    W = new Complex32((float)(sigmamin + j * deltasig), (float)(wi + i * deltaw));
                    ACSweepSolver.Calculate(solveinfo, W);

                    //          Node    Voltage
                    Dictionary <string, Complex32> result = new Dictionary <string, Complex32>();

                    #region almacenamiento temporal

                    foreach (var nodo in nodos)
                    {
                        result.Add(nodo.Name, nodo.Voltage);
                    }
                    if (!Voltages.ContainsKey(W))
                    {
                        Voltages.Add(W, result);
                        WfromIndexes.Add(new Tuple <int, int>(i, j), W);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                    // Results[i,j] = new Tuple<Complex32,Complex32>(W,

                    #endregion

                    //calculo las corrientes:
                    CalculateCurrents(cir, W);
                    Dictionary <string, Complex32> currents = new Dictionary <string, Complex32>();
                    StorageCurrents(cir, currents);
                    Currents.Add(W, currents);
                }
            }
            cir.State = Circuit.CircuitState.Solved;

            return(true);
        }
Example #32
0
        public override bool FindPattern(GameBoard board)
        {
            Board = board;
            InitCellLineGroups();
            int dim = Board.Dimension;

            AllBoardCells = Board.GetAllLines(Coord.ROWS)
                            .SelectMany(t => t)
                            .ToList();

            var         colorizedCells = new List <Cell>();
            List <Cell> affectedCells  = null;

            for (int pm = 1; pm <= dim; pm++)
            {
                Board.ClearPMColorization();
                Logger.Clear();
                GetConjugateSegments(pm);

                while (CellGraph.Count > 0)
                {
                    #region Cleaning for loop 2 and over

                    colorizedCells = Board.GetAllColorizedCells();
                    Logger.WriteLine("Colorized cells are: {0}.", CellsInCsvFormat(colorizedCells, false));
                    StringBuilder finalDescription = new StringBuilder();

                    colorizedCells
                    .Where(cell => VisitedCells.Contains(cell))
                    .ToList()
                    .ForEach(cell => CellGraph.Remove(cell));

                    Logger.WriteLine("Removed colorized from CellGraph.  Remaining cells are {0}.",
                                     CellsInCsvFormat(CellGraph.Keys.ToList()));

                    Board.ClearPMColorization();
                    colorizedCells.Clear();
                    VisitedCells.Clear();

                    #endregion

                    ColorizeSegments(pm);
                    colorizedCells = Board.GetAllColorizedCells();

                    if (colorizedCells.Count < 4)
                    {
                        continue;
                    }

                    if (!MedusaOnly)
                    {
                        #region "Simple Coloring - Rule 2"

                        // Rule 2: If any 2 cell in the same unit have the same color, all such colored
                        // pencilmarks can be eliminated.
                        foreach (var colorValue in new[] { PMColor.COLOR1, PMColor.COLOR2 })
                        {
                            List <Cell> commonColorCells = colorizedCells
                                                           .Where(cell => cell.GetPencilmarkColor(pm) == colorValue)
                                                           .ToList();

                            for (int coord = Coord.ROWS; coord <= Coord.SECTIONS; coord++)
                            {
                                IGrouping <int, Cell> crowdedGroup = commonColorCells
                                                                     .GroupBy(cell => cell.GetCoordinate(coord))
                                                                     .FirstOrDefault(group => group.Count() > 1);

                                if (crowdedGroup != null)
                                {
                                    List <Cell> badColorCells  = commonColorCells;
                                    List <Cell> goodColorCells = colorizedCells
                                                                 .Except(badColorCells)
                                                                 .ToList();

                                    Solution = new SolveInfo();
                                    badColorCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                                     GetPmFindings(cell, 1 << pm, PMRole.ChainColor2))); // PMRole.Remove

                                    goodColorCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern2,
                                                                                      GetPmFindings(cell, 1 << pm, PMRole.Pattern)));

                                    string csvAffected = CellsInCsvFormat(badColorCells);
                                    Solution.Description = $"Simple Coloring - Type 1: All sets of cells " +
                                                           $"where a pencilmark appears twice in a row, column or box are found.  Then a " +
                                                           $"graph is made alternating colors.  Once done, any row, column or box having " +
                                                           $"2 or more cells of the same color indicate that the color cannot happen and  " +
                                                           $"should be removed.  Option {pm} will be removed for cells {csvAffected}.";

                                    return(true);
                                }
                            }
                        }

                        #endregion

                        #region "Simple Coloring - Rule 4"

                        // Rule 4:  If any cell in the board, not included in the graph can see
                        // 2 pencilmarks of the same color, then that cell can be removed.
                        do
                        {
                            List <IGrouping <PMColor, Cell> > groupsByColor =
                                colorizedCells.GroupBy(cell => cell.GetPencilmarkColor(pm))
                                .ToList();

                            if (groupsByColor.Count != 2)
                            {
                                continue;
                            }

                            List <Cell> color1Cells = groupsByColor[0].ToList();
                            List <Cell> color2Cells = groupsByColor[1].ToList();

                            affectedCells = AllBoardCells
                                            .Except(colorizedCells)
                                            .Where(cell => cell.IsPencilmarkSet(pm) &&
                                                   cell.GetShadowedCellsInList(color1Cells, pm).Any() &&
                                                   cell.GetShadowedCellsInList(color2Cells, pm).Any())
                                            .ToList();

                            if (affectedCells.Any())
                            {
                                int pmMask = 1 << pm;
                                Solution = new SolveInfo();
                                color1Cells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                               GetPmFindings(cell, pmMask, PMRole.ChainColor1)));

                                color2Cells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                               GetPmFindings(cell, pmMask, PMRole.ChainColor2)));

                                affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                                 GetPmFindings(cell, pmMask, PMRole.Remove)));

                                string csvAffected = CellsInCsvFormat(affectedCells);
                                string csvChain    = CellsInCsvFormat(colorizedCells.ToList(), false /*sorted*/);
                                Solution.Description = $"Simple Coloring - Type 2: Only 2 cells in a " +
                                                       $"housing with a pencilmark, form a segment.  All segments are joined in a graph, " +
                                                       $"and then cells are colored alternating color.  Any cell in the board which can " +
                                                       $"'see' cells of both colors can be eliminated as a valid option.   Cells {csvAffected} " +
                                                       $"can see cells of both colors in chain {csvChain}.  Pencilmark {pm} can be removed from them.";

                                return(true);
                            }
                        }while (false);

                        #endregion

                        continue;
                    }

                    #region "Medusa Coloring Rules"

                    bool medusaRuleFound = false;
                    ColorizeMedusa(pm);
                    do
                    {
                        #region Medusa - Rule 0: Contradiction found

                        Cell contradictionCell = colorizedCells.FirstOrDefault(cell => cell.ClashedPMColor != PMColor.NONE);
                        if (contradictionCell != null)
                        {
                            string csvCellContradiction = CellsInCsvFormat(contradictionCell);

                            finalDescription.AppendFormat("Medusa contradicted color rule: Following a path of alternating " +
                                                          "colors, led to cell {0} where pencilmark {1} would have both colors.  Therefore color " +
                                                          "{2} is not a solution and can be eliminated.\r\n", csvCellContradiction, contradictionCell.ClashedPM,
                                                          contradictionCell.ClashedPMColor);

                            FalseColorProcessing(colorizedCells, finalDescription, contradictionCell.ClashedPMColor);
                            medusaRuleFound = true;
                            break;
                        }

                        #endregion

                        #region Medusa - Rule 1: PM color twice in a cell

                        colorizedCells = Board.GetAllColorizedCells();
                        PMColor duplicateColor = PMColor.NONE;
                        Cell    dupColorCell   = colorizedCells
                                                 .FirstOrDefault(cell => (duplicateColor = cell.DuplicatePMColor) != PMColor.NONE);

                        if (dupColorCell != null)
                        {
                            List <int> listOfColorPMs = dupColorCell.ListOfColorizedPencilmarks();
                            string     csvColorPMs    = PMsInCsvFormat(listOfColorPMs);
                            string     csvDupCell     = CellsInCsvFormat(dupColorCell);
                            finalDescription.AppendFormat("Rule 1: Cell {0} has pencilmarks {1}, both with color {2}, so the color " +
                                                          "can be eliminated as possible solution in the board.", csvDupCell, csvColorPMs, duplicateColor);

                            FalseColorProcessing(colorizedCells, finalDescription, duplicateColor);
                            medusaRuleFound = true;
                            break;
                        }

                        #endregion

                        #region Medusa - Rule 2: PMs with same value and same color in the same house

                        int len = colorizedCells.Count;
                        for (int iCell = 0; !medusaRuleFound && iCell < len; iCell++)
                        {
                            Cell       colorCell = colorizedCells[iCell];
                            List <int> colorPMs  = colorCell.ListOfColorizedPencilmarks();
                            for (int iCell2 = iCell + 1; !medusaRuleFound && iCell2 < len; iCell2++)
                            {
                                Cell colorCell2 = colorizedCells[iCell2];
                                if (!colorCell2.CanSee(colorCell))
                                {
                                    continue;
                                }

                                foreach (int singleColorPM in colorPMs)
                                {
                                    PMColor pm1Color = colorCell.GetPencilmarkColor(singleColorPM);
                                    PMColor pm2Color = colorCell2.GetPencilmarkColor(singleColorPM);
                                    if (!colorCell2.IsPencilmarkColorized(singleColorPM) ||
                                        pm2Color != colorCell.GetPencilmarkColor(singleColorPM))
                                    {
                                        continue;
                                    }

                                    string csvColorCell    = CellsInCsvFormat(colorCell);
                                    string csvColorCell2   = CellsInCsvFormat(colorCell2);
                                    string commonCoordName = null;
                                    if (colorCell.RowIndex == colorCell2.RowIndex)
                                    {
                                        commonCoordName = "row";
                                    }
                                    else if (colorCell.ColIndex == colorCell2.ColIndex)
                                    {
                                        commonCoordName = "column";
                                    }
                                    else
                                    {
                                        commonCoordName = "box";
                                    }

                                    finalDescription.AppendFormat("Rule 2: Pencilmark {0} has color {1} in cell {2} and also in cell " +
                                                                  "{3}.  The number can only appear once in the {4}.  Therefore this color is the \"false\" color.",
                                                                  singleColorPM, pm1Color, csvColorCell, csvColorCell2, commonCoordName);

                                    FalseColorProcessing(colorizedCells, finalDescription, pm2Color);
                                    medusaRuleFound = true;
                                    break;
                                }
                            }
                        }

                        if (medusaRuleFound)
                        {
                            break;
                        }

                        #endregion

                        #region Medusa - Rule 3: Extra pencilmarks in 2 color cells

                        List <Cell> extraPMCells = colorizedCells
                                                   .Where(cell => cell.PencilMarkCount > 2 && cell.ColorizedPencilmarkCount == 2)
                                                   .ToList();

                        if (extraPMCells.Count > 0)
                        {
                            extraPMCells.ForEach(cell => cell.MarkPencilmarksForRemoval(
                                                     cell.PMUncolorizedSignature
                                                     .ListOfBits()
                                                     .ToArray()));

                            string csvExtraPMs = CellsInCsvFormat(extraPMCells);
                            finalDescription.AppendFormat("Rule 3: Cells {0} include pencilmarks with both colors. Therefore " +
                                                          "Any other pencilmark in these cells can be removed.\r\n", csvExtraPMs);

                            medusaRuleFound = true;
                        }

                        #endregion

                        #region Medusa - Rule 4: Uncolorized pm shadowed by 2 pm's of different colors

                        var Color1CellsByPM = new Dictionary <int, List <Cell> >();
                        var Color2CellsByPM = new Dictionary <int, List <Cell> >();

                        foreach (Cell cell in colorizedCells)
                        {
                            foreach (int colorizedPM in cell.ListOfColorizedPencilmarks())
                            {
                                PMColor pmColor = cell.GetPencilmarkColor(colorizedPM);
                                Dictionary <int, List <Cell> > workDictionary = (pmColor == PMColor.COLOR1) ? Color1CellsByPM : Color2CellsByPM;
                                if (!workDictionary.ContainsKey(colorizedPM))
                                {
                                    workDictionary.Add(colorizedPM, new List <Cell>());
                                }

                                workDictionary[colorizedPM].Add(cell);
                            }
                        }

                        List <int> searchPMs = Color1CellsByPM.Keys.Intersect(Color2CellsByPM.Keys).ToList();
                        affectedCells = new List <Cell>();
                        foreach (int singleSearchPM in searchPMs)
                        {
                            List <Cell> cellsWithPMColor1 = Color1CellsByPM[singleSearchPM];
                            List <Cell> cellsWithPMColor2 = Color2CellsByPM[singleSearchPM];
                            bool        firstItemFound    = false;
                            foreach (Cell cell1 in cellsWithPMColor1)
                            {
                                foreach (Cell cell2 in cellsWithPMColor2)
                                {
                                    if (cell1.CanSee(cell2))
                                    {
                                        continue;
                                    }

                                    List <Cell> solutionCells = cell1.ShadowedCells
                                                                .Intersect(cell2.ShadowedCells)
                                                                .Where(cell => cell.IsPencilmarkSet(singleSearchPM) &&
                                                                       cell.GetPencilmarkColor(singleSearchPM) == PMColor.NONE)
                                                                .ToList();

                                    solutionCells.ForEach(cell => cell.MarkPencilmarksForRemoval(singleSearchPM));
                                    affectedCells.AddRange(solutionCells);

                                    if (solutionCells.Count > 0)
                                    {
                                        if (!firstItemFound)
                                        {
                                            finalDescription.AppendFormat("Rule 4: When a pencilmark is shadowed by 2 colorized " +
                                                                          "pencilmarks in 2 different colors and the same value, the pencilmark is not a solution " +
                                                                          "for the cell.");

                                            firstItemFound  = true;
                                            medusaRuleFound = true;
                                        }

                                        solutionCells.ForEach(cell => finalDescription.AppendFormat("Remove pencilmark {0} from cell {1};",
                                                                                                    singleSearchPM, CellsInCsvFormat(cell)));
                                    }
                                }
                            }
                        }

                        if (affectedCells.Count > 0)
                        {
                            finalDescription.Append("\r\n");
                        }

                        #endregion

                        #region Medusa - Rule 5: Non-Colorized PM sharing colorizedPM in cell can see same value colorizedPM somewhere else

                        // The rule goes like this:  There are 2 candidates in a cell: cA and cB. cB has been colorized "Blue".
                        // If cA can see another cA value PM with color "Green" somewhere else, then cA can be eliminated in the
                        // original cell.  Example:  Cell [5,5] has blue pencilmark for "7", and no color pencilmark "1".   Cell [5,6]
                        // has a green pencilmark "1".  If "Green" is true, then [5, 6] will have a "1" and [5, 5] cannot be "1".
                        // If "blue" is true, then [5, 5] will be "7" filling the value for the cell.   Either way, "1" cannot be an option
                        // for cell [5,5]

                        List <Cell> rule5Candidates = colorizedCells
                                                      .Where(cell => cell.ColorizedPencilmarkCount == 1 && cell.PencilMarkCount >= 2)
                                                      .ToList();

                        affectedCells.Clear();
                        foreach (Cell cand5Cell in rule5Candidates)
                        {
                            PMColor    cellPMColor   = cand5Cell.GetColorOfOnlyColorizedPM();
                            PMColor    searchedColor = cellPMColor.ToggleColor();
                            List <int> noColorPMs    = cand5Cell.PMSignature
                                                       .ListOfBits()
                                                       .Except(cand5Cell.ListOfColorizedPencilmarks())
                                                       .ToList();

                            List <Cell> cellScope = cand5Cell.ShadowedCells.ToList();
                            foreach (int singlePM in noColorPMs)
                            {
                                List <Cell> rule5Cells = cellScope.Where(cell => cell.IsPencilmarkSet(singlePM) &&
                                                                         cell.GetPencilmarkColor(singlePM) == searchedColor)
                                                         .ToList();

                                if (rule5Cells.Count > 0)
                                {
                                    string csvRule5Cells      = CellsInCsvFormat(rule5Cells);
                                    string csvCand5Cell       = CellsInCsvFormat(cand5Cell);
                                    int    colorPMInCand5Cell = cand5Cell.GetPMsWithColor(cellPMColor)[0];
                                    string cellForm           = (rule5Cells.Count > 1) ? "Cells" : "Cell";
                                    string verbForm           = (rule5Cells.Count > 1) ? "have" : "has";

                                    cand5Cell.MarkPencilmarksForRemoval(singlePM);
                                    finalDescription.AppendFormat("Rule 5: {6} {0} {7} pencilmark {1} colorized with {2}. " +
                                                                  "Cell {4} has pencilmark {1} with no color, and pencilmark {5} with color {3}. " +
                                                                  "Therefore, {1} cannot be a solution for cell {4}.\r\n",
                                                                  csvRule5Cells, singlePM, searchedColor, cellPMColor, csvCand5Cell, colorPMInCand5Cell,
                                                                  cellForm, verbForm);

                                    medusaRuleFound = true;
                                }
                            }
                        }
                        #endregion

                        #region Medusa - Rule 6: Cell Emptied by color. All non colored cells see same PM in one color

                        // Rule 6 works like this:   A cell with only non-colorized pencilmarks, where all pencilmarks see pencilmarks
                        // in the same color.  Then, that color is false, or else the cell would be empty.   Example:  Non-colorized
                        // cell has pencilmarks 1, 2, 5.  Cell 1 sees a yellow 1.  2 sees a yellow 2, and 5 sees a yellow 5.  If
                        // yellow assumption was true, then there would be no possible solution for the cell.   Therefore yellow has
                        // to be the "false" color.

                        List <Cell> nonColorizedCells = AllBoardCells
                                                        .Where(cell => cell.Value == 0 && cell.ColorizedPencilmarkCount == 0)
                                                        .ToList();

                        bool foundRule6Case = false;
                        foreach (Cell nonColorCell in nonColorizedCells)
                        {
                            List <int>  nonColorPMList = nonColorCell.PMSignature.ListOfBits();
                            List <Cell> shadowedCells  = nonColorCell.ShadowedCells;
                            bool        complies       = true;
                            foreach (PMColor testColor in new[] { PMColor.COLOR1, PMColor.COLOR2 })
                            {
                                complies = true;
                                foreach (int nonColorPM in nonColorPMList)
                                {
                                    List <Cell> SameColorSamePMList = shadowedCells.Where(cell => cell.IsPencilmarkColorized(nonColorPM) &&
                                                                                          cell.GetPencilmarkColor(nonColorPM) == testColor)
                                                                      .ToList();

                                    if (SameColorSamePMList.Count > 0)
                                    {
                                        continue;
                                    }

                                    complies = false;
                                    break;
                                }

                                if (complies)  // testColor is false
                                {
                                    finalDescription.AppendFormat("Rule 6: Cell {0} has pencilmark(s) {1}, all of which can see " +
                                                                  "a pencilmark with the same value colorized {2}.  This color has to be \"false\" or else the " +
                                                                  " cell would be empty.", CellsInCsvFormat(nonColorCell), PMsInCsvFormat(nonColorPMList),
                                                                  testColor);

                                    FalseColorProcessing(colorizedCells, finalDescription, testColor);
                                    foundRule6Case  = true;
                                    medusaRuleFound = true;
                                    break;
                                }
                            }

                            if (foundRule6Case)
                            {
                                break;
                            }
                        }

                        #endregion
                    } while (false);

                    if (medusaRuleFound)
                    {
                        Solution             = new SolveInfo();
                        Solution.Description = $"3D Medussa Rules\r\n{finalDescription.ToString()}";
                        foreach (Cell cell in colorizedCells)
                        {
                            var pmFindings = new List <PMFinding>();
                            cell.ListOfColorizedPencilmarks()
                            .ForEach(colorPM => pmFindings.Add(
                                         new PMFinding(colorPM, (cell.GetPencilmarkColor(colorPM) == PMColor.COLOR1) ?
                                                       PMRole.ChainColor1 : PMRole.ChainColor2)));

                            cell.ListOfPMsForRemoval.ForEach(removePM => pmFindings.Add(
                                                                 new PMFinding(removePM, PMRole.Remove)));

                            CellRole cellRole = CellRole.Pattern;
                            if (cell.IsPencilmarkColorized(pm) && cell.GetPencilmarkColor(pm) == PMColor.COLOR1)
                            {
                                cellRole = CellRole.Pattern2;
                            }

                            Solution.AddAction(cell, cellRole, pmFindings.ToArray());
                        }

                        AllBoardCells
                        .Except(colorizedCells)
                        .Where(cell => cell.HasPencilmarksMarkedForRemoval)
                        .ToList()
                        .ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                            GetPmFindings(cell, cell.ListOfPMsForRemoval.ToBitMask(), PMRole.Remove)));

                        return(true);
                    }

                    #endregion
                }
            }

            return(false);
        }
Example #33
0
        public bool IsPathWithRemotePair(List <Cell> path)
        {
            var orderedPath = path.Take(1).ToList();

            path.RemoveAt(0);
            Cell        lastCell      = orderedPath[0];
            Cell        firstCell     = lastCell;
            List <Cell> affectedCells = null;
            bool        solved        = false;
            int         pmMask        = firstCell.PMSignature;

            while (path.Count > 0)
            {
                Cell nextCell = path.FirstOrDefault(t => lastCell.ShadowedCells.Contains(t));
                if (nextCell == null)
                {
                    return(false);
                }

                lastCell = nextCell;
                orderedPath.Add(nextCell);
                path.Remove(nextCell);
                if ((orderedPath.Count & 0x01) == 0x01)
                {
                    continue;
                }

                affectedCells = firstCell
                                .ShadowedCells
                                .Intersect(lastCell.ShadowedCells)
                                .Where(t => (t.PMSignature & pmMask) != 0)
                                .ToList();

                if (affectedCells.Count == 0)
                {
                    continue;
                }

                solved = true;
                break;
            }

            if (solved)
            {
                Solution = new SolveInfo();
                PMRole[]   chainRoles = new[] { PMRole.ChainColor1, PMRole.ChainColor2 };
                int        linkIndex  = 0;
                List <int> optionPair = pmMask.ListOfBits();
                foreach (Cell pathCell in orderedPath)
                {
                    Solution.AddAction(pathCell, CellRole.Pattern,
                                       new PMFinding(optionPair[0], chainRoles[linkIndex]),
                                       new PMFinding(optionPair[1], chainRoles[linkIndex]));

                    linkIndex = 1 - linkIndex;
                }

                affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                 GetPmFindings(cell, pmMask, PMRole.Remove)));

                string csvCells    = CellsInCsvFormat(orderedPath, false);
                string csvAffected = CellsInCsvFormat(affectedCells);
                Solution.Description = $"Remote Pair Rule: cells {csvCells} can only have values " +
                                       $"{optionPair[0]} or {optionPair[1]} and form a chain with " +
                                       $"an even number of cells.  Therefore the first and last cells in the chain will " +
                                       $"contain both values, and cells csvAffected (seen by these 2) could not possible have any " +
                                       $"of the 2 values.";
            }

            return(solved);
        }
Example #34
0
        public override bool FindPattern(GameBoard board)
        {
            Board    = board;
            AllCells = Board.GetAllLines(Coord.ROWS).SelectMany(t => t).ToList();
            for (int coord = Coord.ROWS; coord <= Coord.COLUMNS; coord++)
            {
                int secCoord = 1 - coord;
                for (int iValue = 1; iValue <= Board.Dimension; iValue++)
                {
                    int count;

                    // IGrouping.  Key is main coordinate, list is list of 2nd coordinates
                    List <IGrouping <int, int> > lineInfo = AllCells
                                                            .Where(cell => cell.IsPencilmarkSet(iValue))
                                                            .GroupBy(cell => cell.GetCoordinate(coord), cell => cell.GetCoordinate(secCoord))
                                                            .Where(g => (count = g.Count()) >= 2 && count <= MaxCellsPerLine)
                                                            .ToList();

                    if (lineInfo.Count < FishSize)
                    {
                        continue;
                    }

                    var selectedLines    = new List <int>();
                    var selectedSecLines = new List <int>();
                    var selectedFinCells = new List <int[]>();
                    var fishCells        = new List <Cell>();
                    if (SelectFish(lineInfo, secCoord, 0 /*start*/, iValue,
                                   selectedLines, selectedSecLines, selectedFinCells, fishCells))
                    {
                        int pmMask = 1 << affectedPencilmark;

                        Solution = new SolveInfo();
                        affectedCells.ForEach(cell => Solution.AddAction(cell, CellRole.Affected,
                                                                         GetPmFindings(cell, pmMask, PMRole.Remove)));

                        patternCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                                        GetPmFindings(cell, pmMask, PMRole.Pattern)));

                        if (FinCells == null)
                        {
                            FinCells = new List <Cell>();
                        }

                        FinCells.ForEach(cell => Solution.AddAction(cell, CellRole.Pattern2,
                                                                    GetPmFindings(cell, pmMask, PMRole.Pattern)));

                        List <int> involvedLineIndexes = patternCells
                                                         .Select(cell => cell.GetCoordinate(coord))
                                                         .Distinct()
                                                         .ToList();


                        involvedLineIndexes
                        .Select(index => Board.GetLine(coord, index))
                        .SelectMany(t => t)
                        .Except(patternCells)
                        .Except(FinCells)
                        .ToList()
                        .ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine));

                        string csvCells = CellsInCsvFormat(patternCells);
                        Solution.Description = string.Format("{0}{1} on {2} for pencilmark {4}  Cells involved: {3}.",
                                                             Finned ? "Finned " : (Sashimi ? "Sashimi " : string.Empty),
                                                             FishNames[FishSize - 2],
                                                             coord == Coord.ROWS ? "rows" : "columns",
                                                             csvCells,
                                                             iValue);

                        return(true);
                    }
                }
            }

            return(false);
        }
        protected static void Calculate(SolveInfo solveinfo, Complex32 W)
        {

            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
                return;

             //existen nodos donde la tension se puede calcular directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is ACVoltageGenerator))
                        {
                            nodo.Voltage = compo.voltage(nodo, W);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Calculo de tensions mediante matrices

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0, max;
                //cada componente especial agrega 0, 1 o 2 variable mas, dependiendo del tipo
                max = solveinfo.MatrixDimension;
                var v = Vector<Complex32>.Build.Dense(max);
                var A = Matrix<Complex32>.Build.DenseOfArray(new Complex32[max, max]);

                //primero la ecuacion de transferencia del VcV
                foreach (var info in solveinfo.specialcomponents)
                {
                    //foreach (var item in info.Component)
                    //{
                        
                    //}
                    //int entrada = especialcomponents.IndexOf(info);
                    //fila = nodosnorton.Count - 1 + entrada;
                    columna = 1;
                    A[fila, columna] = 1;


                }

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    Complex32 Z, V;
                    if (
                        nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.VoltageFixedNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is PasiveComponent)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                    V = ((Branch)rama).NortonCurrent(nodo, W);
                                else
                                    V = rama.Current(nodo, W);
                                
                                v[fila] += V;
                                Z = rama.Impedance(W);
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference)
                                {
                                    columna = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator)
                            {
                                V = rama.Current(nodo, W);
                                v[fila] += V;
                            }
                            else if (rama is VoltageControlledGenerator)
                            {
                                //int entrada = especialcomponents.Values.ToList().IndexOf(rama);
                                //columna = nodosnorton.Count -1 + entrada;

                                ////un nodo es positva la corriente, en el otro es negativa 
                                //if (entrada % 2 == 0)
                                //    A[fila, columna] = 1;
                                //else
                                //    A[fila, columna] = -1;
                                
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator))
                            compo = nodo.Components[1];
                        v[fila] = compo.Voltage.Real;
                        A[fila, columna] = 1;
                        columna = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    //else if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                    //{
                    //    foreach (var rama in nodo.Components)
                    //    {
                    //        if (rama is VoltageControlledGenerator)
                    //        {

                    //        }
                    //    }
                    //}
                    else
                        throw new NotImplementedException();
                }
                var x = A.Solve(v);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = x[fila];
                }
            }

            #endregion

            //existen nodos donde la tension se puede calcular indirectamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node nodo1 = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    Complex32 v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = Complex32.Zero;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo, 
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, W, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, W, ref v2, ref z2);
                    nodo.Voltage = (z2 * v1 + v2 * z1) / (z1 + z2);
                }
            }


        }
        public override bool FindPattern(GameBoard board)
        {
            // The algorithm is the same for finding naked or hidden values.  For naked:
            // an array of integers where each integer is a set of bits for the pencilmarks.
            // (e.g. 01 0110 0010 == 0x162 which mean pencilmark 1, 5, 6, and 8 are set.  The
            // LSB is position 0), and the index in the array is a cell position in the line.
            // For Hidden:  Swap the meaning: The bits are the positions in the line and the
            // index is the pencilmark.
            // Start from the beginning in the array.   Its content is a cumulative mask.
            // If the cumulative mask has more than the goal bits, it is thrown away and the
            // next one is considered.   If N bits are found in a mask using N entries in the
            // array, then there are N of N which is what is being searched for.   Once found,
            // a "final approval method" is invoked to check if the set is good.  The approval
            // is determined to be good if there are pencilmarks to turn off. (for naked, in
            // other positions in the line.  for hidden: more pencilmarks in the same cells
            // (other than the N found (e.g. found 1,2,3 but cell also has 2,7 which can be
            // turned off.  Since there is a large number of combinations the best approach
            // to try promising ones and discard useless ones quickly is to use recursion.
            // Since a board has a small number of cells (9 or so) the recursion depth is not
            // an issue.

            Board = board;
            for (int coord = Coord.ROWS; coord <= Coord.SECTIONS; coord++)
            {
                List <List <Cell> > allLines = Board.GetAllLines(coord);
                foreach (List <Cell> line in allLines)
                {
                    var hiddenFinder = new NakedHiddenFinder();
                    int dim          = line.Count + 1;
                    hiddenFinder.MapBits   = CreateMapBits(line);
                    hiddenFinder.MapLength = hiddenFinder.MapBits.Count;

                    // Step 2:  Search for N of N values
                    int maxGoal = hiddenFinder.MapBits.Count(t => t != 0);
                    if (maxGoal == 0)
                    {
                        continue;
                    }

                    int goal = 1;
                    for (; goal < maxGoal; goal++)
                    {
                        if (hiddenFinder.Search(goal))
                        {
                            break;
                        }
                    }

                    // Finally set the information as related to cells, and information
                    if (goal == maxGoal)
                    {
                        continue;
                    }

                    LineCoordinate = coord;
                    int        indexLine    = line[0].GetCoordinate(LineCoordinate);
                    List <int> locationList = GetLocationList(hiddenFinder);
                    patternCells = locationList.Select(i => line[i]).ToList();

                    PencilmarkList = GetPencilmarkList(hiddenFinder);
                    Solution       = new SolveInfo();
                    int pmMask = GetPencilmarkMask();

                    int patternPMs = 0;
                    patternCells.ForEach(cell => patternPMs |= cell.PMSignature);

                    locationList
                    .Select(loc => line[loc])
                    .ToList()
                    .ForEach(cell => Solution.AddAction(cell, CellRole.Pattern,
                                                        GetPmFindings(cell, patternPMs, PMRole.Pattern)));

                    List <int> solutionPMs = pmMask.ListOfBits();
                    CalculateAffectedCells(line);
                    affectedCells.ForEach(affCell =>
                                          Solution.AddAction(affCell, AffectedCellRole,
                                                             GetPmFindings(affCell,
                                                                           new int[] { pmMask, patternPMs },
                                                                           new PMRole[] { PMRole.Remove, PMRole.Pattern })));

                    line
                    .Except(patternCells)
                    .Except(affectedCells)
                    .ToList()
                    .ForEach(cell => Solution.AddAction(cell, CellRole.InvolvedLine));

                    CreateRuleInformation();
                    return(true);
                }
            }

            return(false);
        }