LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/main - command_executor.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 107 72.9 %
Date: 2025-01-29 12:48:36 Functions: 10 13 76.9 %
Branches: 66 96 68.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Gereon Kremer, Morgan Deters
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 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                 :            :  * An additional layer between commands and invoking them.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "main/command_executor.h"
      17                 :            : 
      18                 :            : #ifndef __WIN32__
      19                 :            : #  include <sys/resource.h>
      20                 :            : #endif /* ! __WIN32__ */
      21                 :            : 
      22                 :            : #include <cvc5/cvc5_parser.h>
      23                 :            : 
      24                 :            : #include <iomanip>
      25                 :            : #include <iostream>
      26                 :            : #include <memory>
      27                 :            : #include <string>
      28                 :            : #include <vector>
      29                 :            : 
      30                 :            : #include "base/output.h"
      31                 :            : #include "main/main.h"
      32                 :            : #include "parser/commands.h"
      33                 :            : #include "smt/solver_engine.h"
      34                 :            : 
      35                 :            : using namespace cvc5::parser;
      36                 :            : 
      37                 :            : namespace cvc5::main {
      38                 :            : 
      39                 :            : // Function to cancel any (externally-imposed) limit on CPU time.
      40                 :            : // This is used for competitions while a solution (proof or model)
      41                 :            : // is being dumped (so that we don't give "sat" or "unsat" then get
      42                 :            : // interrupted partway through outputting a proof!).
      43                 :          0 : void setNoLimitCPU() {
      44                 :            :   // Windows doesn't have these things, just ignore
      45                 :            : #ifndef __WIN32__
      46                 :            :   struct rlimit rlc;
      47                 :          0 :   int st = getrlimit(RLIMIT_CPU, &rlc);
      48         [ -  - ]:          0 :   if(st == 0) {
      49                 :          0 :     rlc.rlim_cur = rlc.rlim_max;
      50                 :          0 :     setrlimit(RLIMIT_CPU, &rlc);
      51                 :            :   }
      52                 :            : #endif /* ! __WIN32__ */
      53                 :          0 : }
      54                 :            : 
      55                 :      27489 : CommandExecutor::CommandExecutor(std::unique_ptr<cvc5::Solver>& solver)
      56                 :            :     : d_solver(solver),
      57                 :      27489 :       d_symman(new SymbolManager(d_solver->getTermManager())),
      58                 :            :       d_result(),
      59                 :      54978 :       d_parseOnly(false)
      60                 :            : {
      61                 :      27489 : }
      62                 :      54978 : CommandExecutor::~CommandExecutor()
      63                 :            : {
      64                 :      54978 : }
      65                 :            : 
      66                 :      23615 : void CommandExecutor::storeOptionsAsOriginal()
      67                 :            : {
      68                 :      23615 :   d_solver->d_originalOptions->copyValues(d_solver->d_slv->getOptions());
      69                 :            :   // cache the value of parse-only, which is set by the command line only
      70                 :            :   // and thus will not change in a run.
      71                 :      23615 :   d_parseOnly = d_solver->getOptionInfo("parse-only").boolValue();
      72                 :      23615 : }
      73                 :            : 
      74                 :      89345 : void CommandExecutor::setOptionInternal(const std::string& key,
      75                 :            :                                         const std::string& value)
      76                 :            : {
      77                 :            :   // set option, marked not from user.
      78                 :      89345 :   d_solver->d_slv->setOption(key, value, false);
      79                 :      89345 : }
      80                 :            : 
      81                 :      23567 : void CommandExecutor::printStatistics(std::ostream& out) const
      82                 :            : {
      83         [ -  + ]:      23567 :   if (d_solver->getOptionInfo("stats").boolValue())
      84                 :            :   {
      85                 :            :     {
      86                 :          0 :       const auto& stats = d_solver->getStatistics();
      87                 :            :       auto it =
      88                 :          0 :           stats.begin(d_solver->getOptionInfo("stats-internal").boolValue(),
      89                 :          0 :                       d_solver->getOptionInfo("stats-all").boolValue());
      90         [ -  - ]:          0 :       for (; it != stats.end(); ++it)
      91                 :            :       {
      92                 :          0 :         out << it->first << " = " << it->second << std::endl;
      93                 :            :       }
      94                 :            :     }
      95                 :            :     {
      96                 :          0 :       const auto& stats = d_solver->getTermManager().getStatistics();
      97                 :            :       auto it =
      98                 :          0 :           stats.begin(d_solver->getOptionInfo("stats-internal").boolValue(),
      99                 :          0 :                       d_solver->getOptionInfo("stats-all").boolValue());
     100         [ -  - ]:          0 :       for (; it != stats.end(); ++it)
     101                 :            :       {
     102                 :          0 :         out << it->first << " = " << it->second << std::endl;
     103                 :            :       }
     104                 :            :     }
     105                 :            :   }
     106                 :      23567 : }
     107                 :            : 
     108                 :          0 : void CommandExecutor::printStatisticsSafe(int fd) const
     109                 :            : {
     110         [ -  - ]:          0 :   if (d_solver->getOptionInfo("stats").boolValue())
     111                 :            :   {
     112                 :          0 :     d_solver->getTermManager().printStatisticsSafe(fd);
     113                 :          0 :     d_solver->printStatisticsSafe(fd);
     114                 :            :   }
     115                 :          0 : }
     116                 :            : 
     117                 :     701037 : bool CommandExecutor::doCommand(Command* cmd)
     118                 :            : {
     119                 :            :   // formerly was guarded by verbosity > 2
     120         [ +  - ]:     701037 :   Trace("cmd-exec") << "Invoking: " << *cmd << std::endl;
     121                 :     701037 :   return doCommandSingleton(cmd->d_cmd.get());
     122                 :            : }
     123                 :            : 
     124                 :          0 : void CommandExecutor::reset()
     125                 :            : {
     126                 :          0 :   printStatistics(d_solver->getDriverOptions().err());
     127                 :          0 :   Cmd::resetSolver(d_solver.get());
     128                 :          0 : }
     129                 :            : 
     130                 :     705659 : bool CommandExecutor::doCommandSingleton(Cmd* cmd)
     131                 :            : {
     132                 :     705659 :   bool status = solverInvoke(d_solver.get(),
     133                 :            :                              d_symman->toSymManager(),
     134                 :            :                              cmd,
     135                 :     705661 :                              d_solver->getDriverOptions().out());
     136                 :            : 
     137                 :    1411310 :   cvc5::Result res;
     138                 :     705657 :   bool hasResult = false;
     139         [ +  - ]:     705657 :   const CheckSatCommand* cs = dynamic_cast<const CheckSatCommand*>(cmd);
     140         [ +  + ]:     705657 :   if (cs != nullptr)
     141                 :            :   {
     142                 :      26961 :     d_result = res = cs->getResult();
     143                 :      26961 :     hasResult = true;
     144                 :            :   }
     145                 :            :   const CheckSatAssumingCommand* csa =
     146         [ +  - ]:     705657 :       dynamic_cast<const CheckSatAssumingCommand*>(cmd);
     147         [ +  + ]:     705657 :   if (csa != nullptr)
     148                 :            :   {
     149                 :       4453 :     d_result = res = csa->getResult();
     150                 :       4453 :     hasResult = true;
     151                 :            :   }
     152                 :            : 
     153                 :            :   // if we didnt set a result, return the status
     154         [ +  + ]:     705657 :   if (!hasResult)
     155                 :            :   {
     156                 :     674243 :     return status;
     157                 :            :   }
     158                 :            : 
     159                 :            :   // dump the model/proof/unsat core if option is set
     160         [ +  + ]:      31414 :   if (status) {
     161                 :      31367 :     bool isResultUnsat = res.isUnsat();
     162                 :      31367 :     bool isResultSat = res.isSat();
     163                 :      62734 :     std::vector<std::unique_ptr<Cmd> > getterCommands;
     164                 :      62734 :     if (d_solver->getOptionInfo("dump-models").boolValue()
     165 [ +  + ][ +  + ]:      62744 :         && (isResultSat
                 [ +  - ]
     166         [ -  + ]:         10 :             || (res.isUnknown()
     167         [ -  - ]:          0 :                 && res.getUnknownExplanation()
     168                 :            :                        == cvc5::UnknownExplanation::INCOMPLETE)))
     169                 :            :     {
     170                 :         10 :       getterCommands.emplace_back(new GetModelCommand());
     171                 :            :     }
     172                 :      31367 :     if (d_solver->getOptionInfo("dump-proofs").boolValue() && isResultUnsat)
     173                 :            :     {
     174                 :       4582 :       getterCommands.emplace_back(new GetProofCommand());
     175                 :            :     }
     176                 :            : 
     177                 :      62734 :     if ((d_solver->getOptionInfo("dump-instantiations").boolValue()
     178                 :      62710 :          || d_solver->getOptionInfo("dump-instantiations-debug").boolValue())
     179 [ +  + ][ +  + ]:      94077 :         && GetInstantiationsCommand::isEnabled(d_solver.get(), res))
                 [ +  + ]
     180                 :            :     {
     181                 :         14 :       getterCommands.emplace_back(new GetInstantiationsCommand());
     182                 :            :     }
     183                 :            : 
     184                 :      62734 :     if (d_solver->getOptionInfo("dump-unsat-cores").boolValue()
     185 [ +  + ][ +  + ]:      62734 :         && isResultUnsat)
                 [ +  - ]
     186                 :            :     {
     187                 :          4 :       getterCommands.emplace_back(new GetUnsatCoreCommand());
     188                 :            :     }
     189                 :            : 
     190                 :      62734 :     if (d_solver->getOptionInfo("dump-unsat-cores-lemmas").boolValue()
     191 [ -  + ][ -  - ]:      62734 :         && isResultUnsat)
                 [ +  - ]
     192                 :            :     {
     193                 :          0 :       getterCommands.emplace_back(new GetUnsatCoreLemmasCommand());
     194                 :            :     }
     195                 :            : 
     196                 :      62734 :     if (d_solver->getOptionInfo("dump-difficulty").boolValue()
     197 [ +  + ][ +  + ]:      62734 :         && (isResultUnsat || isResultSat || res.isUnknown()))
         [ +  + ][ -  + ]
                 [ +  - ]
     198                 :            :     {
     199                 :         12 :       getterCommands.emplace_back(new GetDifficultyCommand());
     200                 :            :     }
     201                 :            : 
     202         [ +  + ]:      31367 :     if (!getterCommands.empty()) {
     203                 :            :       // set no time limit during dumping if applicable
     204         [ -  + ]:       4622 :       if (d_solver->getOptionInfo("force-no-limit-cpu-while-dump").boolValue())
     205                 :            :       {
     206                 :          0 :         setNoLimitCPU();
     207                 :            :       }
     208         [ +  + ]:       9244 :       for (const auto& getterCommand : getterCommands) {
     209                 :       4622 :         status = doCommandSingleton(getterCommand.get());
     210         [ -  + ]:       4622 :         if (!status)
     211                 :            :         {
     212                 :          0 :           break;
     213                 :            :         }
     214                 :            :       }
     215                 :            :     }
     216                 :            :   }
     217                 :      31414 :   return status;
     218                 :            : }
     219                 :            : 
     220                 :     705659 : bool CommandExecutor::solverInvoke(cvc5::Solver* solver,
     221                 :            :                                    SymManager* sm,
     222                 :            :                                    Cmd* cmd,
     223                 :            :                                    std::ostream& out)
     224                 :            : {
     225                 :            :   // print output for -o raw-benchmark
     226         [ +  + ]:     705659 :   if (solver->isOutputOn("raw-benchmark"))
     227                 :            :   {
     228                 :     135252 :     solver->getOutput("raw-benchmark") << cmd->toString() << std::endl;
     229                 :            :   }
     230                 :            : 
     231                 :            :   // In parse-only mode, we do not invoke any of the commands except define-*
     232                 :            :   // declare-*, set-logic, and reset commands. We invoke define-* and declare-*
     233                 :            :   // commands because they add function names to the symbol table.
     234 [ +  - ][ +  + ]:     270436 :   if (d_parseOnly && dynamic_cast<SetBenchmarkLogicCommand*>(cmd) == nullptr
     235 [ +  - ][ +  + ]:     262644 :       && dynamic_cast<ResetCommand*>(cmd) == nullptr
     236 [ +  - ][ +  + ]:     262609 :       && dynamic_cast<DeclarationDefinitionCommand*>(cmd) == nullptr
     237 [ +  - ][ +  + ]:      98108 :       && dynamic_cast<DatatypeDeclarationCommand*>(cmd) == nullptr
     238 [ +  + ][ +  - ]:     976095 :       && dynamic_cast<DefineFunctionRecCommand*>(cmd) == nullptr)
         [ +  + ][ +  + ]
     239                 :            :   {
     240                 :      96726 :     return true;
     241                 :            :   }
     242                 :            : 
     243                 :     608933 :   cmd->invoke(solver, sm, out);
     244                 :     608931 :   return !cmd->fail();
     245                 :            : }
     246                 :            : 
     247                 :      23567 : void CommandExecutor::flushOutputStreams() {
     248                 :      23567 :   printStatistics(d_solver->getDriverOptions().err());
     249                 :            : 
     250                 :            :   // make sure out and err streams are flushed too
     251                 :      23567 :   d_solver->getDriverOptions().out() << std::flush;
     252                 :      23567 :   d_solver->getDriverOptions().err() << std::flush;
     253                 :      23567 : }
     254                 :            : 
     255                 :            : }  // namespace cvc5::main

Generated by: LCOV version 1.14