summaryrefslogtreecommitdiff
path: root/test/spass/rules-split.c
blob: 7ee420a9935febbbc3e13dd459aa48dc02bfc4cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/**************************************************************/
/* ********************************************************** */
/* *                                                        * */
/* *               SPLITTING OF CLAUSES                     * */
/* *                                                        * */
/* *  $Module:   SPLIT                                      * */ 
/* *                                                        * */
/* *  Copyright (C) 1996, 1997, 1998, 2000                  * */
/* *  MPI fuer Informatik                                   * */
/* *                                                        * */
/* *  This program is free software; you can redistribute   * */
/* *  it and/or modify it under the terms of the GNU        * */
/* *  General Public License as published by the Free       * */
/* *  Software Foundation; either version 2 of the License, * */
/* *  or (at your option) any later version.                * */
/* *                                                        * */
/* *  This program is distributed in the hope that it will  * */
/* *  be useful, but WITHOUT ANY WARRANTY; without even     * */
/* *  the implied warranty of MERCHANTABILITY or FITNESS    * */
/* *  FOR A PARTICULAR PURPOSE.  See the GNU General Public * */
/* *  License for more details.                             * */
/* *                                                        * */
/* *  You should have received a copy of the GNU General    * */
/* *  Public License along with this program; if not, write * */
/* *  to the Free Software Foundation, Inc., 59 Temple      * */
/* *  Place, Suite 330, Boston, MA  02111-1307  USA         * */
/* *                                                        * */
/* *                                                        * */
/* $Revision: 21527 $                                        * */
/* $State$                                            * */
/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $                             * */
/* $Author: duraid $                                       * */
/* *                                                        * */
/* *             Contact:                                   * */
/* *             Christoph Weidenbach                       * */
/* *             MPI fuer Informatik                        * */
/* *             Stuhlsatzenhausweg 85                      * */
/* *             66123 Saarbruecken                         * */
/* *             Email: weidenb@mpi-sb.mpg.de               * */
/* *             Germany                                    * */
/* *                                                        * */
/* ********************************************************** */
/**************************************************************/


/* $RCSfile$ */

/**************************************************************/
/* Includes                                                   */
/**************************************************************/

#include "rules-split.h"

static LIST  split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH,LIST, int, LIST*);
static LIST  split_DeleteInvalidClausesFromList(PROOFSEARCH, int, LIST);
static void  split_DeleteInvalidClausesFromStack(PROOFSEARCH);
static LIST  split_RemoveUnnecessarySplits(PROOFSEARCH, CLAUSE);


/**************************************************************/
/* Functions                                                  */
/**************************************************************/


LIST split_Backtrack(PROOFSEARCH PS, CLAUSE EmptyClause, CLAUSE* SplitClause) 
/**************************************************************
  INPUT:   A proofsearch object, an empty clause and a pointer to a clause
           used as return value.
  RETURNS: A list of clauses deleted in the backtracked split levels.
           <*SplitClause> is set to the split clause for the right branch
	   of the splitting step, or NULL, if the tableau is finished.
  EFFECT:  Backtracks the top of the split stack wrt the empty clause's level
***************************************************************/
{
  SPLIT ActBacktrackSplit;
  LIST  RecoverList, Scan;
  int   Backtracklevel;

  ActBacktrackSplit = (SPLIT)NULL;
  RecoverList       = split_RemoveUnnecessarySplits(PS, EmptyClause);
  Backtracklevel    = clause_SplitLevel(EmptyClause);
  *SplitClause      = NULL;

  /* Backtrack all split levels bigger than the level of the empty clause */
  while (!prfs_SplitStackEmpty(PS) && (prfs_ValidLevel(PS) > Backtracklevel)) {
    ActBacktrackSplit = prfs_SplitStackTop(PS);
    prfs_SplitStackPop(PS);
    if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL) {
      RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit),
			      RecoverList);
      prfs_SplitSetFatherClause(ActBacktrackSplit, NULL);
    }
    RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit),
			     RecoverList);
    clause_DeleteClauseList(prfs_SplitBlockedClauses(ActBacktrackSplit));
    prfs_SplitFree(ActBacktrackSplit);
    prfs_DecValidLevel(PS);
  }
  
  /* Backtrack further for all right branches on top of the stack */
  while (!prfs_SplitStackEmpty(PS) &&
	 list_Empty(prfs_SplitBlockedClauses(prfs_SplitStackTop(PS)))) {
    ActBacktrackSplit = prfs_SplitStackTop(PS);
    prfs_SplitStackPop(PS);
    if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL)
      RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit),
			      RecoverList);
    RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit),
			     RecoverList);
    prfs_SplitFree(ActBacktrackSplit);
    prfs_DecValidLevel(PS);
  }
  
  if (!prfs_SplitStackEmpty(PS)) {
    /* Enter the right branch of the splitting step */
    int SplitMinus1;
    LIST RightClauses;

    SplitMinus1       = prfs_ValidLevel(PS) - 1;
    ActBacktrackSplit = prfs_SplitStackTop(PS);

    RecoverList       = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit),
				   RecoverList);
    prfs_SplitSetDeletedClauses(ActBacktrackSplit, list_Nil());    
    RecoverList       = split_DeleteInvalidClausesFromList(PS, SplitMinus1,
							   RecoverList);

    RightClauses = prfs_SplitBlockedClauses(ActBacktrackSplit);
    prfs_SplitSetBlockedClauses(ActBacktrackSplit, list_Nil());    
    for (Scan = RightClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
      if (clause_Number(list_Car(Scan)) == 0) {
	/* Found the right clause, the negation clauses have number -1. */
#ifdef CHECK
	if (*SplitClause != NULL) {
	  misc_StartErrorReport();
	  misc_ErrorReport("\n In split_Backtrack:");
	  misc_ErrorReport(" Found two blocked clauses ");
	  misc_ErrorReport("\n with clause number 0 (this marks the clause ");
	  misc_ErrorReport("\n for the right branch of the tableau).");
	  misc_FinishErrorReport();
	}
#endif
	*SplitClause = list_Car(Scan);
      }
      
      clause_NewNumber((CLAUSE) list_Car(Scan));
      clause_AddParentClause((CLAUSE) list_Car(Scan), clause_Number(EmptyClause));
      clause_AddParentLiteral((CLAUSE) list_Car(Scan), 0);  /* dummy literal */
    }

#ifdef CHECK
    if (*SplitClause == NULL) {
      misc_StartErrorReport();
      misc_ErrorReport("\n In split_Backtrack: Didn´t find a blocked clause");
      misc_ErrorReport("\n with clause number 0. (this marks the clause ");
      misc_ErrorReport("\n for the right branch of the tableau).");
      misc_FinishErrorReport();
    }
#endif
    
    RecoverList = list_Nconc(RightClauses, RecoverList);

    /* Then, delete clauses from current level (Hack) */
    prfs_DecValidLevel(PS);
    prfs_MoveInvalidClausesDocProof(PS);
    split_DeleteInvalidClausesFromStack(PS);
    prfs_IncValidLevel(PS);
  } else {
    /* Don't delete clauses from current level (split is top level) */
    prfs_MoveInvalidClausesDocProof(PS);
    for (Scan = RecoverList; !list_Empty(Scan); Scan = list_Cdr(Scan))
      prfs_InsertDocProofClause(PS, list_Car(Scan));
    list_Delete(RecoverList);
    RecoverList = list_Nil();
  }
  prfs_SetLastBacktrackLevel(PS, prfs_ValidLevel(PS));

  return RecoverList;
}


static LIST split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH Search,
							LIST ClauseList,
							int Level, LIST* New)
/**************************************************************
  INPUT:   A proof search object, a list of unshared clauses
           and a split level.
  EFFECT:  Deletes all clauses depending on split level from
           <ClauseList>.
           All split stored deleted clauses from the level of
           the deleted clauses from <ClauseList> are stored in
           <*New>.
  RETURNS: The updated list and the recover clauses in <*New>.
***************************************************************/
{
  LIST   Scan;
  CLAUSE Clause;
  SPLIT  Reinsert;

  for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
    Clause = list_Car(Scan);   
    if (clause_DependsOnSplitLevel(Clause, Level)) {
      Reinsert = prfs_GetSplitOfLevel(clause_SplitLevel(Clause), Search);
      if (prfs_SplitDeletedClauses(Reinsert) != list_Nil()) {
	*New = list_Nconc(prfs_SplitDeletedClauses(Reinsert), *New);
	prfs_SplitSetDeletedClauses(Reinsert, list_Nil());
      }
      prfs_InsertDocProofClause(Search,Clause);
      list_Rplaca(Scan, NULL);
    }
  }
  return list_PointerDeleteElement(ClauseList, NULL);
}
 

static LIST split_DeleteClausesDependingOnLevelFromSet(PROOFSEARCH PS,
						       LIST ClauseList,
						       int SplitLevel)
/**************************************************************
  INPUT:   A PROOFSEARCH object, a list of shared clauses
           and a split level.
  RETURNS: A list of clauses that have to be recovered possibly.
  EFFECT:  Clauses from the clause list depending on <SplitLevel>
           are moved to the doc proof index of <PS>.
           All formerly redundant clauses that were reduced by a clause
           of the same split level as a clause from the list depending
           on <SplitLevel> are returned.
***************************************************************/
{
  LIST   scan, delList, recover;
  CLAUSE clause;
  SPLIT  reinsert;

  delList = recover = list_Nil();

  for (scan = ClauseList; !list_Empty(scan); scan = list_Cdr(scan)){
    clause = list_Car(scan);
    if (clause_DependsOnSplitLevel(clause, SplitLevel)) {
      reinsert = prfs_GetSplitOfLevel(clause_SplitLevel(clause), PS);
      recover = list_Nconc(prfs_SplitDeletedClauses(reinsert), recover);
      prfs_SplitSetDeletedClauses(reinsert, list_Nil());
      delList = list_Cons(clause, delList);
    }
  }

  /* WARNING: The following move operations change the worked off */
  /* and usable sets of the proof search object destructively.    */
  /* So it's impossible to move those function calls into the     */
  /* loop above.                                                  */
  for ( ; !list_Empty(delList); delList = list_Pop(delList)) {
    clause = list_Car(delList);
    if (clause_GetFlag(clause, WORKEDOFF))
      prfs_MoveWorkedOffDocProof(PS, clause);
    else
      prfs_MoveUsableDocProof(PS, clause);
  }
  return recover;
}



static LIST split_DeleteInvalidClausesFromList(PROOFSEARCH Search, int Level,
					       LIST ClauseList)
/**************************************************************
  INPUT:   A proof search object, a split level and a list of clauses.
  RETURNS: The list where invalid clauses wrt 'Level' are deleted.
  EFFECT:  The invalid clauses are stored in the doc proof index
           of the proof search object if necessary.
***************************************************************/
{
  LIST   Scan;
  CLAUSE Clause;

  /*printf("\nDiese Liste soll von ungueltigen (Level > %d) "
    "befreit werden: \n",Level);fflush(stdout);
    clause_ListPrint(ClauseList);*/

  for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) {
    Clause = list_Car(Scan);
    if (!prfs_IsClauseValid(Clause,Level)) {
      prfs_InsertDocProofClause(Search,Clause);
      list_Rplaca(Scan, NULL);
    }
  }
  return list_PointerDeleteElement(ClauseList, NULL);
}

static void split_DeleteInvalidClausesFromStack(PROOFSEARCH Search)
/**************************************************************
  INPUT:   A proof search object.            
  EFFECT:  All clauses in the split stack of <Search> that have a higher
           split level than the current <Search> split level are deleted.
***************************************************************/
{
  LIST   Scan1,Scan2,ClauseList;
  int    Level;
  CLAUSE Clause;

  Level = prfs_ValidLevel(Search);

  for (Scan1=prfs_SplitStack(Search);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) {
    ClauseList = prfs_SplitDeletedClauses(list_Car(Scan1));
    for (Scan2 = ClauseList; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) {
      Clause = (CLAUSE)list_Car(Scan2);
      if (!prfs_IsClauseValid(Clause,Level)) {
	prfs_InsertDocProofClause(Search,Clause);
	list_Rplaca(Scan2, NULL);
      }
    }
    prfs_SplitSetDeletedClauses(list_Car(Scan1),list_PointerDeleteElement(ClauseList, NULL));
  }
}


static LIST split_RemoveUnnecessarySplits(PROOFSEARCH PS, CLAUSE EmptyClause)
/**************************************************************
  INPUT:   An empty clause and a proof search object
  EFFECT:  Removes all splits up to the last backtrack level
           that were not necessary to derive the empty clause.
  RETURNS: A list of recovered clauses.
***************************************************************/
{
  LIST Scan;
  LIST Recover, New;
  LIST Deleted;
  LIST ScanStack;

  int SplitLevel;
  int LastBacktrackLevel;
  SPLIT Split,ScanSplit;

  Scan               = prfs_SplitStack(PS);
  SplitLevel         = prfs_ValidLevel(PS);
  LastBacktrackLevel = prfs_LastBacktrackLevel(PS);
  Recover            = list_Nil();

  while (SplitLevel > LastBacktrackLevel) {
    if (prfs_SplitIsUnused(list_Car(Scan)) &&
	!clause_DependsOnSplitLevel(EmptyClause, SplitLevel)) {
      New   = list_Nil();
      Split = list_Car(Scan);

      /*printf("\n\t Removed: %d",prfs_SplitSplitLevel(Split));*/
      
      clause_DeleteClauseList(prfs_SplitBlockedClauses(Split));
      prfs_SplitSetBlockedClauses(Split, list_Nil());
      
      Recover = list_Nconc(prfs_SplitDeletedClauses(Split), Recover);
      prfs_SplitSetDeletedClauses(Split, list_Nil());
      
      if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) {
	Recover = list_Cons(prfs_SplitFatherClause(Split),Recover);
	prfs_SplitSetFatherClause(Split,NULL);
      }
      Recover = split_DeleteClausesDependingOnLevelFromList(PS, Recover, SplitLevel, &New);
      
      ScanStack = prfs_SplitStack(PS);
      while (!list_StackEmpty(ScanStack) &&  
	     prfs_SplitSplitLevel((ScanSplit = (SPLIT)list_Car(ScanStack))) > LastBacktrackLevel) {
	Deleted = prfs_SplitDeletedClauses(ScanSplit);
	prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); /* IMPORTANT!, see next line */
	Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New);
	prfs_SplitSetDeletedClauses(ScanSplit, Deleted);
	ScanStack = list_Cdr(ScanStack);
      }
      
      while (!list_Empty(New)) {
	Deleted = list_Nil();
	Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted),
			     Recover);
	New     = Deleted;
      }
      Recover = list_Nconc(Recover, 
		    split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel));
      Recover = list_Nconc(Recover,
			   split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel));
      
      prfs_SplitSetUsed(Split);
    }
    
    SplitLevel--;
    Scan = list_Cdr(Scan);
  }
  return Recover;
}


void split_DeleteClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level)
/**************************************************************
  INPUT:   A clause, a level and a proofsearch object
  RETURNS: Nothing.
  EFFECT:  <Clause> is deleted from the usable or worked off set
           and made unshared.
***************************************************************/
{
  if (clause_GetFlag(Clause,WORKEDOFF)) 
    prfs_ExtractWorkedOff(PS, Clause);
  else 
    prfs_ExtractUsable(PS, Clause);

  split_KeepClauseAtLevel(PS, Clause, Level);
}


void split_KeepClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level)
/**************************************************************
  INPUT:   A clause and a level as int.
  RETURNS: None.
  MEMORY:  A copy of clause is made and kept within the split stack.
***************************************************************/
{
  SPLIT  Split;

  Split = prfs_GetSplitOfLevel(Level, PS);
  prfs_SplitSetDeletedClauses(Split,list_Cons(Clause, prfs_SplitDeletedClauses(Split)));
}


LIST split_ExtractEmptyClauses(LIST Clauses, LIST* EmptyClauses)
/**************************************************************
  INPUT:   A list of clauses and a pointer to a list of empty clauses.
  RETURNS: <Clauses> without all empty clauses where the empty clauses
           are moved to <EmptyClauses>
  MEMORY:  Destructive on <Clauses>.
***************************************************************/
{
  LIST   Scan;
  CLAUSE Clause;

  for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) {
    Clause = (CLAUSE)list_Car(Scan);
    if (clause_IsEmptyClause(Clause)) {
      *EmptyClauses = list_Cons(Clause,*EmptyClauses);
      list_Rplaca(Scan,NULL);
    }
  }
  Clauses = list_PointerDeleteElement(Clauses,NULL);

  return Clauses;
}

CLAUSE split_SmallestSplitLevelClause(LIST Clauses)
/**************************************************************
  INPUT:   A non-empty list of clauses.
  RETURNS: The clause with the smallest split level.
***************************************************************/
{
  CLAUSE Result;

  Result  = (CLAUSE)list_Car(Clauses);
  Clauses = list_Cdr(Clauses);
  
  while (!list_Empty(Clauses)) {
    if (clause_SplitLevel(Result) > clause_SplitLevel(list_Car(Clauses)))
      Result  = list_Car(Clauses);
    Clauses = list_Cdr(Clauses);
  }

  return Result;
}