GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/proof_checker.cpp Lines: 5 87 5.7 %
Date: 2021-09-29 Branches: 2 716 0.3 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Gereon Kremer, Aina Niemetz
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Implementation of NlExt proof checker.
14
 */
15
16
#include "theory/arith/nl/ext/proof_checker.h"
17
18
#include "expr/sequence.h"
19
#include "theory/arith/arith_utilities.h"
20
#include "theory/rewriter.h"
21
22
using namespace cvc5::kind;
23
24
namespace cvc5 {
25
namespace theory {
26
namespace arith {
27
namespace nl {
28
29
3
void ExtProofRuleChecker::registerTo(ProofChecker* pc)
30
{
31
3
  pc->registerChecker(PfRule::ARITH_MULT_SIGN, this);
32
3
  pc->registerChecker(PfRule::ARITH_MULT_TANGENT, this);
33
3
}
34
35
Node ExtProofRuleChecker::checkInternal(PfRule id,
36
                                        const std::vector<Node>& children,
37
                                        const std::vector<Node>& args)
38
{
39
  NodeManager* nm = NodeManager::currentNM();
40
  auto zero = nm->mkConst<Rational>(0);
41
  auto one = nm->mkConst<Rational>(1);
42
  auto mone = nm->mkConst<Rational>(-1);
43
  auto pi = nm->mkNullaryOperator(nm->realType(), Kind::PI);
44
  auto mpi = nm->mkNode(Kind::MULT, mone, pi);
45
  Trace("nl-ext-checker") << "Checking " << id << std::endl;
46
  for (const auto& c : children)
47
  {
48
    Trace("nl-ext-checker") << "\t" << c << std::endl;
49
  }
50
  if (id == PfRule::ARITH_MULT_SIGN)
51
  {
52
    Assert(children.empty());
53
    Assert(args.size() > 1);
54
    Node mon = args.back();
55
    std::map<Node, int> exps;
56
    std::vector<Node> premise = args;
57
    premise.pop_back();
58
    Assert(mon.getKind() == Kind::MULT
59
           || mon.getKind() == Kind::NONLINEAR_MULT);
60
    for (const auto& v : mon)
61
    {
62
      exps[v]++;
63
    }
64
    std::map<Node, int> signs;
65
    for (const auto& f : premise)
66
    {
67
      if (f.getKind() == Kind::NOT)
68
      {
69
        Assert(f[0].getKind() == Kind::EQUAL);
70
        Assert(f[0][1].isConst() && f[0][1].getConst<Rational>().isZero());
71
        Assert(signs.find(f[0][0]) == signs.end());
72
        signs.emplace(f[0][0], 0);
73
        continue;
74
      }
75
      Assert(f.getKind() == Kind::LT || f.getKind() == Kind::GT);
76
      Assert(f[1].isConst() && f[1].getConst<Rational>().isZero());
77
      Assert(signs.find(f[0]) == signs.end());
78
      signs.emplace(f[0], f.getKind() == Kind::LT ? -1 : 1);
79
    }
80
    int sign = 0;
81
    for (const auto& ve : exps)
82
    {
83
      auto sit = signs.find(ve.first);
84
      Assert(sit != signs.end());
85
      if (ve.second % 2 == 0)
86
      {
87
        Assert(sit->second == 0);
88
        if (sign == 0)
89
        {
90
          sign = 1;
91
        }
92
      }
93
      else
94
      {
95
        Assert(sit->second != 0);
96
        if (sign == 0)
97
        {
98
          sign = sit->second;
99
        }
100
        else
101
        {
102
          sign *= sit->second;
103
        }
104
      }
105
    }
106
    switch (sign)
107
    {
108
      case -1:
109
        return nm->mkNode(
110
            Kind::IMPLIES, nm->mkAnd(premise), nm->mkNode(Kind::GT, zero, mon));
111
      case 0:
112
        return nm->mkNode(Kind::IMPLIES,
113
                          nm->mkAnd(premise),
114
                          nm->mkNode(Kind::DISTINCT, mon, zero));
115
      case 1:
116
        return nm->mkNode(
117
            Kind::IMPLIES, nm->mkAnd(premise), nm->mkNode(Kind::GT, mon, zero));
118
      default: Assert(false); return Node();
119
    }
120
  }
121
  else if (id == PfRule::ARITH_MULT_TANGENT)
122
  {
123
    Assert(children.empty());
124
    Assert(args.size() == 6);
125
    Assert(args[0].getType().isReal());
126
    Assert(args[1].getType().isReal());
127
    Assert(args[2].getType().isReal());
128
    Assert(args[3].getType().isReal());
129
    Assert(args[4].getType().isReal());
130
    Assert(args[5].isConst() && args[5].getKind() == Kind::CONST_RATIONAL
131
           && args[5].getConst<Rational>().isIntegral());
132
    Node t = args[0];
133
    Node x = args[1];
134
    Node y = args[2];
135
    Node a = args[3];
136
    Node b = args[4];
137
    int sgn = args[5].getConst<Rational>().getNumerator().sgn();
138
    Assert(sgn == -1 || sgn == 1);
139
    Node tplane = nm->mkNode(Kind::MINUS,
140
                             nm->mkNode(Kind::PLUS,
141
                                        nm->mkNode(Kind::MULT, b, x),
142
                                        nm->mkNode(Kind::MULT, a, y)),
143
                             nm->mkNode(Kind::MULT, a, b));
144
    return nm->mkNode(
145
        Kind::EQUAL,
146
        nm->mkNode(sgn == -1 ? Kind::LEQ : Kind::GEQ, t, tplane),
147
        nm->mkNode(
148
            Kind::OR,
149
            nm->mkNode(Kind::AND,
150
                       nm->mkNode(Kind::LEQ, x, a),
151
                       nm->mkNode(sgn == -1 ? Kind::GEQ : Kind::LEQ, y, b)),
152
            nm->mkNode(Kind::AND,
153
                       nm->mkNode(Kind::GEQ, x, a),
154
                       nm->mkNode(sgn == -1 ? Kind::LEQ : Kind::GEQ, y, b))));
155
  }
156
  return Node::null();
157
}
158
159
}  // namespace nl
160
}  // namespace arith
161
}  // namespace theory
162
22746
}  // namespace cvc5