#include "Lib/Environment.hpp"
#include "Lib/Stack.hpp"
#include "Kernel/Signature.hpp"
#include "Kernel/Problem.hpp"
#include "Kernel/Term.hpp"
#include "Kernel/Formula.hpp"
#include "Kernel/FormulaUnit.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/SortHelper.hpp"
#include "Kernel/Connective.hpp"
#include "Options.hpp"
#include "DistinctGroupExpansion.hpp"
using namespace std;
using namespace Shell;
void DistinctGroupExpansion::apply(Problem& prb)
{
if(apply(prb.units())){
prb.invalidateProperty();
prb.reportFormulasAdded();
prb.reportEqualityAdded(false); }
}
bool DistinctGroupExpansion::apply(UnitList*& units)
{
bool added=false;
Stack<Signature::DistinctGroupMembers>& group_members = env.signature->distinctGroupMembers();
bool expandEverything = (_expandUpToSize == 0) ||
env.options->saturationAlgorithm()==Options::SaturationAlgorithm::FINITE_MODEL_BUILDING;
bool someLeft = false;
for(unsigned i=0;i<group_members.size();i++){
Signature::DistinctGroupMembers members = group_members[i];
if(members->size() > 0) {
if( members->size()>1 && (expandEverything || members->size() <= _expandUpToSize)) {
added=true;
Formula* expansion = expand(*members);
if(env.options->showPreprocessing()){
std::cout << " expansion adding " << expansion->toString() << endl;
}
UnitList::push(
new FormulaUnit(expansion,NonspecificInference0(UnitInputType::AXIOM,InferenceRule::DISTINCTNESS_AXIOM)),
units);
}
else {
someLeft=true;
}
}
}
if(!someLeft){
env.signature->noDistinctGroupsLeft();
}
return added;
}
Formula* DistinctGroupExpansion::expand(Stack<unsigned>& constants)
{
ASS(constants.size()>=2);
if(constants.size()==2){
TermList a = TermList(Term::createConstant(constants[0]));
TermList b = TermList(Term::createConstant(constants[1]));
TermList sort = SortHelper::getResultSort(a.term()); return new AtomicFormula(Literal::createEquality(false,a,b,sort));
}
FormulaList* diseqs = 0;
for(unsigned i=0;i<constants.size();i++){
TermList a = TermList(Term::createConstant(constants[i]));
ASS(a.isSafe());
TermList sort = SortHelper::getResultSort(a.term());
for(unsigned j=0;j<i;j++){
TermList b = TermList(Term::createConstant(constants[j]));
ASS(b.isSafe());
Formula* new_dis = new AtomicFormula(Literal::createEquality(false,a,b,sort));
if(diseqs) FormulaList::push(new_dis,diseqs);
else diseqs = new FormulaList(new_dis);
}
}
return new JunctionFormula(Connective::AND, diseqs);
}