ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
exorList.c
Go to the documentation of this file.
1
20
47
48#include "exor.h"
49
51
55
56// information about options and the cover
57extern cinfo g_CoverInfo;
58
59// the look-up table for the number of 1's in unsigned short
60extern unsigned char BitCount[];
61
65
66extern int GetDistance( Cube* pC1, Cube* pC2 );
67// distance computation for two cubes
68extern int GetDistancePlus( Cube* pC1, Cube* pC2 );
69
70extern void ExorVar( Cube* pC, int Var, varvalue Val );
71
72extern void AddToFreeCubes( Cube* pC );
73// returns a simplified cube back into the free list
74
75//extern void PrintCube( ostream& DebugStream, Cube* pC );
76// debug output for cubes
77
78extern Cube* GetFreeCube();
79
82extern int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist );
83// this function starts the Exor-Link IteratorCubePair, which iterates
84// through the cube groups starting from the group with min literals
85// returns 1 on success, returns 0 if the cubes have wrong distance
86
87extern int ExorLinkCubeIteratorNext( Cube** pGroup );
88// give the next group in the decreasing order of sum of literals
89// returns 1 on success, returns 0 if there are no more groups
90
91extern int ExorLinkCubeIteratorPick( Cube** pGroup, int g );
92// gives the group #g in the order in which the groups were given
93// during iteration
94// returns 1 on success, returns 0 if something g is too large
95
96extern void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup );
97// removes the cubes from the store back into the list of free cubes
98// if fTakeLastGroup is 0, removes all cubes
99// if fTakeLastGroup is 1, does not store the last group
100
104
105// iterative ExorLink
106int IterativelyApplyExorLink2( char fDistEnable );
107int IterativelyApplyExorLink3( char fDistEnable );
108int IterativelyApplyExorLink4( char fDistEnable );
109
110// function which performs distance computation and simplifes on the fly
111// it is also called from the Pseudo-Kronecker module when cubes are added
112int CheckForCloseCubes( Cube* p, int fAddCube );
113int CheckAndInsert( Cube* p );
114
115// this function changes the cube back after it was DIST-1 transformed
116void UndoRecentChanges();
117
119// iterating through adjucency pair queques (with authomatic garbage collection)
120
121// start an iterator through cubes of dist CubeDist,
122// the resulting pointers are written into ppC1 and ppC2
124// gives the next VALID cube pair (the previous one is automatically dequequed)
126
128// the cube storage
129
130// cube storage allocation/delocation
131int AllocateCubeSets( int nVarsIn, int nVarsOut );
132void DelocateCubeSets();
133
134// insert/extract a cube into/from the storage
135void CubeInsert( Cube* p );
137
139// Cube Set Iterator
141// starts an iterator that traverses all the cubes in the ring
143// returns the next cube in the ring
144// to use it again after it has returned NULL, call IterCubeSetStart() first
145
147// cube adjacency queques
148
149// adjacency queque allocation/delocation procedures
150int AllocateQueques( int nPlaces );
151void DelocateQueques();
152
153// conditional adding cube pairs to queques
154// reset temporarily stored new range of cube pairs
155static void NewRangeReset();
156// add temporarily stored new range of cube pairs to the queque
157static void NewRangeAdd();
158// insert one cube pair into the new range
159static void NewRangeInsertCubePair( cubedist Dist, Cube* p1, Cube* p2 );
160
161static void MarkSet();
162static void MarkRewind();
163
164void PrintQuequeStats();
166
167// iterating through the queque (with authomatic garbage collection)
168// start an iterator through cubes of dist CubeDist,
169// the resulting pointers are written into ppC1 and ppC2
171// gives the next VALID cube pair (the previous one is automatically dequequed)
173
177
178// the number of allocated places
180// the maximum number of occupied places
182
186
187// 1) check that ExorLink for this cube pair can be performed
188// (it may happen that the group is outdated due to recent reshaping)
189// 2) find out what is the improvement achieved by each cube group
190// 3) depending on the distance, do the following:
191// a) if ( Dist == 2 )
192// try both cube groups,
193// if one of them leads to improvement, take the cube group right away
194// if none of them leads to improment
195// - take the last one (because it reshapes)
196// - take the last one only in case it does not increase literals
197// b) if ( Dist == 3 )
198// try groups one by one
199// if one of them leads to improvement, take the group right away
200// if none of them leads to improvement
201// - take the group which reshapes
202// - take the reshaping group only in case it does not increase literals
203// if none of them leads to reshaping, do not take any of them
204// c) if ( Dist == 4 )
205// try groups one by one
206// if one of the leads to reshaping, take it right away
207// if none of them leads to reshaping, do not take any of them
208
212
213// Cube set is a list of cubes
214static Cube* s_List;
215
217// undo information
219static struct
220{
221 int fInput; // 1 if the input was changed
222 Cube* p; // the pointer to the modified cube
228 int Var; // the number of variable that was changed
229 int Value; // the value what was there
230 int PrevID; // the previous ID of the removed cube
231} s_ChangeStore;
233
234// enable pair accumulation
235// from the begginning (while the starting cover is generated)
236// only the distance 2 accumulation is enabled
237static int s_fDistEnable2 = 1;
238static int s_fDistEnable3;
239static int s_fDistEnable4;
240
241// temporary storage for cubes generated by the ExorLink iterator
242static Cube* s_CubeGroup[5];
243// the marks telling whether the given cube is inserted
244static int s_fInserted[5];
245
246// enable selection only those Dist2 and Dist3 that do not increase literals
248
249// the counters for display
250static int s_cEnquequed;
251static int s_cAttempts;
252static int s_cReshapes;
253
254// the number of cubes before ExorLink starts
255static int s_nCubesBefore;
256// the distance code specific for each ExorLink
257static cubedist s_Dist;
258
259// other variables
260static int s_Gain;
261static int s_GainTotal;
262static int s_GroupCounter;
263static int s_GroupBest;
264static Cube *s_pC1, *s_pC2;
265
269
271{
272// return CheckForCloseCubes( p, 1 );
273 CubeInsert( p );
274 return 0;
275}
276
277int IterativelyApplyExorLink2( char fDistEnable )
278// MEMO: instead of inserting the cubes that have already been checked
279// by running CheckForCloseCubes again, try inserting them without checking
280// and observe the difference (it will save 50% of checking time)
281{
282 int z;
283
284 // this var is specific to ExorLink-2
285 s_Dist = (cubedist)0;
286
287 // enable pair accumulation
288 s_fDistEnable2 = fDistEnable & 1;
289 s_fDistEnable3 = fDistEnable & 2;
290 s_fDistEnable4 = fDistEnable & 4;
291
292 // initialize counters
293 s_cEnquequed = GetQuequeStats( s_Dist );
294 s_cAttempts = 0;
295 s_cReshapes = 0;
296
297 // remember the number of cubes before minimization
298 s_nCubesBefore = g_CoverInfo.nCubesInUse;
299
300 for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() )
301 {
302 s_cAttempts++;
303 // start ExorLink of the given Distance
304 if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) )
305 {
306 // extract old cubes from storage (to prevent EXORing with their derivitives)
307 CubeExtract( s_pC1 );
308 CubeExtract( s_pC2 );
309
310 // mark the current position in the cube pair queques
311 MarkSet();
312
313 // check the first group (generated by ExorLinkCubeIteratorStart())
314 if ( CheckForCloseCubes( s_CubeGroup[0], 0 ) )
315 { // the first cube leads to improvement - it is already inserted
316 CheckForCloseCubes( s_CubeGroup[1], 1 ); // insert the second cube
317 goto SUCCESS;
318 }
319 if ( CheckForCloseCubes( s_CubeGroup[1], 0 ) )
320 { // the second cube leads to improvement - it is already inserted
321 CheckForCloseCubes( s_CubeGroup[0], 1 ); // insert the first cube
322// CheckAndInsert( s_CubeGroup[0] );
323 goto SUCCESS;
324 }
325 // the first group does not lead to improvement
326
327 // rewind to the previously marked position in the cube pair queques
328 MarkRewind();
329
330 // generate the second group
331 ExorLinkCubeIteratorNext( s_CubeGroup );
332
333 // check the second group
334 if ( CheckForCloseCubes( s_CubeGroup[0], 0 ) )
335 { // the first cube leads to improvement - it is already inserted
336 CheckForCloseCubes( s_CubeGroup[1], 1 ); // insert the second cube
337 goto SUCCESS;
338 }
339 if ( CheckForCloseCubes( s_CubeGroup[1], 0 ) )
340 { // the second cube leads to improvement - it is already inserted
341 CheckForCloseCubes( s_CubeGroup[0], 1 ); // insert the first cube
342// CheckAndInsert( s_CubeGroup[0] );
343 goto SUCCESS;
344 }
345 // the second group does not lead to improvement
346
347 // decide whether to accept the second group, depending on literals
349 {
350 if ( g_CoverInfo.fUseQCost ?
351 s_CubeGroup[0]->q + s_CubeGroup[1]->q >= s_pC1->q + s_pC2->q :
352 s_CubeGroup[0]->a + s_CubeGroup[1]->a >= s_pC1->a + s_pC2->a )
353 // the group increases literals
354 { // do not take the last group
355
356 // rewind to the previously marked position in the cube pair queques
357 MarkRewind();
358
359 // return the old cubes back to storage
360 CubeInsert( s_pC1 );
361 CubeInsert( s_pC2 );
362 // clean the results of generating ExorLinked cubes
364 continue;
365 }
366 }
367
368 // take the last group
369 // there is no need to test these cubes again,
370 // because they have been tested and did not yield any improvement
371 CubeInsert( s_CubeGroup[0] );
372 CubeInsert( s_CubeGroup[1] );
373// CheckForCloseCubes( s_CubeGroup[0], 1 );
374// CheckForCloseCubes( s_CubeGroup[1], 1 );
375
376SUCCESS:
377 // clean the results of generating ExorLinked cubes
378 ExorLinkCubeIteratorCleanUp( 1 ); // take the last group
379 // free old cubes
380 AddToFreeCubes( s_pC1 );
381 AddToFreeCubes( s_pC2 );
382 // increate the counter
383 s_cReshapes++;
384 }
385 }
386 // print the report
387 if ( g_CoverInfo.Verbosity == 2 )
388 {
389 printf( "ExLink-%d", 2 );
390 printf( ": Que= %5d", s_cEnquequed );
391 printf( " Att= %4d", s_cAttempts );
392 printf( " Resh= %4d", s_cReshapes );
393 printf( " NoResh= %4d", s_cAttempts - s_cReshapes );
394 printf( " Cubes= %3d", g_CoverInfo.nCubesInUse );
395 printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse );
396 printf( " Lits= %5d", CountLiterals() );
397 printf( " QCost = %6d", CountQCost() );
398 printf( "\n" );
399 }
400
401 // return the number of cubes gained in the process
402 return s_nCubesBefore - g_CoverInfo.nCubesInUse;
403}
404
405int IterativelyApplyExorLink3( char fDistEnable )
406{
407 int z, c, d;
408 // this var is specific to ExorLink-3
409 s_Dist = (cubedist)1;
410
411 // enable pair accumulation
412 s_fDistEnable2 = fDistEnable & 1;
413 s_fDistEnable3 = fDistEnable & 2;
414 s_fDistEnable4 = fDistEnable & 4;
415
416 // initialize counters
417 s_cEnquequed = GetQuequeStats( s_Dist );
418 s_cAttempts = 0;
419 s_cReshapes = 0;
420
421 // remember the number of cubes before minimization
422 s_nCubesBefore = g_CoverInfo.nCubesInUse;
423
424 for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() )
425 {
426 s_cAttempts++;
427 // start ExorLink of the given Distance
428 if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) )
429 {
430 // extract old cubes from storage (to prevent EXORing with their derivitives)
431 CubeExtract( s_pC1 );
432 CubeExtract( s_pC2 );
433
434 // mark the current position in the cube pair queques
435 MarkSet();
436
437 // check cube groups one by one
438 s_GroupCounter = 0;
439 do
440 { // check the cubes of this group one by one
441 for ( c = 0; c < 3; c++ )
442 if ( !s_CubeGroup[c]->fMark ) // this cube has not yet been checked
443 {
444 s_Gain = CheckForCloseCubes( s_CubeGroup[c], 0 ); // do not insert the cube, by default
445 if ( s_Gain )
446 { // this cube leads to improvement or reshaping - it is already inserted
447
448 // decide whether to accept this group based on literal count
449 if ( s_fDecreaseLiterals && s_Gain == 1 )
450 if ( g_CoverInfo.fUseQCost ?
451 s_CubeGroup[0]->q + s_CubeGroup[1]->q + s_CubeGroup[2]->q > s_pC1->q + s_pC2->q + s_ChangeStore.PrevQq :
452 s_CubeGroup[0]->a + s_CubeGroup[1]->a + s_CubeGroup[2]->a > s_pC1->a + s_pC2->a + s_ChangeStore.PrevQa
453 ) // the group increases literals
454 { // do not take this group
455 // remember the group
456 s_GroupBest = s_GroupCounter;
457 // undo changes to be able to continue checking other groups
459 break;
460 }
461
462 // take this group
463 for ( d = 0; d < 3; d++ ) // insert other cubes
464 if ( d != c )
465 {
466 CheckForCloseCubes( s_CubeGroup[d], 1 );
467// if ( s_CubeGroup[d]->fMark )
468// CheckAndInsert( s_CubeGroup[d] );
469// CheckOnlyOneCube( s_CubeGroup[d] );
470// CheckForCloseCubes( s_CubeGroup[d], 1 );
471// else
472// CheckForCloseCubes( s_CubeGroup[d], 1 );
473 }
474
475 // clean the results of generating ExorLinked cubes
476 ExorLinkCubeIteratorCleanUp( 1 ); // take the last group
477 // free old cubes
478 AddToFreeCubes( s_pC1 );
479 AddToFreeCubes( s_pC2 );
480 // update the counter
481 s_cReshapes++;
482 goto END_OF_LOOP;
483 }
484 else // mark the cube as checked
485 s_CubeGroup[c]->fMark = 1;
486 }
487 // the group is not taken - find the new group
488 s_GroupCounter++;
489
490 // rewind to the previously marked position in the cube pair queques
491 MarkRewind();
492 }
493 while ( ExorLinkCubeIteratorNext( s_CubeGroup ) );
494 // none of the groups leads to improvement
495
496 // return the old cubes back to storage
497 CubeInsert( s_pC1 );
498 CubeInsert( s_pC2 );
499 // clean the results of generating ExorLinked cubes
501 }
502END_OF_LOOP: {}
503 }
504
505 // print the report
506 if ( g_CoverInfo.Verbosity == 2 )
507 {
508 printf( "ExLink-%d", 3 );
509 printf( ": Que= %5d", s_cEnquequed );
510 printf( " Att= %4d", s_cAttempts );
511 printf( " Resh= %4d", s_cReshapes );
512 printf( " NoResh= %4d", s_cAttempts - s_cReshapes );
513 printf( " Cubes= %3d", g_CoverInfo.nCubesInUse );
514 printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse );
515 printf( " Lits= %5d", CountLiterals() );
516 printf( " QCost = %6d", CountQCost() );
517 printf( "\n" );
518 }
519
520 // return the number of cubes gained in the process
521 return s_nCubesBefore - g_CoverInfo.nCubesInUse;
522}
523
524int IterativelyApplyExorLink4( char fDistEnable )
525{
526 int z, c;
527 // this var is specific to ExorLink-4
528 s_Dist = (cubedist)2;
529
530 // enable pair accumulation
531 s_fDistEnable2 = fDistEnable & 1;
532 s_fDistEnable3 = fDistEnable & 2;
533 s_fDistEnable4 = fDistEnable & 4;
534
535 // initialize counters
536 s_cEnquequed = GetQuequeStats( s_Dist );
537 s_cAttempts = 0;
538 s_cReshapes = 0;
539
540 // remember the number of cubes before minimization
541 s_nCubesBefore = g_CoverInfo.nCubesInUse;
542
543 for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() )
544 {
545 s_cAttempts++;
546 // start ExorLink of the given Distance
547 if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) )
548 {
549 // extract old cubes from storage (to prevent EXORing with their derivitives)
550 CubeExtract( s_pC1 );
551 CubeExtract( s_pC2 );
552
553 // mark the current position in the cube pair queques
554 MarkSet();
555
556 // check cube groups one by one
557 do
558 { // check the cubes of this group one by one
559 s_GainTotal = 0;
560 for ( c = 0; c < 4; c++ )
561 if ( !s_CubeGroup[c]->fMark ) // this cube has not yet been checked
562 {
563 s_Gain = CheckForCloseCubes( s_CubeGroup[c], 0 ); // do not insert the cube, by default
564 // if the cube leads to gain, it is already inserted
565 s_fInserted[c] = (int)(s_Gain>0);
566 // increment the total gain
567 s_GainTotal += s_Gain;
568 }
569 else
570 s_fInserted[c] = 0; // the cube has already been checked - it is not inserted
571
572 if ( s_GainTotal == 0 ) // the group does not lead to any gain
573 { // mark the cubes
574 for ( c = 0; c < 4; c++ )
575 s_CubeGroup[c]->fMark = 1;
576 }
577 else if ( s_GainTotal == 1 ) // the group does not lead to substantial gain, too
578 {
579 // undo changes to be able to continue checking groups
581 // mark those cubes that were not inserted
582 for ( c = 0; c < 4; c++ )
583 s_CubeGroup[c]->fMark = !s_fInserted[c];
584 }
585 else // if ( s_GainTotal > 1 ) // the group reshapes or improves
586 { // accept the group
587 for ( c = 0; c < 4; c++ ) // insert other cubes
588 if ( !s_fInserted[c] )
589 CheckForCloseCubes( s_CubeGroup[c], 1 );
590// CheckAndInsert( s_CubeGroup[c] );
591 // clean the results of generating ExorLinked cubes
592 ExorLinkCubeIteratorCleanUp( 1 ); // take the last group
593 // free old cubes
594 AddToFreeCubes( s_pC1 );
595 AddToFreeCubes( s_pC2 );
596 // update the counter
597 s_cReshapes++;
598 goto END_OF_LOOP;
599 }
600
601 // rewind to the previously marked position in the cube pair queques
602 MarkRewind();
603 }
604 while ( ExorLinkCubeIteratorNext( s_CubeGroup ) );
605 // none of the groups leads to improvement
606
607 // return the old cubes back to storage
608 CubeInsert( s_pC1 );
609 CubeInsert( s_pC2 );
610 // clean the results of generating ExorLinked cubes
612 }
613END_OF_LOOP: {}
614 }
615
616 // print the report
617 if ( g_CoverInfo.Verbosity == 2 )
618 {
619 printf( "ExLink-%d", 4 );
620 printf( ": Que= %5d", s_cEnquequed );
621 printf( " Att= %4d", s_cAttempts );
622 printf( " Resh= %4d", s_cReshapes );
623 printf( " NoResh= %4d", s_cAttempts - s_cReshapes );
624 printf( " Cubes= %3d", g_CoverInfo.nCubesInUse );
625 printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse );
626 printf( " Lits= %5d", CountLiterals() );
627 printf( " QCost = %6d", CountQCost() );
628 printf( "\n" );
629 }
630
631 // return the number of cubes gained in the process
632 return s_nCubesBefore - g_CoverInfo.nCubesInUse;
633}
634
635// local static variables
642
643int CheckForCloseCubes( Cube* p, int fAddCube )
644// checks the cube storage for a cube that is dist-0 and dist-1 removed
645// from the given one (p) if such a cube is found, extracts it from the data
646// structure, EXORs it with the given cube, adds the resultant cube
647// to the data structure and performed the same check for the resultant cube;
648// returns the number of cubes gained in the process of reduction;
649// if an adjacent cube is not found, inserts the cube only if (fAddCube==1)!!!
650{
651 // start the new range
652 NewRangeReset();
653
654 for ( s_q = s_List; s_q; s_q = s_q->Next )
655 {
657 if ( s_Distance > 4 )
658 {
659 }
660 else if ( s_Distance == 4 )
661 {
662 if ( s_fDistEnable4 )
663 NewRangeInsertCubePair( DIST4, p, s_q );
664 }
665 else if ( s_Distance == 3 )
666 {
667 if ( s_fDistEnable3 )
668 NewRangeInsertCubePair( DIST3, p, s_q );
669 }
670 else if ( s_Distance == 2 )
671 {
672 if ( s_fDistEnable2 )
673 NewRangeInsertCubePair( DIST2, p, s_q );
674 }
675 else if ( s_Distance == 1 )
676 { // extract the cube from the data structure
677
679 // store the changes
680 s_ChangeStore.fInput = (s_DiffVarNum != -1);
681 s_ChangeStore.p = p;
682 s_ChangeStore.PrevQa = s_q->a;
683 s_ChangeStore.PrevPa = p->a;
684 s_ChangeStore.PrevQq = s_q->q;
685 s_ChangeStore.PrevPq = p->q;
686 s_ChangeStore.PrevPz = p->z;
687 s_ChangeStore.Var = s_DiffVarNum;
688 s_ChangeStore.Value = s_DiffVarValueQ;
689 s_ChangeStore.PrevID = s_q->ID;
691
692 CubeExtract( s_q );
693 // perform the EXOR of the two cubes and write the result into p
694
695 // it is important that the resultant cube is written into p!!!
696
697 if ( s_DiffVarNum == -1 )
698 {
699 int i;
700 // exor the output part
701 p->z = 0;
702 for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
703 {
704 p->pCubeDataOut[i] ^= s_q->pCubeDataOut[i];
705 p->z += BIT_COUNT(p->pCubeDataOut[i]);
706 }
707 }
708 else
709 {
710 // the cube has already been updated by GetDistancePlus()
711
712 // modify the parameters of the number of literals in the new cube
713// p->a += s_UpdateLiterals[ s_DiffVarValueP ][ s_DiffVarValueQ ];
715 p->a--;
717 p->a++;
718 p->q = ComputeQCostBits(p);
719 }
720
721 // move q to the free cube list
723
724 // make sure that nobody with use the pairs created so far
725// NewRangeReset();
726 // call the function again for the new cube
727 return 1 + CheckForCloseCubes( p, 1 );
728 }
729 else // if ( Distance == 0 )
730 { // extract the second cube from the data structure and add them both to the free list
731 AddToFreeCubes( p );
733
734 // make sure that nobody with use the pairs created so far
735 NewRangeReset();
736 return 2;
737 }
738 }
739
740 // add the cube to the data structure if needed
741 if ( fAddCube )
742 CubeInsert( p );
743
744 // add temporarily stored new range of cube pairs to the queque
745 NewRangeAdd();
746
747 return 0;
748}
749
751{
752 Cube * p, * q;
753 // get back cube q that was deleted
754 q = GetFreeCube();
755 // restore the ID
756 q->ID = s_ChangeStore.PrevID;
757 // insert the cube into storage again
758 CubeInsert( q );
759
760 // extract cube p
761 p = CubeExtract( s_ChangeStore.p );
762
763 // modify it back
764 if ( s_ChangeStore.fInput ) // the input has changed
765 {
766 ExorVar( p, s_ChangeStore.Var, (varvalue)s_ChangeStore.Value );
767 p->a = s_ChangeStore.PrevPa;
768 p->q = s_ChangeStore.PrevPq;
769 // p->z did not change
770 }
771 else // if ( s_ChangeStore.fInput ) // the output has changed
772 {
773 int i;
774 for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
775 p->pCubeDataOut[i] ^= q->pCubeDataOut[i];
776 p->z = s_ChangeStore.PrevPz;
777 // p->a did not change
778 }
779}
780
784
785// Cube set is a list of cubes
786//static Cube* s_List;
787
791
792int AllocateCubeSets( int nVarsIn, int nVarsOut )
793{
794 s_List = NULL;
795
796 // clean other data
797 s_fDistEnable2 = 1;
798 s_fDistEnable3 = 0;
799 s_fDistEnable4 = 0;
800 memset( s_CubeGroup, 0, sizeof(void *) * 5 );
801 memset( s_fInserted, 0, sizeof(int) * 5 );
803 s_cEnquequed = 0;
804 s_cAttempts = 0;
805 s_cReshapes = 0;
806 s_nCubesBefore = 0;
807 s_Gain = 0;
808 s_GainTotal = 0;
809 s_GroupCounter = 0;
810 s_GroupBest = 0;
811 s_pC1 = s_pC2 = NULL;
812
813 return 4;
814}
815
817{
818}
819
823
825// inserts the cube into storage (puts it at the beginning of the list)
826{
827 assert( p->Prev == NULL && p->Next == NULL );
828 assert( p->ID );
829
830 if ( s_List == NULL )
831 s_List = p;
832 else
833 {
834 p->Next = s_List;
835
836 s_List->Prev = p;
837 s_List = p;
838 }
839
840 g_CoverInfo.nCubesInUse++;
841}
842
844// extracts the cube from storage
845{
846// assert( p->Prev && p->Next ); // can be done only with rings
847 assert( p->ID );
848
849// if ( s_List == p )
850// s_List = p->Next;
851// if ( p->Prev )
852// p->Prev->Next = p->Next;
853
854 if ( s_List == p )
855 s_List = p->Next;
856 else
857 p->Prev->Next = p->Next;
858
859 if ( p->Next )
860 p->Next->Prev = p->Prev;
861
862 p->Prev = NULL;
863 p->Next = NULL;
864
865 g_CoverInfo.nCubesInUse--;
866 return p;
867}
868
872
873// the iterator starts from the Head and stops when it sees NULL
875
879
881// starts an iterator that traverses all the cubes in the ring
882{
883 assert( s_pCubeLast == NULL );
884
885 // check whether the List has cubes
886 if ( s_List == NULL )
887 return NULL;
888
889 return ( s_pCubeLast = s_List );
890}
891
893// returns the next cube in the cube set
894// to use it again after it has returned NULL, first call IterCubeSetStart()
895{
897 return ( s_pCubeLast = s_pCubeLast->Next );
898}
899
903
904typedef struct
905{
906 Cube** pC1; // the pointer to the first cube
907 Cube** pC2; // the pointer to the second cube
908 byte* ID1; // the ID of the first cube
909 byte* ID2; // the ID of the second cube
910 int PosOut; // extract position
911 int PosIn; // insert position
912 int PosCur; // temporary insert position
913 int PosMark; // the marked position
914 int fEmpty; // this flag is 1 if there is nothing in the queque
915} que;
916
917static que s_Que[3]; // Dist-2, Dist-3, Dist-4 queques
918
919// the number of allocated places
920//int s_nPosAlloc;
921// the maximum number of occupied places
922//int s_nPosMax[3];
923
925// Conditional Adding Cube Pairs To Queques //
927
928int GetPosDiff( int PosBeg, int PosEnd )
929{
930 return (PosEnd - PosBeg + s_nPosAlloc) % s_nPosAlloc;
931}
932
933void MarkSet()
934// sets marks in the cube pair queques
935{
936 s_Que[0].PosMark = s_Que[0].PosIn;
937 s_Que[1].PosMark = s_Que[1].PosIn;
938 s_Que[2].PosMark = s_Que[2].PosIn;
939}
940
941void MarkRewind()
942// rewinds the queques to the previously set marks
943{
944 s_Que[0].PosIn = s_Que[0].PosMark;
945 s_Que[1].PosIn = s_Que[1].PosMark;
946 s_Que[2].PosIn = s_Que[2].PosMark;
947}
948
949void NewRangeReset()
950// resets temporarily stored new range of cube pairs
951{
952 s_Que[0].PosCur = s_Que[0].PosIn;
953 s_Que[1].PosCur = s_Que[1].PosIn;
954 s_Que[2].PosCur = s_Que[2].PosIn;
955}
956
957void NewRangeAdd()
958// adds temporarily stored new range of cube pairs to the queque
959{
960 s_Que[0].PosIn = s_Que[0].PosCur;
961 s_Que[1].PosIn = s_Que[1].PosCur;
962 s_Que[2].PosIn = s_Que[2].PosCur;
963}
964
965void NewRangeInsertCubePair( cubedist Dist, Cube* p1, Cube* p2 )
966// insert one cube pair into the new range
967{
968 que* p = &s_Que[Dist];
969 int Pos = p->PosCur;
970
971 if ( p->fEmpty || Pos != p->PosOut )
972 {
973 p->pC1[Pos] = p1;
974 p->pC2[Pos] = p2;
975 p->ID1[Pos] = p1->ID;
976 p->ID2[Pos] = p2->ID;
977
978 p->PosCur = (p->PosCur+1)%s_nPosAlloc;
979 }
980 else
981 assert(0);
982// cout << endl << "DIST-" << (int)(Dist+2) << ": Have run out of queque space!" << endl;
983}
984
986{
987/*
988 cout << endl << "Queque statistics: ";
989 cout << " Alloc = " << s_nPosAlloc;
990 cout << " DIST2 = " << GetPosDiff( s_Que[0].PosOut, s_Que[0].PosIn );
991 cout << " DIST3 = " << GetPosDiff( s_Que[1].PosOut, s_Que[1].PosIn );
992 cout << " DIST4 = " << GetPosDiff( s_Que[2].PosOut, s_Que[2].PosIn );
993 cout << endl;
994 cout << endl;
995*/
996}
997
999{
1000 return GetPosDiff( s_Que[Dist].PosOut, s_Que[Dist].PosIn );
1001}
1002
1004// Queque Iterators //
1006
1007// iterating through the queque (with authomatic garbage collection)
1008// only one iterator can be active at a time
1009static struct
1010{
1011 int fStarted; // status of the iterator (1 if working)
1012 cubedist Dist; // the currently iterated queque
1013 Cube** ppC1; // the position where the first cube pointer goes
1014 Cube** ppC2; // the position where the second cube pointer goes
1015 int PosStop; // the stop position (to prevent the iterator from
1016 // choking when new pairs are added during iteration)
1017 int CutValue; // the number of literals below which the cubes are not used
1018} s_Iter;
1019
1020static que* pQ;
1021static Cube *p1, *p2;
1022
1024// start an iterator through cubes of dist CubeDist,
1025// the resulting pointers are written into ppC1 and ppC2
1026// returns 1 if the first cube pair is found
1027{
1028 int fEntryFound;
1029
1030 assert( s_Iter.fStarted == 0 );
1031 assert( CubeDist >= 0 && CubeDist <= 2 );
1032
1033 s_Iter.fStarted = 1;
1034 s_Iter.Dist = CubeDist;
1035 s_Iter.ppC1 = ppC1;
1036 s_Iter.ppC2 = ppC2;
1037
1038 s_Iter.PosStop = s_Que[ CubeDist ].PosIn;
1039
1040 // determine the cut value
1041// s_Iter.CutValue = s_nLiteralsInUse/s_nCubesInUse/2;
1042 s_Iter.CutValue = -1;
1043
1044 fEntryFound = 0;
1045 // go through the entries while there is something in the queque
1046 for ( pQ = &s_Que[ CubeDist ]; pQ->PosOut != s_Iter.PosStop; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc )
1047 {
1048 p1 = pQ->pC1[ pQ->PosOut ];
1049 p2 = pQ->pC2[ pQ->PosOut ];
1050
1051 // check whether the entry is valid
1052 if ( p1->ID == pQ->ID1[ pQ->PosOut ] &&
1053 p2->ID == pQ->ID2[ pQ->PosOut ] ) //&&
1054 //p1->x + p1->y + p2->x + p2->y > s_Iter.CutValue )
1055 {
1056 fEntryFound = 1;
1057 break;
1058 }
1059 }
1060
1061 if ( fEntryFound )
1062 { // write the result into the pick-up place
1063 *ppC1 = pQ->pC1[ pQ->PosOut ];
1064 *ppC2 = pQ->pC2[ pQ->PosOut ];
1065
1066 pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc;
1067 }
1068 else
1069 s_Iter.fStarted = 0;
1070 return fEntryFound;
1071}
1072
1074// gives the next VALID cube pair (the previous one is automatically dequequed)
1075{
1076 int fEntryFound = 0;
1077 assert( s_Iter.fStarted );
1078
1079 // go through the entries while there is something in the queque
1080 for ( pQ = &s_Que[ s_Iter.Dist ]; pQ->PosOut != s_Iter.PosStop; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc )
1081 {
1082 p1 = pQ->pC1[ pQ->PosOut ];
1083 p2 = pQ->pC2[ pQ->PosOut ];
1084
1085 // check whether the entry is valid
1086 if ( p1->ID == pQ->ID1[ pQ->PosOut ] &&
1087 p2->ID == pQ->ID2[ pQ->PosOut ] ) //&&
1088 //p1->x + p1->y + p2->x + p2->y > s_Iter.CutValue )
1089 {
1090 fEntryFound = 1;
1091 break;
1092 }
1093 }
1094
1095 if ( fEntryFound )
1096 { // write the result into the pick-up place
1097 *(s_Iter.ppC1) = pQ->pC1[ pQ->PosOut ];
1098 *(s_Iter.ppC2) = pQ->pC2[ pQ->PosOut ];
1099
1100 pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc;
1101 }
1102 else // iteration has finished
1103 s_Iter.fStarted = 0;
1104
1105 return fEntryFound;
1106}
1107
1109// Allocation/Delocation //
1111
1112int AllocateQueques( int nPlaces )
1113// nPlaces should be approximately nCubes*nCubes/10
1114// allocates memory for cube pair queques
1115{
1116 int i;
1117 s_nPosAlloc = nPlaces;
1118
1119 for ( i = 0; i < 3; i++ )
1120 {
1121 // clean data
1122 memset( &s_Que[i], 0, sizeof(que) );
1123
1124 s_Que[i].pC1 = (Cube**) ABC_ALLOC( Cube*, nPlaces );
1125 s_Que[i].pC2 = (Cube**) ABC_ALLOC( Cube*, nPlaces );
1126 s_Que[i].ID1 = (byte*) ABC_ALLOC( byte, nPlaces );
1127 s_Que[i].ID2 = (byte*) ABC_ALLOC( byte, nPlaces );
1128
1129 if ( s_Que[i].pC1==NULL || s_Que[i].pC2==NULL || s_Que[i].ID1==NULL || s_Que[i].ID2==NULL )
1130 return 0;
1131
1132 s_nPosMax[i] = 0;
1133 s_Que[i].fEmpty = 1;
1134 }
1135
1136 return nPlaces * (sizeof(Cube*) + sizeof(Cube*) + 2*sizeof(byte) );
1137}
1138
1140{
1141 int i;
1142 for ( i = 0; i < 3; i++ )
1143 {
1144 ABC_FREE( s_Que[i].pC1 );
1145 ABC_FREE( s_Que[i].pC2 );
1146 ABC_FREE( s_Que[i].ID1 );
1147 ABC_FREE( s_Que[i].ID2 );
1148 }
1149}
1150
1154
1155
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
ush Pos
Definition deflate.h:88
int s_DiffVarValueP_new
Definition exorList.c:640
int s_DiffVarValueQ
Definition exorList.c:641
int s_DiffVarNum
Definition exorList.c:638
int s_DiffVarValueP_old
Definition exorList.c:639
int IteratorCubePairNext()
Definition exorList.c:1073
Cube * p
Definition exorList.c:222
int IteratorCubePairStart(cubedist Dist, Cube **ppC1, Cube **ppC2)
Definition exorList.c:1023
void DelocateQueques()
Definition exorList.c:1139
cubedist Dist
Definition exorList.c:1012
Cube ** ppC2
Definition exorList.c:1014
int s_Distance
Definition exorList.c:637
int IterativelyApplyExorLink4(char fDistEnable)
Definition exorList.c:524
Cube * s_q
Definition exorList.c:636
int AllocateCubeSets(int nVarsIn, int nVarsOut)
CUBE SET MANIPULATION PROCEDURES ///.
Definition exorList.c:792
int PrevPq
Definition exorList.c:226
int AllocateQueques(int nPlaces)
Definition exorList.c:1112
void DelocateCubeSets()
Definition exorList.c:816
int PrevID
Definition exorList.c:230
void PrintQuequeStats()
Definition exorList.c:985
int GetQuequeStats(cubedist Dist)
Definition exorList.c:998
int ExorLinkCubeIteratorNext(Cube **pGroup)
Definition exorLink.c:560
int s_nPosAlloc
EXPORTED VARIABLES /// /////////////////////////////////////////////////////////////////////`.
Definition exorList.c:179
int fStarted
Definition exorList.c:1011
int PrevQq
Definition exorList.c:225
int fInput
Definition exorList.c:221
void UndoRecentChanges()
Definition exorList.c:750
int ExorLinkCubeIteratorStart(Cube **pGroup, Cube *pC1, Cube *pC2, cubedist Dist)
ExorLink Functions.
Definition exorLink.c:376
int IterativelyApplyExorLink3(char fDistEnable)
Definition exorList.c:405
int GetPosDiff(int PosBeg, int PosEnd)
Definition exorList.c:928
int s_nPosMax[3]
Definition exorList.c:181
int CutValue
Definition exorList.c:1017
int PrevPa
Definition exorList.c:224
int IterativelyApplyExorLink2(char fDistEnable)
FUNCTIONS OF THIS MODULE ///.
Definition exorList.c:277
void ExorVar(Cube *pC, int Var, varvalue Val)
Definition exorBits.c:197
Cube * GetFreeCube()
Definition exorCubes.c:174
int CheckAndInsert(Cube *p)
Iterative ExorLink Operation ///.
Definition exorList.c:270
int ExorLinkCubeIteratorPick(Cube **pGroup, int g)
Definition exorLink.c:682
int Var
Definition exorList.c:228
int PosStop
Definition exorList.c:1015
Cube ** ppC1
Definition exorList.c:1013
Cube * s_pCubeLast
CUBE ITERATOR ///.
Definition exorList.c:874
int PrevPz
Definition exorList.c:227
int GetDistance(Cube *pC1, Cube *pC2)
EXTERNAL FUNCTIONS ///.
Definition exorBits.c:214
int PrevQa
Definition exorList.c:223
int CheckForCloseCubes(Cube *p, int fAddCube)
Definition exorList.c:643
Cube * CubeExtract(Cube *p)
Definition exorList.c:843
void AddToFreeCubes(Cube *pC)
FREE CUBE LIST MANIPULATION FUNCTIONS ///.
Definition exorCubes.c:157
Cube * IterCubeSetStart()
Cube Set Iterator ///.
Definition exorList.c:880
Cube * IterCubeSetNext()
Definition exorList.c:892
void ExorLinkCubeIteratorCleanUp(int fTakeLastGroup)
Definition exorLink.c:710
void CubeInsert(Cube *p)
Insertion Operators ///.
Definition exorList.c:824
int GetDistancePlus(Cube *pC1, Cube *pC2)
Definition exorBits.c:246
int s_fDecreaseLiterals
Definition exorList.c:247
int ComputeQCostBits(Cube *p)
Definition exor.c:139
ABC_NAMESPACE_IMPL_START cinfo g_CoverInfo
GLOBAL VARIABLES ///.
Definition exor.c:58
int CountLiterals()
FUNCTION DECLARATIONS ///.
Definition exorUtil.c:77
unsigned char BitCount[]
Definition exorBits.c:138
int CountQCost()
Definition exorUtil.c:119
struct cube Cube
cubedist
Definition exor.h:181
@ DIST4
Definition exor.h:181
@ DIST2
Definition exor.h:181
@ DIST3
Definition exor.h:181
struct cinfo_tag cinfo
varvalue
VARVALUE and CUBEDIST enum typedefs ///.
Definition exor.h:178
@ VAR_POS
Definition exor.h:178
@ VAR_NEG
Definition exor.h:178
byte ID
Definition exor.h:125
drow * pCubeDataOut
Definition exor.h:130
Cube ** pC2
Definition exorList.c:907
int PosMark
Definition exorList.c:913
int fEmpty
Definition exorList.c:914
int PosCur
Definition exorList.c:912
byte * ID2
Definition exorList.c:909
byte * ID1
Definition exorList.c:908
int PosOut
Definition exorList.c:910
Cube ** pC1
Definition exorList.c:906
int PosIn
Definition exorList.c:911
#define assert(ex)
Definition util_old.h:213
char * memset()