File: quantifier_test.cpp

package info (click to toggle)
mcrl2 201409.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd
  • size: 46,348 kB
  • ctags: 29,960
  • sloc: cpp: 213,160; ansic: 16,219; python: 13,238; yacc: 309; lex: 214; xml: 197; makefile: 83; sh: 82; pascal: 17
file content (182 lines) | stat: -rwxr-xr-x 8,688 bytes parent folder | download
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
// Author(s): Frank Stappers
// Copyright: see the accompanying file COPYING or copy at
// https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
/// \file list_test.cpp
/// \brief Basic regression test for quantifier expressions.

#include <boost/test/minimal.hpp>

#include "mcrl2/data/list.h"
#include "mcrl2/data/parse.h"
#include "mcrl2/data/rewriter.h"
#include "mcrl2/data/set.h"
#include "mcrl2/data/fset.h"
#include "mcrl2/data/standard.h"

#include "mcrl2/utilities/test_utilities.h"

using namespace mcrl2;
using namespace mcrl2::data;
using namespace mcrl2::data::sort_list;

void quantifier_expression_test(const std::string& expr1_text, const std::string& expr2_text, const data_specification& dataspec, const rewriter& r)
{
  data_expression expr1 = parse_data_expression(expr1_text, dataspec);
  data_expression expr2 = parse_data_expression(expr2_text, dataspec);
  std::cout << "Testing " << expr1_text << " <-> " << expr2_text << std::endl;
  if (r(expr1) != r(expr2))
  {
    std::cout << "--- ERROR ---\n";
    std::cout << " expr1    = " << expr1 << std::endl;
    std::cout << " expr2    = " << expr2 << std::endl;
    std::cout << " r(expr1) = " << r(expr1) << std::endl;
    std::cout << " r(expr2) = " << r(expr2) << std::endl;
    BOOST_CHECK(r(expr1) == r(expr2));
  }
}

void quantifier_expression_test(mcrl2::data::rewrite_strategy s)
{
  data_specification dataspec;
  rewriter r(dataspec, s);

  // tests for Bool
  quantifier_expression_test("exists x: Bool. x == false", "true", dataspec, r);
  quantifier_expression_test("forall x: Bool. x == false", "false", dataspec, r);
  quantifier_expression_test("exists x: Bool. x == true", "true", dataspec, r);
  quantifier_expression_test("forall x: Bool. x == true", "false", dataspec, r);
  quantifier_expression_test("forall x: Bool. x == true && x==false", "false", dataspec, r);
  quantifier_expression_test("exists x: Bool. x == true && x==false", "false", dataspec, r);
  quantifier_expression_test("forall x: Bool. x == true || x==false", "true", dataspec, r);
  quantifier_expression_test("exists x: Bool. x == true || x==false", "true", dataspec, r);
  quantifier_expression_test("forall x:Bool.exists y: Bool. x == y", "true", dataspec, r);
  quantifier_expression_test("exists x: Bool.forall y:Bool.x == y", "false", dataspec, r);
  quantifier_expression_test("forall b: Bool. b", "false", dataspec, r);

  // tests for Pos / Nat
  dataspec.add_context_sort(sort_nat::nat());
  dataspec.add_context_sort(sort_set::set_(sort_nat::nat()));
  r = rewriter(dataspec, s);
  quantifier_expression_test("exists x: Nat. (  x in {1,2,25,600} && 25 == x )", "true", dataspec, r);

  // This test depends on the naming of variables in the enumerator
  // quantifier_expression_test("forall x: Nat. exists y: Nat. y == x", "true", dataspec, r);

  quantifier_expression_test("forall x: Nat. x == 3", "false", dataspec, r);
  quantifier_expression_test("exists x: Nat. x == 3", "true", dataspec, r);
  quantifier_expression_test("forall x: Pos. exists y: Pos.x == y+1", "false", dataspec, r);
  quantifier_expression_test("forall x: Pos. exists y: Pos.x == y+1", "false", dataspec, r);
  /* Test 15. Test whether elimination of quantifiers also happens inside a term. */
  quantifier_expression_test("(exists x_0: Bool. false) && (forall x_0: Nat. true)", "false", dataspec, r);
  quantifier_expression_test("(forall x_0: Pos. true) || (exists x_0: Bool. false)", "true", dataspec, r);
  /* The test below is too complex for the enumerator to solve.
  quantifier_expression_test("forall x: Pos. exists y: Nat.x == y+1", "true", dataspec, r);
  */

/* These tests do not work with the new enumerator, since it does not handle data equalities.
  quantifier_expression_test("forall x:Pos.exists y1,y2:Pos.x==y1+y2", "false", dataspec, r);
  quantifier_expression_test("forall x:Nat.exists y1,y2:Nat.x==y1+y2", "true", dataspec, r);
*/

  // tests for struct / List
  dataspec = parse_data_specification("sort S = struct s1?is_s1 | s2?is_s2;"
                                      "sort T = struct t;"
                                      "sort L = List(T);");
  r = rewriter(dataspec, s);

  quantifier_expression_test("exists s: S.( is_s1(s) && is_s2(s) )", "false", dataspec, r);
  quantifier_expression_test("exists s: S.( s == s2 && is_s2(s) )", "true", dataspec, r);
  quantifier_expression_test("forall y: T. y in [t]", "true", dataspec, r);

/* Should work but takes too much time.
  dataspec = parse_data_specification(
  " sort A = struct ac( first: Bool, args: List(Bool));"
  " "
  " map COMM: List(Bool)#Bool#List(A) -> List(A);"
  "     COMM: List(Bool)#Bool#List(A)#(List(Bool)->FBag(Bool))#FBag(Bool) -> List(A);"
  "     MAC: List(Bool) -> FBag(Bool);"
  "     PART: List(A)#(List(Bool) -> FBag(Bool)) -> (List(Bool) -> FBag(Bool));"
  "     ELM: List(Bool)#Bool#List(A)#List(Bool)#List(Bool) -> List(A);"
  "     RM: A#List(A)->List(A);"
  " var func: List(Bool)->FBag(Bool);"
  "     as: List(A);"
  "     ca: Bool;"
  "     cal: List(Bool);"
  "     cal_const: List(Bool);"
  "     al: Bool;"
  "     lsa: List(A);"
  "     m: FBag(Bool);"
  "     args: List(Bool);"
  "     a, b: A;"
  " eqn PART( [] , func ) = func;"
  "     PART( a |> as , func ) = PART( as, func[ args(a) -> func(args(a)) + {first(a):1}]  );"
  "     MAC( [] ) = {:};"
  "     MAC( ca |> cal ) = {ca:1} + MAC(cal);"
  " "
  "     COMM( cal, al, lsa ) = COMM( cal, al, lsa,  PART( lsa, lambda x: List(Bool). {:} ), MAC(cal) );"
  "     COMM( cal, al, [] , func, m ) = [];"
  "     COMM( cal, al, a |> lsa, func, m ) = if( m <= func(args(a)), "
  "                                                      ELM( cal, al, a |> lsa, args(a) , cal ) , "
  "                                                      a |> COMM( cal, al, lsa, func, m)"
  "                                                    );"
  "     ELM( [] , al, lsa, args, cal_const ) = [ac(al, args)] ++ COMM( cal_const, al, lsa );"
  "     ELM( ca |> cal, al, lsa, args, cal_const ) = ELM( cal, al , RM( ac( ca ,args), lsa), args, cal_const );"
  "     RM( a, [] ) = [];"
  "     RM( a, b |> lsa ) = if(a == b , lsa,  b |> RM( a, lsa)) ;"
  );
  r = rewriter(dataspec, s);

  quantifier_expression_test("exists x_0: List(A). x_0 == [ac( false, []), ac(true, []), ac(false, [])] && [ac(true, []), ac(true, [])] == COMM([false, false], true, x_0, PART(x_0, lambda x: List(Bool). {:}), {false: 2}) ", "true", dataspec, r);
  quantifier_expression_test("exists x_0: List(A). [ac(true, []), ac(true, [])] == "
       "        COMM([false, false], true, x_0, PART(x_0, lambda x: List(Bool). {:}), {false: 2}) &&  "
       "        x_0 == [ac( false, []), ac(true, []), ac(false, [])]", "true", dataspec, r);
*/

  // tests for Set
  dataspec = parse_data_specification( "sort A = Set(Bool);");
  r = rewriter(dataspec, s);

  /* Test that exists and forall over a non enumerable sort (situation winter 2012)
     with a trivial predicate can still be reduced, by removing the variable. */
  quantifier_expression_test("exists x:Set(Bool). x==x", "true", dataspec, r);
  quantifier_expression_test("forall x:Set(Bool). x==x", "true", dataspec, r);
  quantifier_expression_test("exists x:Set(Bool). x!=x", "false", dataspec, r);
  quantifier_expression_test("forall x:Set(Bool). x!=x", "false", dataspec, r);
}

void quantifier_in_rewrite_rules_test(mcrl2::data::rewrite_strategy s)
{
  // The test below checks whether bound variables in rewrite rules are properly renamed
  // when substituting variables. In concreto, if the y in the eqn for f is substituted in
  // the body of g(x), then if y is substituted for x, the rhs of g(x) reduces to y!=y, or false.
  // The correct answer however is true, as f states taht for every boolean y there is an y' that
  // is not equal to it.
  data_specification dataspec = parse_data_specification(
                    "map f:Bool;\n"
                    "    g:Bool->Bool;\n"
                    "var x:Bool;\n"
                    "eqn f=forall y:Bool.g(y);\n"
                    "    g(x)=exists y:Bool.x!=y;\n");

  rewriter r(dataspec, s);
  quantifier_expression_test("f", "true", dataspec, r);
}


int test_main(int argc, char** argv)
{
  auto strategies = utilities::get_test_rewrite_strategies(false);
  for (auto strat = strategies.begin(); strat != strategies.end(); ++strat)
  {
    std::clog << "  Strategy: " << *strat << std::endl;
    quantifier_expression_test(*strat);
    quantifier_in_rewrite_rules_test(*strat);
  }

  return EXIT_SUCCESS;
}