/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// 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); }
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); }
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); } } }
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); }
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); }
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); } }
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()); }
public bool hasAnotherSolution() { try { result = engine.solveNext(); return(result.isSuccess()); } catch (PrologException e) { return(false); } }
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); }
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); } } } }
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; }
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) //{ //} } }
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); }
/* Meters */ public bool hasSolution() { result = engine.solve(this.query); return(result.isSuccess()); }
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); } } }
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); }
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); }
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); }
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); }