public IEnumerable <UBasCov2> IEGet_BaseSet(int sz, int rnk) //### BaseSet generator { if (GLK_UList_All.Count < sz * 2 + rnk) { yield break; } BSstatus2 = new BaseSet_Status2(sz, rnk); //Marking method // #1:Focus on the link(LK0) and follow the connecting links. A link of size(sz) is a candidate for BaseSet/CoverSet. // (This alone won't make it faster.) // #2:Select BaseSet from the candidates and check suitability. // Excludes generation G1 links. // #3:Also select the CoverSet from the candidates. At least common elements with baseset are required. // Light selection and aptitude testing. // Efficient evaluation of aptitude of baseSet is important. // #4:If there is no solution for the candidate starting from LK0, record LK0 in the invalid list. // #2':Select BaseSet from the candidates, exclude links in the invalid list. Bit324 invalidLink = new Bit324(); foreach (var LK0 in GLK_UList_All) //#1 LK0:First link { _chkX1 = false; _chkX2 = false; // if( SDK_Ctrl.UGPMan.stageNo>=12 && sz>=3 ){//&& rnk==1){ // _chkX1=false; _chkX2=true; // if(LK0.ToAppearance()=="r4#2"){ // WriteLine($"--->{LK0.ToAppearance()}"); // _chkX1=false; _chkX2=true; // } // } if (_chkX1) { WriteLine($"\r-1- baseset sz:{sz} rnk:{rnk} first:{LK0} -"); } GLK_UList_Marked.Clear(); QueueGlk.Clear(); rcnGenNo = new int[9, 81]; //### gen ### BasCovCandidates = new Bit324(); #region ----- marking for LK0 ------------------------- BasCovCandidates.BPSet(LK0.IDsq); //1)BC_Set 候補のリスト ## 初のリンク(LK0)の登録 LK0._gen = 1; foreach (var NDx in LK0.ConnectLinks) //LK0の他端ノードNDx に着目 { var(rc, no) = (NDx >> 4, NDx & 0xF); // (rc,no) <-- NDx rcnGenNo[no, rc] = 1; //### gen ### //NDXの世代<-1 set rcnGenNo QueueGlk.Enqueue(NDx); //Enqueue(ND1) if (_chkX1) { WriteLine($"@{_jkc_++} -1.5- Enqueue {rc.ToRCString()}#{no+1}"); } } //==== sz>=2 ==== while (QueueGlk.Count > 0) { var ND2 = QueueGlk.Dequeue(); var(rc, no) = (ND2 >> 4, ND2 & 0xF); int gen = rcnGenNo[no, rc]; //### gen ### if (_chkX1) { WriteLine($"@{_jkc_++} -2- Dequeue {rc.ToRCString()}#{no+1}-G{gen}"); } if (gen > sz) { continue; } foreach (var LKpair in GLK_connection[rc, no]) { var(no2, rc2) = (LKpair.no2, LKpair.rc2); var gen2 = rcnGenNo[no2, rc2]; //### gen ### UGLink_unit LKx = LKpair.objUGL; LKx._gen = gen; bool hit = BasCovCandidates.IsHit(LKx.IDsq); BasCovCandidates.BPSet(LKx.IDsq); //1)BC_Set 候補のリスト ビット表現で重複を回避 if (_chkX1) { string st3 = $"@{_jkc_++} -2.5- Link set {LKx} {(hit? "---": "New")}"; WriteLine(st3); } if (gen2 == 0) { rcnGenNo[no2, rc2] = gen + 1; //### gen ### if (gen < sz) { QueueGlk.Enqueue(LKpair.rcno); if (_chkX1) { string st3 = $"@{_jkc_++} -3- Enqueue {rc2.ToRCString()}#{no2+1}-G{gen+1}"; st3 += " " + LKx.ToString(); WriteLine(st3); } } } } } GLK_UList_Marked.Add(LK0); //First is LK0. BasCovCandidates.BPReset(LK0.IDsq); //reset LK0. foreach (var LX in BasCovCandidates.IEGet_Index().Select(kx => GLK_UList_All[kx])) { GLK_UList_Marked.Add(LX); } if (_chkX2) { string stBC = $"\r@{_jkc_++} BasCovCandidates({GLK_UList_Marked.Count}) :"; GLK_UList_Marked.ForEach(LK => stBC += $" {LK.ToAppearance(Gen:true)}"); //#### debug print WriteLine(stBC); } if (GLK_UList_Marked.Count < sz) { continue; } #endregion ----- marking ------------------------- #region ----- selecte ------------------------- var GLK_UList_Sel = new List <UGLink_unit>(); Combination cmbBas = new Combination(GLK_UList_Marked.Count, sz); string st, stw = ""; int nxt = int.MaxValue; //(skip function) string stT = ""; while (cmbBas.Successor(nxt)) { nxt = int.MaxValue; if (cmbBas.Index[0] != 0) { continue; //"The first link is fixed at 0!" } GeneralLogicGen2.ChkBas0++; //***** var usedLKIDsq = new Bit324(); var BaseSetLst = new List <UGLink_unit>(); var HB981 = new Bit981(); //BaseSet bitPattern long RCBN_frameA = 0; int[] RCB_frameB9 = new int[9]; foreach (var(kx, elementX) in cmbBas.IEGetIndex2()) { nxt = kx; var UGL = GLK_UList_Marked[elementX]; if (kx >= 1 && UGL._gen == 1) { goto LnxtCombination; // (#2) excludes generation G1 links. } if (invalidLink.IsHit(UGL.IDsq)) { goto LnxtCombination; // (#2')exclude links in the invalid list. } usedLKIDsq.BPSet(UGL.IDsq); BaseSetLst.Add(UGL); foreach (var P in UGL.ConnectLinks) { int no2 = P & 0xF, rc2 = P >> 4; if (HB981.IsHit(no2, rc2)) { goto LnxtCombination; // BaseSet links do not overlap. } HB981.BPSet(no2, rc2); } long RCBN_frameB = UGL.RCBN_frameB; //bit expression of [ UC.FreeB<<27 | 1<<(UC.b+18)) | 1<<(UC.c+9) | (1<<UC.r) ] int freebX = (int)(RCBN_frameB >> 27); foreach (var no in freebX.IEGet_BtoNo()) { RCB_frameB9[no] |= (int)(RCBN_frameB & 0x7FFFFFF); } RCBN_frameA |= UGL.RCBN_frameB; //bit expression of rcb if (kx > 0) { if (!Check_rcbnCondition(sz, rnk, elementX, RCBN_frameA)) { goto LnxtCombination; //(### extremely efficient) ???? } } } if (!Check_rcbnCondition(sz, rnk, 0, RCBN_frameA)) { goto LnxtCombination; //Evaluate BaseSet pattern. Extremely efficient. } if (sz >= 2) { BSstatus2.Prepare(usedLKIDsq, BaseSetLst, HB981, RCB_frameB9); //check 421 52.1sec //check 124 53.6sec if (!BSstatus2.Check_4()) { goto LnxtCombination; //Each element of LK0 is associated with the rest of the links. } if (!BSstatus2.Check_2()) { goto LnxtCombination; //Each cell(A) is in a position to link with other cells. } if (!BSstatus2.Check_1()) { goto LnxtCombination; //A and B are not linked by other link(C). } // if( !BSstatus2.Check_3() ) goto LnxtCombination; //There is a limit to the number of cells that have no links other than BaseSet. // Check_1 and _3 are almost the same evaluation. Check_3 is a heavy process. // if( !BSstatus2.Check_5() ) goto LnxtCombination; //XXX Almost no effect. Check_1-4 has been determined. } var BasCov = new UBasCov2(usedLKIDsq, BaseSetLst, HB981, sz); if (_chkX2) { string st2 = $"\r{_jkc_++} BaseSet:"; BaseSetLst.ForEach(P => st2 += " " + P.ToAppearance()); // WriteLine(st2); WriteLine($"Check_5---->{st2}"); //################### } yield return(BasCov); LnxtCombination: continue; } //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* invalidLink.BPSet(LK0.IDsq); //#4:If there is no solution for the candidate starting from LK0, record LK0 in the invalid list. //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* #endregion ----- selecte ------------------------- } yield break; }
//1..4....8.9.1...5.....63.....13.5.79..3...8..76.2.94.....75.....1...6.4.8....4..2 public IEnumerable <UBasCov2> IEGet_CoverSet(UBasCov2 BasCov, int rnk) //### CoverSet generator { if (GLK_UList_All == null) { yield break; } int sz = BasCov.sz; if (GLK_UList_Marked.Count < sz) { yield break; } var BaseSetLst = BasCov.BaseSetLst; var usedLKIDsq = BasCov.usedLKIDsq; //used links var HB981 = BasCov.HB981; //BaseSet bit expression int noBit = HB981.noBit; //bit expression of digits containing cell elements var UGLCovCandidates = new List <UGLink_unit>(); // UGLCovCandidates:candidate link #region Preparation(Create UGLCovCandidates) //Preparation: select candidates for CoverSet.(this process is extremely effective!) // 1)First select BaseSet, then select CoverSet to cover. // 2)CoverSet requirements: // .Exclude links that do not contain BaseSet elements // .Rank=0 includes two or more elements of BaseSet // .Rank>0 contains one or more elements of BaseSet Bit81 Bcmp = HB981.CompressToHitCells(); //x long RCBN_frameBex = BaseSetLst.Aggregate((long)0,(p,q)=>p|q.RCBN_frameBex); foreach (var P in GLK_UList_Marked) //Exclude Baseset links //x if((RCBN_frameBex&P.RCBN_frameB) == 0) continue; { if (BaseSetLst.Contains(P)) { continue; } if (P.type == 0) // 0:link { if ((noBit & (1 << P.no)) == 0) { continue; //Exclude links with digits not included in BaseSet. } int Bcount = (HB981._BQ[P.no] & P.rcBit81).BitCount(); //Bcount : Number of cells in common with BaseSet. if (Bcount == 0) { continue; //Link without common parts is excluded from candidate links. } if (rnk == 0 && Bcount < 2) { continue; //if rank=0, the CoverSet has two or more common items } UGLCovCandidates.Add(P); } else // 1:cell { if (noBit.BitCount() <= 1) { continue; //For links within a cell, the Coverset digits must be 2 or more. } if ((noBit & P.FreeB) == 0) { continue; //Exclude links with digits not included in BaseSet. } int B = noBit & P.FreeB; //Common digits of BaseSet and link if (B == 0) { continue; //Link without common parts are excluded from candidate links. } int rc = P.rc; //focused cell int kcc = 0, kccLim = (rnk == 0)? 2:1; foreach (var no in B.IEGet_BtoNo()) //no:Candidate digit of forcused cell. { if (!HB981._BQ[no].IsHit(rc)) { continue; //do not check if BaseSet does not include no. } if (++kcc >= kccLim) { UGLCovCandidates.Add(P); break; } //number of digits contained in BaseSet satisfies the condition(kccLim). } } } if (_chkX2) { string st2 = $"{_jkc_++} UGLCovCandidates for CoverSet:"; st2 = UGLCovCandidates.Aggregate(st2, (p, q) => p + " " + q.ToAppearance());//#### debug print WriteLine(st2); } #endregion Preparation(Create UGLCovCandidates) #region CoverSet generator if (UGLCovCandidates.Count < sz + rnk) { yield break; } Bit981 HC981 = new Bit981(); //CoverSet Bit981 Can981 = new Bit981(); //Items that break "Locked"(excludable candidates) Combination cmbCvr = new Combination(UGLCovCandidates.Count, sz + rnk); int nxt = int.MaxValue; while (cmbCvr.Successor(nxt)) //Combination one-element generator { ++GeneralLogicGen2.ChkCov1; HC981.Clear(); Array.ForEach(cmbCvr.Index, m => HC981 |= UGLCovCandidates[m].rcnBit); //CoverSet bit expression if (!(HB981 - HC981).IsZero()) { goto LNextSet; //BaseSet is covered? } Bit981 CsubB = HC981 - HB981; //CsubB:excludable candidates if (CsubB.IsZero()) { goto LNextSet; // is exist? } var CoverSetLst = new List <UGLink_unit>(); Array.ForEach(cmbCvr.Index, m => CoverSetLst.Add(UGLCovCandidates[m])); //CoverSet List if (rnk == 0) { Can981 = CsubB; } //(excludable candidates) else //if(rnk>0){ // rank=k // Consider the case of covering n-BaseSet with (n+k)-CoverSet. // In order to be an analysis algorithm, the following conditions must be satisfied. // 1:(n+k)-CoverSet completely covers n-BaseSet. // 2:(k+1) of the (n+k) links of CoverSet have elements in common which are not included in the n-BaseSet. // When these conditions are satisfied, the elements of the intersection of condition 2 are not true. { bool SolFound = false; Can981.Clear(); foreach (int n in CsubB.noBit.IEGet_BtoNo()) { foreach (int rc in CsubB._BQ[n].IEGetRC()) { int kc = CoverSetLst.Count(Q => Q.rcnBit.IsHit(n, rc)); if (kc == rnk + 1) { Can981.BPSet(n, rc); SolFound = true; } } } if (!SolFound) { continue; } } ++GeneralLogicGen2.ChkCov2; //***** BasCov.addCoverSet(CoverSetLst, HC981, Can981, rnk); if (_chkX2) { string st = $"{_jkc_++} ◆CoverSet:"; foreach (var P in CoverSetLst) { st += $" {P.ToAppearance()}"; //#### debug print } WriteLine(st); } yield return(BasCov); LNextSet: continue; } yield break; #endregion CoverSet generator }
public void BPSet_true(int no, int rc) { _true.BPSet(no, rc); }
public void BPSet_false(int no, int rc) { _false.BPSet(no, rc); }
public IEnumerable <UBasCov> IEGet_BaseSet(int sz, int rnk) { if (UGLLst == null) { yield break; } BSstatus = new BaseSet_Status(sz, rnk); List <UGLink> basUGLs = BSstatus.basUGLs; //BaseSet List Bit981 HB981 = BSstatus.HB981; //BaseSet bitPattern Bit324 usedLK = BSstatus.usedLK; //usedLink(by serial number) List <int> usedLKLst = BSstatus.usedLKLst; long RCBN_frameA = 0; _jkc_ = 0; var cmbBas = new Combination(UGLLst.Count, sz); int nxt = int.MaxValue; //(skip function) while (cmbBas.Successor(nxt)) { GeneralLogicGen.ChkBas0++; //***** _jkc_++; // sz=1 *==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* if (sz == 1) { UGLink UGL = UGLLst[cmbBas.Index[0]]; if (UGL.UC is UCell) { goto LNextSet; //only row/column/block link. } HB981.Clear(); HB981.BPSet(UGL.rcBit81.no, UGL.rcBit81, tfbSet: false); //accumulate rcbn info. in HB981. basUGLs.Clear(); basUGLs.Add(UGL); //set UGL in BaseSet GeneralLogicGen.ChkBas1++; //***** goto LBSFound; //possibility of solution } //=================================================================================================================== // sz>=2 *==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* HB981.Clear(); basUGLs.Clear(); usedLKLst.Clear(); BSstatus.Clear(); RCBN_frameA = 0; int[] _RCB_frameB = new int[9]; for (int k = 0; k < sz; k++) //(r:row c:column b:block n:digit => rcbn) { nxt = k; UGLink UGL = UGLLst[cmbBas.Index[k]]; RCBN_frameA |= UGL.RCBN_frameB; //bit expression of rcbn if (!Check_rcbnCondition(sz, rnk, k, RCBN_frameA)) { goto LNextSet; //### extremely efficient } if (UGL.rcBit81 is Bit81) // ........................ rcb link ........................ { int no = UGL.rcBit81.no; if (k > 0 && HB981.IsHit(no, UGL.rcBit81)) { goto LNextSet; //elements already included in HB981 } HB981.BPSet(no, UGL.rcBit81, tfbSet: true); //accumulate rcbn info. in HB981. usedLKLst.Add(UGL.rcBit81.ID); //(ID=tfx<<4 | no) //[rcb_link type]register ID to used list. _RCB_frameB[no] |= (int)UGL.RCBN_frameB & 0x3FFFFFF; } else // ....................... Cell link ........................ { UCell UC = UGL.UC; int rc = UC.rc; //In UGLLst, rcb-Links is first, and cell-Links is second. //Even in combination, this order is maintained. //Therefore, the condition "cell-links have common parts with rcb-Links?" is satisfied. foreach (var no in UC.FreeB.IEGet_BtoNo(9)) { if (k > 0 && HB981.IsHit(no, rc)) { goto LNextSet; //Not BaseSet as it has no intersection. } HB981.BPSet(no, rc, tfbSet: true); //accumulate rcbn info. in HB981. _RCB_frameB[no] |= rc.ToRCBitPat(); } int IDrc = rc << 4 | 0xF; //( 0xF:Cell type identification flag ) usedLKLst.Add(IDrc); //(ID=rc<<4| no) //[cell type]register ID to used list. } basUGLs.Add(UGL); //set UGL in BaseSet // ........................................................... } BSstatus.RCB_frameB = _RCB_frameB; __UsedLinkToFrame(HB981, usedLKLst, BSstatus); //// if(SDK_Ctrl.UGPMan.stageNo==8 && _usedLKLst_ToRCBString("",usedLKLst)==" c1#3 c1#6"){ //// Board_Check("*** Check_6 ?"); //// } if (SDK_Ctrl.UGPMan.stageNo == 20 && _usedLKLst_ToRCBString("", usedLKLst) == " r3#2 r4#2 r3#8") { WriteLine(_usedLKLst_ToRCBString($"usedLKLst:{_jkc_}", usedLKLst, addFreeBB: true)); Board_Check(); } //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* // Board_Check(); //1..4....8.9.1...5.....63.....13.5.79..3...8..76.2.94.....75.....1...6.4.8....4..2 if (!BSstatus.Check_1()) { goto LNextSet; //A and B are not linked by other link(C). } if (!BSstatus.Check_2()) { goto LNextSet; //Each cell(A) is in a position to link with other cells. } if (!BSstatus.Check_3()) { goto LNextSet; //There is a limit to the number of cells that have no links other than BaseSet. } //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==* /* * //if(SDK_Ctrl.UGPMan.stageNo==12 && sz>=3){// && rnk==1 ){ * if(SDK_Ctrl.UGPMan.stageNo==9 && sz>=2){// && rnk==1 ){ * WriteLine($"\r sz:{sz} rnk:{rnk} jkc:{_jkc_}"); * Check_rcbnCondition(sz,rnk,sz,RCBN_frameA,printB:true); * basUGLs.ForEach(P=>WriteLine(P.ToString("BaseSet"))); * } */ LBSFound: usedLK.Clear(); basUGLs.ForEach(P => usedLK.BPSet(P.IDnum)); //IDrc: rc<<17 | 1<<16 UBasCov UBC = new UBasCov(basUGLs, HB981, sz, usedLK); yield return(UBC); //--------------------------------------------------------------------------------------- LNextSet: continue; } yield break; void __UsedLinkToFrame(Bit981 HB981, List <int> usedLKLst, BaseSet_Status BSstatus) { int[] _frame_0 = new int[9]; int[] _frame_1 = new int[9]; Bit81 _frame_T = new Bit81(); int frm, _cellC = 0; foreach (var no in HB981.noBit.IEGet_BtoNo()) { _frame_0[no] = frm = HB981._BQ[no].IEGetRC().Aggregate(0, (Q, rc) => Q | rc.ToRCBitPat()); _frame_1[no] = ___frame_ResetUsed(frm, no, usedLKLst); _frame_T |= HB981._BQ[no]; } Bit81 _frame_81 = new Bit81(_frame_T); usedLKLst.ForEach(P => { if ((P & 0xF) == 0xF) { _frame_81.BPReset(P >> 4); _cellC++; } }); BSstatus._frame_0 = _frame_0; BSstatus._frame_1 = _frame_1; BSstatus._frame_T = _frame_T; BSstatus._frame_81 = _frame_81; BSstatus._cellC = _cellC; //(Number of cell links in BaseSet) } }