Initial revision
[ardour.git] / libs / cassowary / ClTests.cc
1 // $Id$
2 //
3 // Cassowary Incremental Constraint Solver
4 // Original Smalltalk Implementation by Alan Borning
5 // This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
6 // http://www.cs.washington.edu/homes/gjb
7 // (C) 1998, 1999 Greg J. Badros and Alan Borning
8 // See ../LICENSE for legal details regarding this software
9 // 
10 // ClTests.cc
11
12 #include <cassowary/Cl.h>
13 #include <stdlib.h>
14 #include <cassowary/timer.h>
15 #include <iostream>
16 #include <iomanip>
17
18 inline 
19 double UniformRandom()
20 { return double(rand())/RAND_MAX; }
21
22
23 bool
24 simple1()
25 {
26  try
27    {
28    bool fOkResult = true;
29    ClVariable x(167);
30    ClVariable y(2);
31    ClSimplexSolver solver;
32
33    ClLinearEquation eq(x,y+0.0);
34    solver.AddStay(x);
35    solver.AddStay(y);
36    solver.AddConstraint(eq);
37    cout << "x = " << x.Value() << endl
38         << "y = " << y.Value() << endl;
39    fOkResult = (x.Value() == y.Value());
40    return fOkResult;
41    } 
42  catch (ExCLError &error) 
43    {
44    cerr << "Exception! " << error.description() << endl;
45    return(false);
46    } 
47  catch (...) 
48    {
49    cerr << "Unknown exception" << endl;
50    return(false);
51    }
52 }
53
54
55 /* Add an edit variable to an empty solver */
56 bool
57 simple2()
58 {
59  try
60    {
61    ClVariable x(167);
62    ClSimplexSolver solver;
63
64    solver.AddEditVar(x);
65    solver.BeginEdit();
66    solver.SuggestValue(x,100);
67    solver.EndEdit();
68
69    cout << "x = " << x.Value() << endl;
70    } 
71  catch (ExCLEditMisuse &error)
72    {
73    cout << "Success: got the exception" << endl;
74    return true;
75    }
76  catch (ExCLError &error) 
77    {
78    cerr << "Exception! " << error.description() << endl;
79    return(false);
80    } 
81  catch (...) 
82    {
83    cerr << "Unknown exception" << endl;
84    return(false);
85    }
86  cerr << "Should have gotten an exception!" << endl;
87  return false;
88 }
89
90
91 bool
92 justStay1()
93 {
94  try
95    {
96    bool fOkResult = true;
97    ClVariable x(5);
98    ClVariable y(10);
99    ClSimplexSolver solver;
100
101 #if 0
102    solver.AddPointStay(x,y,1);
103 #else
104    solver.AddStay(x);
105    solver.AddStay(y);
106 #endif
107    fOkResult = fOkResult && ClApprox(x,5);
108    fOkResult = fOkResult && ClApprox(y,10);
109    cout << "x == " << x.Value() << endl;
110    cout << "y == " << y.Value() << endl;
111
112    return(fOkResult);
113    } 
114  catch (ExCLError &error) 
115    {
116    cerr << "Exception! " << error.description() << endl;
117    return(false);
118    } 
119  catch (...) 
120    {
121    cerr << "Unknown exception" << endl;
122    return(false);
123    }
124 }
125
126
127
128 bool
129 addDelete1()
130 {
131  try 
132    {
133    bool fOkResult = true; 
134    ClVariable x("x");
135    ClSimplexSolver solver;
136
137    solver.AddConstraint(new ClLinearEquation( x, 100, ClsWeak() ));
138     
139    ClLinearInequality c10(x,cnLEQ,10.0);
140    ClLinearInequality c20(x,cnLEQ,20.0);
141    solver
142      .AddConstraint(c10)
143      .AddConstraint(c20);
144
145    fOkResult = fOkResult && ClApprox(x,10.0);
146    cout << "x == " << x.Value() << endl;
147
148    cout << endl << solver << endl;
149
150    solver.RemoveConstraint(c10);
151
152    cout << endl << solver << endl;
153
154    fOkResult = fOkResult && ClApprox(x,20.0);
155    cout << "x == " << x.Value() << endl;
156
157    solver.RemoveConstraint(c20);
158    fOkResult = fOkResult && ClApprox(x,100.0);
159    cout << "x == " << x.Value() << endl;
160
161    ClLinearInequality c10again(x,cnLEQ,10.0);
162
163    solver
164      .AddConstraint(c10)
165      .AddConstraint(c10again);
166
167    fOkResult = fOkResult && ClApprox(x,10.0);
168    cout << "x == " << x.Value() << endl;
169     
170    solver.RemoveConstraint(c10);
171    fOkResult = fOkResult && ClApprox(x,10.0);
172    cout << "x == " << x.Value() << endl;
173
174    solver.RemoveConstraint(c10again);
175    fOkResult = fOkResult && ClApprox(x,100.0);
176    cout << "x == " << x.Value() << endl;
177
178    return(fOkResult);
179    } 
180  catch (ExCLError &error) 
181    {
182    cerr << "Exception! " << error.description() << endl;
183    return(false);
184    } 
185  catch (...) 
186    {
187    cerr << "Unknown exception" << endl;
188    return(false);
189    }
190 }
191
192 bool
193 addDelete2()
194 {
195  try 
196    {
197    bool fOkResult = true; 
198    ClVariable x("x");
199    ClVariable y("y");
200    ClSimplexSolver solver;
201
202    solver
203      .AddConstraint(new ClLinearEquation(x, 100.0, ClsWeak()))
204      .AddConstraint(new ClLinearEquation(y, 120.0, ClsStrong()));
205
206    ClLinearInequality c10(x,cnLEQ,10.0);
207    ClLinearInequality c20(x,cnLEQ,20.0);
208
209    solver
210      .AddConstraint(c10)
211      .AddConstraint(c20);
212    fOkResult = fOkResult && ClApprox(x,10.0) && ClApprox(y,120.0);
213    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
214
215    solver.RemoveConstraint(c10);
216    fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,120.0);
217    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
218    
219    ClLinearEquation cxy( 2*x, y);
220    solver.AddConstraint(cxy);
221    fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,40.0);
222    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
223
224    solver.RemoveConstraint(c20);
225    fOkResult = fOkResult && ClApprox(x,60.0) && ClApprox(y,120.0);
226    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
227
228    solver.RemoveConstraint(cxy);
229    fOkResult = fOkResult && ClApprox(x,100.0) && ClApprox(y,120.0);
230    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
231
232
233    return(fOkResult);
234    } 
235  catch (ExCLError &error) 
236    {
237    cerr << "Exception! " << error.description() << endl;
238    return(false);
239    }
240  catch (...) 
241    {
242    cerr << "Unknown exception" << endl;
243    return(false);
244    }
245 }
246
247 bool
248 casso1()
249 {
250  try 
251    {
252    bool fOkResult = true; 
253    ClVariable x("x");
254    ClVariable y("y");
255    ClSimplexSolver solver;
256
257    solver
258      .AddConstraint(new ClLinearInequality(x,cnLEQ,y))
259      .AddConstraint(new ClLinearEquation(y, x+3.0))
260      .AddConstraint(new ClLinearEquation(x,10.0,ClsWeak()))
261      .AddConstraint(new ClLinearEquation(y,10.0,ClsWeak()))
262      ;
263    
264    fOkResult = fOkResult && 
265      ( ClApprox(x,10.0) && ClApprox(y,13.0) ||
266        ClApprox(x,7.0) && ClApprox(y,10.0) );
267      
268    cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
269
270    return(fOkResult);
271    } 
272  catch (ExCLError &error) 
273    {
274    cerr << "Exception! " << error.description() << endl;
275    return(false);
276    }
277  catch (...) 
278    {
279    cerr << "Unknown exception" << endl;
280    return(false);
281    }
282 }
283
284 bool
285 inconsistent1()
286 {
287   ClSimplexSolver solver;
288   ClVariable x("x");
289   ClLinearEquation eq1(x,10.0);
290   ClLinearEquation eq2(x,5.0);
291   try 
292     {
293     
294     solver.AddConstraint( eq1 );
295     solver.AddConstraint( eq2 );
296     
297     // no exception, we failed!
298     return(false);
299     } 
300   catch (ExCLRequiredFailure)
301     {
302     // we want this exception to get thrown
303     cout << "Success -- got the exception" << endl;
304     // solver.RemoveConstraint(eq2); this would throw a constraint not found exception
305     //    cout << solver << endl;
306     return(true);
307     }
308   catch (ExCLError &error) 
309     {
310     cerr << "Exception! " << error.description() << endl;
311     return(false);
312     }
313   catch (...) 
314     {
315     cerr << "Unknown exception" << endl;
316     return(false);
317     }
318 }
319
320 bool
321 inconsistent2()
322 {
323  try 
324    {
325    ClVariable x("x");
326    ClSimplexSolver solver;
327
328    solver
329      .AddConstraint(new ClLinearInequality(x,cnGEQ,10.0))
330      .AddConstraint(new ClLinearInequality(x,cnLEQ, 5.0));
331
332    // no exception, we failed!
333    return(false);
334    } 
335  catch (ExCLRequiredFailure &)
336    {
337    // we want this exception to get thrown
338    cout << "Success -- got the exception" << endl;
339    //    cout << solver << endl;
340    return(true);
341    }
342  catch (ExCLError &error) 
343    {
344    cerr << "Exception! " << error.description() << endl;
345    return(false);
346    }
347  catch (...) 
348    {
349    cerr << "Unknown exception" << endl;
350    return(false);
351    }
352 }
353
354 bool
355 inconsistent3()
356 {
357  try 
358    {
359    ClVariable w("w");
360    ClVariable x("x");
361    ClVariable y("y");
362    ClVariable z("z");
363    ClSimplexSolver solver;
364
365    solver
366      .AddConstraint(new ClLinearInequality(w,cnGEQ,10.0))
367      .AddConstraint(new ClLinearInequality(x,cnGEQ,w))
368      .AddConstraint(new ClLinearInequality(y,cnGEQ,x))
369      .AddConstraint(new ClLinearInequality(z,cnGEQ,y))
370      .AddConstraint(new ClLinearInequality(z,cnLEQ,4.0));
371
372    // no exception, we failed!
373    return(false);
374    } 
375  catch (ExCLRequiredFailure &)
376    {
377    // we want this exception to get thrown
378    cout << "Success -- got the exception" << endl;
379    //    cout << solver << endl;
380    return(true);
381    }
382  catch (ExCLError &error) 
383    {
384    cerr << "Exception! " << error.description() << endl;
385    return(false);
386    }
387  catch (...) 
388    {
389    cerr << "Unknown exception" << endl;
390    return(false);
391    }
392 }
393
394
395 bool
396 multiedit()
397 {
398  try
399    {
400    bool fOkResult = true;
401
402    ClVariable x("x",0);
403    ClVariable y("y",0);
404    ClVariable w("w",0);
405    ClVariable h("h",0);
406    ClSimplexSolver solver;
407
408    solver
409      .AddStay(x)
410      .AddStay(y)
411      .AddStay(w)
412      .AddStay(h);
413
414    solver
415      .AddEditVar(x)
416      .AddEditVar(y)
417      .BeginEdit();
418
419    solver
420      .SuggestValue(x,10)
421      .SuggestValue(y,20)
422      .Resolve();
423
424    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
425         << "w = " << w.Value() << "; h = " << h.Value() << endl;
426
427    fOkResult = fOkResult &&
428      ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
429
430    solver
431      .AddEditVar(w)
432      .AddEditVar(h)
433      .BeginEdit();
434
435    solver
436      .SuggestValue(w,30)
437      .SuggestValue(h,40)
438      .EndEdit();
439
440    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
441         << "w = " << w.Value() << "; h = " << h.Value() << endl;
442
443    fOkResult = fOkResult &&
444      ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
445
446    solver
447      .SuggestValue(x,50)
448      .SuggestValue(y,60)
449      .EndEdit();
450
451    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
452         << "w = " << w.Value() << "; h = " << h.Value() << endl;
453
454    fOkResult = fOkResult &&
455      ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
456
457    return fOkResult;
458    } 
459  catch (ExCLError &error) 
460    {
461    cerr << "Exception! " << error.description() << endl;
462    return(false);
463    } 
464  catch (...) 
465    {
466    cerr << "Unknown exception" << endl;
467    return(false);
468    }
469  cerr << "Should have gotten an exception!" << endl;
470  return false;
471 }
472
473
474 bool
475 multiedit2()
476 {
477  try
478    {
479    bool fOkResult = true;
480
481    ClVariable x("x",0);
482    ClVariable y("y",0);
483    ClVariable w("w",0);
484    ClVariable h("h",0);
485    ClSimplexSolver solver;
486
487    solver
488      .AddStay(x)
489      .AddStay(y)
490      .AddStay(w)
491      .AddStay(h);
492
493    solver
494      .AddEditVar(x)
495      .AddEditVar(y)
496      .BeginEdit();
497
498    solver
499      .SuggestValue(x,10)
500      .SuggestValue(y,20)
501      .Resolve();
502
503    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
504         << "w = " << w.Value() << "; h = " << h.Value() << endl;
505
506    fOkResult = fOkResult &&
507      ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
508
509    solver
510      .AddEditVar(x)
511      .AddEditVar(y)
512      .AddEditVar(w)
513      .AddEditVar(h)
514      .BeginEdit();
515
516    solver
517      .SuggestValue(w,30)
518      .SuggestValue(h,40)
519      .EndEdit();
520
521    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
522         << "w = " << w.Value() << "; h = " << h.Value() << endl;
523
524    fOkResult = fOkResult &&
525      ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
526
527    solver
528      .SuggestValue(x,50)
529      .SuggestValue(y,60)
530      .EndEdit();
531
532    cout << "x = " << x.Value() << "; y = " << y.Value() << endl
533         << "w = " << w.Value() << "; h = " << h.Value() << endl;
534
535    fOkResult = fOkResult &&
536      ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
537
538    return fOkResult;
539    } 
540  catch (ExCLError &error) 
541    {
542    cerr << "Exception! " << error.description() << endl;
543    return(false);
544    } 
545  catch (...) 
546    {
547    cerr << "Unknown exception" << endl;
548    return(false);
549    }
550  cerr << "Should have gotten an exception!" << endl;
551  return false;
552 }
553
554
555 // From a bug report from Steve Wolfman on his
556 // SAT project using "blackbox"
557 bool
558 blackboxsat()
559 {
560   try
561     {
562     ClSimplexSolver solver;
563
564     ClVariable r1("r1");
565     ClVariable r2("r2");
566     ClVariable r3("r3");
567     ClVariable r4("r4");
568     ClVariable r5("r5");
569     ClVariable r6("r6");
570     ClVariable r7("r7");
571     ClVariable r8("r8");
572
573     ClConstraint *rgpcn[30];
574     for (int i=0; i<int(sizeof(rgpcn)/sizeof(rgpcn[0])); ++i)
575       rgpcn[i] = NULL;
576
577     rgpcn[1] = new ClLinearEquation(r1,60);
578     rgpcn[2] = new ClLinearEquation(r2,30);
579     rgpcn[12] = new ClLinearEquation(r3,2.5);
580     rgpcn[13] = new ClLinearEquation(r6,0);
581     rgpcn[14] = new ClLinearInequality(r5, cnGEQ, 0);
582     rgpcn[15] = new ClLinearInequality(r8, cnLEQ, 2.5);
583     rgpcn[16] = new ClLinearInequality(r7, cnGEQ, r6);
584     rgpcn[17] = new ClLinearInequality(r8, cnGEQ, r7);
585     rgpcn[18] = new ClLinearEquation(r4, r3 - r2/60.0);
586     rgpcn[19] = new ClLinearEquation(r5, r4 - r1/60.0);
587     rgpcn[20] = new ClLinearInequality(r4, cnGEQ, 0);
588     rgpcn[21] = new ClLinearInequality(r5, cnGEQ, 0);
589     rgpcn[22] = new ClLinearEquation(r7, r6 + r2/20.0);
590     rgpcn[23] = new ClLinearEquation(r8, r7 + r1/20.0);
591     rgpcn[24] = new ClLinearEquation(r4, r3 - r2/30.0);
592     rgpcn[25] = new ClLinearEquation(r5, r4 - r1/30.0);
593     rgpcn[26] = new ClLinearInequality(r4, cnGEQ, 0);
594     rgpcn[27] = new ClLinearInequality(r5, cnGEQ, 0);
595     rgpcn[28] = new ClLinearEquation(r7, r6 + r2/60.0);
596     rgpcn[29] = new ClLinearEquation(r8, r7 + r1/60.0);
597
598     while (true)
599       {
600       char szCmd[1000];
601       int i;
602       cin >> szCmd;
603       if (!cin)
604         break;
605       if (szCmd[0] == '#')
606         { 
607         cin.getline(szCmd,900);
608         continue;
609         }
610       if (strcasecmp(szCmd,"Add") == 0)
611         {
612         cin >> i;
613         cout << "eq" << i << ": " << solver.AddConstraintNoException(rgpcn[i])
614              << "\t" << *(rgpcn[i]) << endl;
615         cout << r1 << " = " << r1.Value() << endl;
616         }
617       else if (strcasecmp(szCmd,"del") == 0)
618         {
619         cin >> i;
620         cout << "REMeq" << i << ": " << solver.RemoveConstraintNoException(rgpcn[i])
621              << "\t" << *(rgpcn[i]) << endl;
622         cout << r1 << " = " << r1.Value() << endl;
623         }
624       else if (strcasecmp(szCmd,"dump") == 0)
625         {
626         cout << solver << endl;
627         }
628       else if (strcasecmp(szCmd,"val") == 0)
629         {
630         cout << r1 << " = " << r1.Value() << endl;
631         }
632       else if (strcasecmp(szCmd,"solve") == 0)
633         {
634         cout << solver.Solve() << endl;
635         }
636       else if (strcasecmp(szCmd,"autosolve") == 0)
637         {
638         solver.SetAutosolve(true);
639         }
640       else if (strcasecmp(szCmd,"noautosolve") == 0)
641         {
642         solver.SetAutosolve(true);
643         }
644       }
645
646     cout << r1 << " = " << r1.Value() << endl
647          << r2 << " = " << r2.Value() << endl
648          << r3 << " = " << r3.Value() << endl
649          << r4 << " = " << r4.Value() << endl
650          << r5 << " = " << r5.Value() << endl
651          << r6 << " = " << r6.Value() << endl
652          << r7 << " = " << r7.Value() << endl
653          << r8 << " = " << r8.Value() << endl;
654
655     return false;
656     }
657   catch (ExCLError &error)
658     {
659    cerr << "Exception! " << error.description() << endl;
660    return(true);
661    }
662  catch (...) 
663    {
664    cerr << "Unknown exception" << endl;
665    return(false);
666    }
667 }
668
669 typedef ClVariable *PClVariable;
670
671 bool
672 addDel(const int nCns = 900, const int nVars = 900, const int nResolves = 10000)
673 //addDel(int nCns = 300, int nVars = 300, int nResolves = 1000)
674 //addDel(int nCns = 30, int nVars = 30, int nResolves = 100)
675 {
676   Timer timer;
677   // FIXGJB: from where did .12 come?
678   static const double ineqProb = 0.12;
679   static const int maxVars = 3;
680
681   cout << "starting timing test. nCns = " << nCns
682        << ", nVars = " << nVars << ", nResolves = " << nResolves << endl;
683
684   timer.Start();
685   ClSimplexSolver solver;
686   solver.SetAutosolve(false);
687
688   ClVariable **rgpclv = new PClVariable[nVars];
689   for (int i = 0; i < nVars; i++)
690     {
691     rgpclv[i] = new ClVariable(i,"x");
692     solver.AddStay(*rgpclv[i]);
693     }
694
695   ClConstraint **rgpcns = new PClConstraint[nCns];
696   int nvs = 0;
697   int k;
698   int j;
699   double coeff;
700   for (j = 0; j < nCns; j++)
701     {
702     // number of variables in this constraint
703     nvs = int(UniformRandom()*maxVars) + 1;
704     ClLinearExpression expr = UniformRandom()*20.0 - 10.0;
705     for (k = 0; k < nvs; k++)
706        {
707        coeff = UniformRandom()*10 - 5;
708        expr.AddExpression(*(rgpclv[int(UniformRandom()*nVars)]) * coeff);
709        }
710     if (UniformRandom() < ineqProb)
711        {
712        rgpcns[j] = new ClLinearInequality(expr);
713        }
714     else
715        {  
716        rgpcns[j] = new ClLinearEquation(expr);
717        }
718 #ifdef CL_SHOW_CNS_IN_BENCHMARK
719     cout << "Cn[" << j << "]: " << *rgpcns[j] << endl;
720 #endif
721     }
722
723   cout << "done building data structures" << endl;
724   cout << "time = " << timer.ElapsedTime() << "\n" << endl;
725   timer.Start();
726   int cExceptions = 0;
727 #ifdef CL_SHOW_CNS_IN_BENCHMARK
728   cout << "Exceptions on: ";
729 #endif
730   for (j = 0; j < nCns; j++)
731     {
732     // Add the constraint -- if it's incompatible, just ignore it
733     try
734       {
735       solver.AddConstraint(rgpcns[j]);
736       }
737     catch (ExCLRequiredFailure &)
738       {
739       cExceptions++;
740       rgpcns[j] = NULL;
741 #ifdef CL_SHOW_CNS_IN_BENCHMARK
742       cout << j << " ";
743 #endif
744       }
745     }
746 #ifdef CL_SHOW_CNS_IN_BENCHMARK
747   cout << "\n" << endl;
748 #endif
749   solver.Solve();
750   cout << "done adding constraints [" << cExceptions << " exceptions]" << endl;
751   cout << "time = " << timer.ElapsedTime() << "\n" << endl;
752   cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" << endl;
753   cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
754   timer.Start();
755
756   int e1Index = int(UniformRandom()*nVars);
757   int e2Index = int(UniformRandom()*nVars);
758
759   ClVariable e1 = *(rgpclv[e1Index]);
760   ClVariable e2 = *(rgpclv[e2Index]);
761
762   solver
763     .AddEditVar(e1)
764     .AddEditVar(e2);
765
766   cout << "done creating edit constraints -- about to start resolves" << endl;
767   cout << "time = " << timer.ElapsedTime() << "\n" << endl;
768   timer.Start();
769
770   solver.BeginEdit();
771   // FIXGJB start = Timer.now();
772   for (int m = 0; m < nResolves; ++m)
773     {
774     solver
775       .SuggestValue(e1,e1->Value()*1.001)
776       .SuggestValue(e2,e2->Value()*1.001)
777       .Resolve();
778     }
779   solver.EndEdit();
780   // cout << "run time: " <<
781
782   cout << "done resolves -- now removing constraints" << endl;
783   cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
784   cout << "time per Resolve = " << timer.ElapsedTime()/nResolves << "\n" <<endl;
785   
786   timer.Start();
787
788   for (j = 0; j < nCns; j++)
789     {
790     if (rgpcns[j])
791       {
792       solver.RemoveConstraint(rgpcns[j]);
793       }
794     }
795
796   // FIXGJB end = Timer.now();
797   // cout << "Total remove time: " 
798   //      << "remove time per cn"
799   cout << "done removing constraints and addDel timing test" << endl;
800   cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
801   cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" <<endl;
802   cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
803
804   for (int i = 0; i < nVars; i++)
805     {
806     delete rgpclv[i];
807     }
808
809   for (int j = 0; j < nCns; j++)
810     {
811     delete rgpcns[j];
812     }
813
814   return true;
815 }
816
817
818 int
819 main( int argc, char **argv )
820 {
821   try 
822     {
823     bool fAllOkResult = true;
824     bool fResult;
825     
826     // seed the random number generator for reproducible results
827     srand(123456789);
828
829     cout << "Cassowary version: " << szCassowaryVersion << endl;
830
831 #define RUN_TEST(x) \
832     cout << #x << ":" << endl; \
833     fResult = x(); fAllOkResult &= fResult; \
834     if (!fResult) cout << "Failed!" << endl;
835
836     RUN_TEST(simple1);
837     RUN_TEST(simple2);
838     RUN_TEST(justStay1);
839     RUN_TEST(addDelete1);
840     RUN_TEST(addDelete2);
841     RUN_TEST(casso1);
842     RUN_TEST(inconsistent1);
843     RUN_TEST(inconsistent2);
844     RUN_TEST(inconsistent3);
845     RUN_TEST(multiedit);
846     RUN_TEST(multiedit2);
847     // RUN_TEST(blackboxsat);
848
849     int cns = 90, vars = 90, resolves = 100;
850
851     if (argc > 1)
852       cns = atoi(argv[1]);
853
854     if (argc > 2)
855       vars = atoi(argv[2]);
856
857     if (argc > 3)
858       resolves = atoi(argv[3]);
859
860     if (cns > 0) 
861       {
862       cout << "addDel" << ":" << endl;
863       fResult = addDel(cns,vars,resolves); fAllOkResult &= fResult;
864       if (!fResult) cout << "Failed!" << endl;
865       }
866       
867 #undef RUN_TEST
868
869 #ifdef CL_FIND_LEAK
870     cout << "ClAbstractVariables: " << ClAbstractVariable::cAbstractVariables
871          << "\nClDummyVariables: " << ClDummyVariable::cDummyVariables
872          << "\nClSlackVariables: " << ClSlackVariable::cSlackVariables
873          << endl;
874 #endif
875
876     
877     return (fAllOkResult? 0 : 255);
878     
879     } 
880   catch (...) 
881     {
882     cerr << "exception!" << endl;
883     }
884 }