diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/README.md b/README.md index 043d8bea9..47507f44b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,11 @@ Checkout the project and type `./gradlew build`. You find the executable JAR in $ git clone --recursive https://github.com/AlloyTools/org.alloytools.alloy.git $ cd org.alloytools.alloy $ ./gradlew build - $ java -jar org.alloytools.alloy.dist/target/org.alloytools.alloy.dist.jar + $ cd org.alloytools.alloy.dist + $ chmod +x binaries/cvc4_linux + $ cp binaries/* target + $ cd target + $ java -jar org.alloytools.alloy.dist.jar # opens GUI Note: if you are behind a proxy, the call to `gradlew` is likely to fail, unless you pass it further options about the http and https proxies (and possibly your login and password on this proxy). There are several ways to pass these options, a simple one is to type (replace the `XXXXX`'s by the adequate settings): diff --git a/SMT-Extension/.classpath b/SMT-Extension/.classpath new file mode 100644 index 000000000..f9dc8d600 --- /dev/null +++ b/SMT-Extension/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/SMT-Extension/.project b/SMT-Extension/.project new file mode 100644 index 000000000..da98391d6 --- /dev/null +++ b/SMT-Extension/.project @@ -0,0 +1,23 @@ + + + SMT-Extension + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/SMT-Extension/bnd.bnd b/SMT-Extension/bnd.bnd new file mode 100644 index 000000000..7cb49bb83 --- /dev/null +++ b/SMT-Extension/bnd.bnd @@ -0,0 +1,11 @@ +-buildpath: \ + org.apache.commons.cli,\ + org.alloytools.alloy.core,\ + com.fasterxml.jackson.core.jackson-annotations,\ + com.fasterxml.jackson.core.jackson-databind,\ + jaxb-api,\ + com.fasterxml.jackson.core.jackson-core,\ + org.antlr.antlr4-runtime,\ + +-testpath: + \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Alloy2SmtLogger.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Alloy2SmtLogger.java new file mode 100644 index 000000000..3d4e05313 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Alloy2SmtLogger.java @@ -0,0 +1,77 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt; + +import java.util.logging.Filter; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +public class Alloy2SmtLogger implements Filter +{ + private final Logger LOGGER; + + public Alloy2SmtLogger(String className) + { + LOGGER = Logger.getLogger(className); + } + + public void printInfo(String info) + { + if (info != null) + { + LOGGER.info(info); + } + } + + public void printWarning(String warning) + { + if (warning != null) + { + LOGGER.warning(warning); + } + } + + public void printSevere(String severe) + { + if (severe != null) + { + LOGGER.warning(severe); + } + } + + @Override + public boolean isLoggable(LogRecord record) + { + if (record == null) + { + return false; + } + return !record.getMessage().toLowerCase().startsWith("debug"); + } + + public enum LEVEL + { + INFO("info"), + WARNING("warning"), + SEVERE("severe"); + + private final String levelStr; + + private LEVEL(String level) + { + this.levelStr = level; + } + + @Override + public String toString() + { + return this.levelStr; + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Main.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Main.java new file mode 100644 index 000000000..c742b874b --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Main.java @@ -0,0 +1,148 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt; + +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.alloy2smt.utils.AlloySettings; +import edu.uiowa.smt.printers.SmtLibPrinter; +import org.apache.commons.cli.*; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Paths; +import java.util.Formatter; +import java.util.Scanner; + +public class Main +{ + public static final String SEP = File.separator; + public static final String OUTPUT_DIR = System.getProperty("java.io.tmpdir"); + public static final String DEFAULT_OUTPUT_FILE = "output.smt2"; + + public static boolean isValidInputFilePath(String path) + { + File inputFile = new File(path); + + return inputFile.exists() && inputFile.canRead() && path.endsWith(".als"); + } + + public static boolean isValidOutputFilePath(String path) throws IOException + { + try + { + Paths.get(path); + } + catch (InvalidPathException | NullPointerException ex) + { + return false; + } + + File outputFile = new File(path); + + if (outputFile.getParentFile() != null) + { + outputFile.getParentFile().mkdirs(); + } + outputFile.createNewFile(); + return true; + } + + public static void main(String[] args) + { + Options options = new Options(); + CommandLineParser commandLineParser = new DefaultParser(); + + options.addOption(Option.builder("i").longOpt("input").desc("Input Alloy model").hasArg().build()); + options.addOption(Option.builder("o").longOpt("output").desc("SMT-LIB model output").hasArg().build()); + + try + { + CommandLine command = commandLineParser.parse(options, args); + + Translation translation; + String defaultOutputFile; + + if (command.hasOption("i")) + { + String inputFile = command.getOptionValue("i").trim(); + + if (isValidInputFilePath(inputFile)) + { + String alloy = new String(Files.readAllBytes(Paths.get(inputFile)), StandardCharsets.UTF_8); + translation = Utils.translate(alloy, AlloySettings.Default); + defaultOutputFile = OUTPUT_DIR + SEP + new File(inputFile).getName() + ".smt2"; + } + else + { + throw new Exception("Can not open file " + inputFile); + } + } + else + { + StringBuilder stringBuilder = new StringBuilder(); + Scanner scanner = new Scanner(System.in); + + while (scanner.hasNextLine()) + { + stringBuilder.append(scanner.nextLine()).append("\n"); + } + + translation = Utils.translate(stringBuilder.toString(), AlloySettings.Default); + defaultOutputFile = DEFAULT_OUTPUT_FILE + ".smt2"; + } + + File outputFile = null; + + if (command.hasOption("o")) + { + if (isValidOutputFilePath(command.getOptionValue("o"))) + { + outputFile = new File(command.getOptionValue("o").trim()); + } + } + if (outputFile == null) + { + outputFile = new File(defaultOutputFile); + } + try (Formatter formatter = new Formatter(outputFile)) + { + formatter.format("%s\n", translation.getOptimizedSmtScript()); + + System.out.println("\n"); + System.out.println(translation.getOptimizedSmtScript()); + + // translate all alloy commands + for (int i = 0; i < translation.getCommands().size(); i++) + { + String commandTranslation = translation.getOptimizedSmtScript(i).toString(); + + commandTranslation = SmtLibPrinter.PUSH + "\n" + commandTranslation + + SmtLibPrinter.CHECK_SAT + "\n" + SmtLibPrinter.GET_MODEL + "\n" + + SmtLibPrinter.POP + "\n"; + + formatter.format("%s\n", commandTranslation); + System.out.println("\n" + commandTranslation); + } + } + System.out.println("\nThe SMT-LIB model was generated at: " + outputFile.getAbsolutePath()); + } + catch (ParseException exception) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("java -jar alloy2smt.jar ", options); + } + catch (Exception exception) + { + exception.printStackTrace(); + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Utils.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Utils.java new file mode 100644 index 000000000..6aac38712 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/Utils.java @@ -0,0 +1,56 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt; + +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.parser.CompUtil; +import edu.uiowa.alloy2smt.mapping.Mapper; +import edu.uiowa.alloy2smt.translators.Alloy2SmtTranslator; +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.alloy2smt.utils.AlloySettings; +import edu.uiowa.smt.smtAst.SmtScript; + +import java.util.Map; + +public class Utils +{ + public static Translation translateFromFile(String filePath, AlloySettings settings) + { + CompModule alloyModel = CompUtil.parseEverything_fromFile(null, null, filePath); + return getTranslation(alloyModel, settings); + } + + public static Translation translate(String alloyScript, AlloySettings settings) + { + CompModule alloyModel = CompUtil.parseEverything_fromString(null, alloyScript); + return getTranslation(alloyModel, settings); + } + + public static Translation translate(Map alloyFiles, String originalFileName, int resolutionMode, + AlloySettings settings) + { + CompModule alloyModel = CompUtil.parseEverything_fromFile(null, alloyFiles, originalFileName, resolutionMode); + return getTranslation(alloyModel, settings); + } + + private static Translation getTranslation(CompModule alloyModel, AlloySettings settings) + { + Alloy2SmtTranslator translator = new Alloy2SmtTranslator(alloyModel, settings); + SmtScript script = translator.translate(); + Mapper mapper = translator.generateMapper(); + + Translation translation = new Translation(translator, script, mapper, settings); + for (int index = 0; index < translation.getCommands().size(); index++) + { + translator.translateCommand(index); + } + translation.optimize(); + return translation; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/Mapper.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/Mapper.java new file mode 100644 index 000000000..ce54f58c5 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/Mapper.java @@ -0,0 +1,64 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.mapping; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@XmlRootElement(name = "Mapper") +public class Mapper +{ + @XmlAttribute(name = "Signature") + @JsonProperty("signatures") + public List signatures = new ArrayList<>(); + + @XmlAttribute(name = "Field") + @JsonProperty("fields") + public List fields = new ArrayList<>(); + + public void writeToXml(String xmlFile) throws JAXBException + { + JAXBContext context = JAXBContext.newInstance(Mapper.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.marshal(this, new File(xmlFile)); + } + + public static Mapper readFromXml(String xmlFile) throws JAXBException + { + JAXBContext context = JAXBContext.newInstance(Mapper.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + Mapper mapper = (Mapper) unmarshaller.unmarshal(new File(xmlFile)); + return mapper; + } + + public void writeToJson(String jsonFile) throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(jsonFile), this); + } + + public static Mapper readFromJson(String jsonFile) throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + Mapper mapper = objectMapper.readValue(new File(jsonFile), Mapper.class); + return mapper; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingField.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingField.java new file mode 100644 index 000000000..dee76d681 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingField.java @@ -0,0 +1,48 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.mapping; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +@XmlRootElement(name = "Field") +public class MappingField +{ + @XmlAttribute(name = "label") + @JsonProperty("label") + public String label; + + @XmlAttribute(name = "functionName") + @JsonProperty("functionName") + public String functionName; // function name in SMT model + + @XmlAttribute(name = "id") + @JsonProperty("id") + public int id; + + @XmlAttribute(name = "parentId") + @JsonProperty("parentId") + public int parentId; + + @XmlAttribute(name = "isPrivate") + @JsonProperty("isPrivate") + public boolean isPrivate; + + @XmlAttribute(name = "isMeta") + @JsonProperty("isMeta") + public boolean isMeta; + + @XmlAttribute(name = "types") + @JsonProperty("types") + public List> types = new ArrayList<>(); +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingSignature.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingSignature.java new file mode 100644 index 000000000..bebe0ff79 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingSignature.java @@ -0,0 +1,77 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.mapping; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +//ToDo: refactor this class with alloy Signature class +@XmlRootElement(name = "Signature") +public class MappingSignature +{ + @XmlAttribute(name = "label") + @JsonProperty("label") + public String label; + + @XmlAttribute(name = "functionName") + @JsonProperty("functionName") + public String functionName; // function name in SMT model + + @XmlAttribute(name = "id") + @JsonProperty("id") + public int id; + + @XmlAttribute(name = "parents") + @JsonProperty("parents") + public List parents = new ArrayList<>(); + + @XmlAttribute(name = "builtIn") + @JsonProperty("builtIn") + public boolean builtIn; + + @XmlAttribute(name = "isAbstract") + @JsonProperty("isAbstract") + public boolean isAbstract; + + @XmlAttribute(name = "isOne") + @JsonProperty("isOne") + public boolean isOne; + + @XmlAttribute(name = "isLone") + @JsonProperty("isLone") + public boolean isLone; + + @XmlAttribute(name = "isSome") + @JsonProperty("isSome") + public boolean isSome; + + @XmlAttribute(name = "isPrivate") + @JsonProperty("isPrivate") + public boolean isPrivate; + + @XmlAttribute(name = "isMeta") + @JsonProperty("isMeta") + public boolean isMeta; + + @XmlAttribute(name = "isExact") + @JsonProperty("isExact") + public boolean isExact; + + @XmlAttribute(name = "isEnum") + @JsonProperty("isEnum") + public boolean isEnum; + + @XmlAttribute(name = "isSubset") + @JsonProperty("isSubset") + public boolean isSubset; +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingType.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingType.java new file mode 100644 index 000000000..0c23e83a1 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/mapping/MappingType.java @@ -0,0 +1,22 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.mapping; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "Type") +public class MappingType +{ + @XmlAttribute(name = "id") + @JsonProperty("id") + public int id; +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Alloy2SmtTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Alloy2SmtTranslator.java new file mode 100644 index 000000000..cadd54b98 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Alloy2SmtTranslator.java @@ -0,0 +1,602 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.*; +import edu.mit.csail.sdg.parser.CompModule; +import edu.uiowa.alloy2smt.mapping.Mapper; +import edu.uiowa.alloy2smt.mapping.MappingField; +import edu.uiowa.alloy2smt.mapping.MappingSignature; +import edu.uiowa.alloy2smt.mapping.MappingType; +import edu.uiowa.alloy2smt.utils.AlloySettings; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.*; +import java.util.stream.Collectors; + +public class Alloy2SmtTranslator extends AbstractTranslator +{ + public final AlloySettings alloySettings; + final CompModule alloyModel; + final List reachableSigs; + final List topLevelSigs; + final List commands; + + final SignatureTranslator signatureTranslator; + final ExprTranslator exprTranslator; + + Map sigFacts; + Map signaturesMap; + Map fieldsMap; + Map sigToIdMap; + List facts; + + public Alloy2SmtTranslator(CompModule alloyModel, AlloySettings alloySettings) + { + TranslatorUtils.reset(); + this.alloySettings = alloySettings; + this.smtScript = new SmtScript(); + this.alloyModel = alloyModel; + this.reachableSigs = new ArrayList<>(); + this.topLevelSigs = new ArrayList<>(); + this.commands = alloyModel.getAllCommands(); + + this.signatureTranslator = new SignatureTranslator(this); + this.comparisonOperations = new HashMap<>(); + this.arithmeticOperations = new HashMap<>(); + this.signaturesMap = new HashMap<>(); + this.functionsMap = new HashMap<>(); + this.fieldsMap = new HashMap<>(); + this.sigFacts = new HashMap<>(); + this.sigToIdMap = new HashMap<>(); + + this.signaturesMap.put(Sig.UNIV, univAtom); + this.signaturesMap.put(Sig.SIGINT, univInt); + this.smtScript.addSort(atomSort); + this.smtScript.addSort(uninterpretedInt); + this.smtScript.addFunction(uninterpretedIntValue); + + this.functionsMap.put(uninterpretedIntValue.getName(), uninterpretedIntValue); + + this.exprTranslator = new ExprTranslator(this); + this.facts = new ArrayList<>(); + } + + public Alloy2SmtTranslator(Alloy2SmtTranslator translator) + { + this.alloySettings = translator.alloySettings; + this.smtScript = new SmtScript(translator.smtScript); + this.alloyModel = translator.alloyModel; + this.reachableSigs = new ArrayList<>(translator.reachableSigs); + this.topLevelSigs = new ArrayList<>(translator.topLevelSigs); + this.sigToIdMap = new HashMap<>(translator.sigToIdMap); + + this.commands = this.alloyModel.getAllCommands(); + + this.signatureTranslator = new SignatureTranslator(this); + this.comparisonOperations = new HashMap<>(translator.comparisonOperations); + this.arithmeticOperations = new HashMap<>(translator.arithmeticOperations); + this.signaturesMap = new HashMap<>(translator.signaturesMap); + this.functionsMap = new HashMap<>(translator.functionsMap); + this.fieldsMap = new HashMap<>(translator.fieldsMap); + this.sigFacts = new HashMap<>(translator.sigFacts); + + this.exprTranslator = new ExprTranslator(this); + this.facts = new ArrayList<>(translator.facts); + } + + @Override + public SmtScript translate() + { + translateSpecialFunctions(); + this.signatureTranslator.translateSigs(); + this.signatureTranslator.translateSpecialSigFacts(); + this.signatureTranslator.translateSigFacts(); + translateFacts(); + translateSpecialAssertions(); + translateFunctions(); + return this.smtScript; + } + + private void translateFunctions() + { + for (CompModule module : alloyModel.getAllReachableModules()) + { + if (module.getModelName().contains("util/ordering") || + module.getModelName().contains("util/integer")) + { + continue; + } + for (Func func : module.getAllFunc()) + { + getFuncTranslation(func); + } + } + } + + private void translateSpecialFunctions() + { + this.smtScript.addFunction(atomNone); + this.smtScript.addFunction(univAtom); + this.smtScript.addFunction(idenAtom); + this.smtScript.addFunction(idenInt); + this.smtScript.addFunction(univInt); + } + + private void translateFacts() + { + for (CompModule module : alloyModel.getAllReachableModules()) + { + for (Pair pair : module.getAllFacts()) + { + exprTranslator.translateFormula(pair.a, pair.b); + this.facts.add(pair.b); + } + } + } + + /** + * @return a mapper that maps signatures's names to the corresponding names + * in the generated smt script + */ + public Mapper generateMapper() + { + Mapper mapper = new Mapper(); + // add special signatures + + MappingSignature univSignature = getSignature(Sig.UNIV); + mapper.signatures.add(univSignature); + + MappingSignature intSignature = getSignature(Sig.SIGINT); + mapper.signatures.add(intSignature); + + //ToDo: add other special signatures: none, iden, string + + for (Sig sig : topLevelSigs) + { + mapper.signatures.addAll(getSignatures(sig)); + } + + // add remaining signatures like int signatures + for (Sig sig : reachableSigs) + { + if (!sigToIdMap.keySet().contains(sig)) + { + mapper.signatures.addAll(getSignatures(sig)); + } + } + + for (Sig sig : reachableSigs) + { + mapper.fields.addAll(getFields(sig)); + } + + return mapper; + } + + private List getSignatures(Sig sig) + { + List signatures = new ArrayList<>(); + MappingSignature signature = getSignature(sig); + signatures.add(signature); + + for (Sig childSig : children(sig)) + { + signatures.addAll(getSignatures(childSig)); + } + + return signatures; + } + + private List getFields(Sig sig) + { + List fields = new ArrayList<>(); + + for (Sig.Field field : sig.getFields()) + { + fields.add(getField(field)); + } + + return fields; + } + + private List children(Sig sig) + { + if (sig == Sig.NONE) + { + return new ArrayList<>(); + } + if (sig instanceof Sig.PrimSig) + { + List sigs = new ArrayList<>(); + ((Sig.PrimSig) sig).children().forEach(sigs::add); + return sigs; + } + return new ArrayList<>(); + } + + + private MappingSignature getSignature(Sig sig) + { + MappingSignature signature = new MappingSignature(); + + signature.label = sig.label; + signature.functionName = TranslatorUtils.getOriginalName(signaturesMap.get(sig).getName()); + + signature.id = getSigId(sig); + + // find the ids of the parents + if (sig instanceof Sig.PrimSig && sig != Sig.UNIV) + { + signature.parents.add(getSigId(((Sig.PrimSig) sig).parent)); + } + else if (sig instanceof Sig.SubsetSig) + { + signature.isSubset = true; + for (Sig parent : ((Sig.SubsetSig) sig).parents) + { + signature.parents.add(getSigId(parent)); + } + } + + signature.builtIn = sig.builtin; + signature.isAbstract = sig.isAbstract != null; + signature.isOne = sig.isOne != null; + signature.isLone = sig.isLone != null; + signature.isSome = sig.isSome != null; + signature.isPrivate = sig.isPrivate != null; + signature.isMeta = sig.isMeta != null; + + if (sig instanceof Sig.SubsetSig) + { + signature.isExact = ((Sig.SubsetSig) sig).exact; + } + + signature.isEnum = sig.isEnum != null; + + return signature; + } + + private MappingField getField(Sig.Field field) + { + MappingField mappingField = new MappingField(); + + mappingField.label = field.label; + mappingField.functionName = TranslatorUtils.getOriginalName(fieldsMap.get(field).getName()); + mappingField.id = getSigId(field); + mappingField.parentId = getSigId(field.sig); + mappingField.isPrivate = field.isPrivate != null; + mappingField.isMeta = field.isMeta != null; + mappingField.types = getFieldTypes(field); + + return mappingField; + } + + private List> getFieldTypes(Sig.Field field) + { + List> types = new ArrayList<>(); + for (List sigs : field.type().fold()) + { + List type = new ArrayList<>(); + for (Sig sig : sigs) + { + MappingType mappingType = new MappingType(); + mappingType.id = getSigId(sig); + type.add(mappingType); + } + types.add(type); + } + return types; + } + + // Sig.univ usually has id = 2 (1 ++) + private int mappingSignatureId = 1; + + private int getUniqueId() + { + mappingSignatureId++; + return mappingSignatureId; + } + + /** + * @param expr can be Sig, Field, or Skolem + * @return the unique id of the expr it exists in the idMap, or generate a new id + */ + public int getSigId(Expr expr) + { + Integer id = sigToIdMap.get(expr); + + if (id == null) + { + id = getUniqueId(); + sigToIdMap.put(expr, id); + } + return id; + } + + /** + * @param commandIndex the index of the run command + * @return a list of assertions that represent the translation + * of the command + */ + public void translateCommand(int commandIndex) + { + // set the current smt script to a new child for push pop commands + this.smtScript = smtScript.createChild(); + + Command command = this.commands.get(commandIndex); + + translatecommandExprList(command); + + if (alloySettings.includeCommandScope) + { + translateSignaturesScope(command); + translateIntScope(command); + } + + // restore the parent for new alloy commands + this.smtScript = this.smtScript.getParent(); + } + + private void translateIntScope(Command command) + { + int minInteger = -(int) Math.pow(2, command.bitwidth - 1); + int maxInteger = -minInteger - 1; + ExprVar x = ExprVar.make(command.pos, "x", Sig.SIGINT.type()); + Expr gte = ExprBinary.Op.GTE.make(command.formula.pos, command.formula.closingBracket, x, ExprConstant.makeNUMBER(minInteger)); + Expr lte = ExprBinary.Op.LTE.make(command.formula.pos, command.formula.closingBracket, x, ExprConstant.makeNUMBER(maxInteger)); + Expr and = ExprList.make(command.formula.pos, command.formula.closingBracket, ExprList.Op.AND, Arrays.asList(gte, lte)); + Expr oneOfInt = ExprUnary.Op.ONEOF.make(null, Sig.SIGINT); + Decl decl = new Decl(null, null, null, null, Collections.singletonList(x), oneOfInt); + Expr all = ExprQt.Op.ALL.make(command.formula.pos, command.formula.closingBracket, Collections.singletonList(decl), and); + exprTranslator.translateFormula("Scope " + command.bitwidth + " Int", all); + } + + private void translateSignaturesScope(Command command) + { + Map> childrenScope = new HashMap<>(); + for (Sig signature : reachableSigs) + { + if (signature instanceof Sig.PrimSig) + { + Optional optional = command.scope + .stream() + .filter(s -> s.sig == signature) + .findFirst(); + int scope = 0; + SmtBinaryExpr.Op op; + if (optional.isPresent()) + { + CommandScope commandScope = optional.get(); + if (commandScope.isExact || alloyModel.getExactSigs().contains(signature)) + { + op = SmtBinaryExpr.Op.EQ; + } + else + { + op = SmtBinaryExpr.Op.SUBSET; + } + scope = commandScope.endingScope; + } + else + { + if (alloyModel.getExactSigs().contains(signature)) + { + op = SmtBinaryExpr.Op.EQ; + } + else + { + op = SmtBinaryExpr.Op.SUBSET; + } + + if (signature.isTopLevel()) + { + if (signature.isAbstract == null) + { + // no scope specification is given, default value is used + scope = command.overall == -1 ? AlloySettings.defaultScope : command.overall; + } + else + { + childrenScope.put(signature, new HashMap<>()); + // the scope is the sum of its children + scope = getScope((Sig.PrimSig) signature, command, childrenScope); + } + } + else + { + // the signature has no implicit bound + } + } + + SmtExpr variable = signaturesMap.get(signature).getVariable(); + + if (scope >= 1) + { + List declarations = new ArrayList<>(); + Sort sort = signature.type().is_int() ? AbstractTranslator.uninterpretedInt : AbstractTranslator.atomSort; + SmtVariable firstAtom = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + declarations.add(firstAtom); + SmtExpr firstTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, firstAtom.getVariable()); + SmtExpr set = SmtUnaryExpr.Op.SINGLETON.make(firstTuple); + for (int i = 1; i < scope; i++) + { + SmtVariable declaration = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + declarations.add(declaration); + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, declaration.getVariable()); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tuple); + set = SmtBinaryExpr.Op.UNION.make(singleton, set); + } + + SmtExpr constraint = op.make(variable, set); + if (declarations.size() > 1) + { + List smtExprs = declarations + .stream().map(d -> d.getVariable()) + .collect(Collectors.toList()); + SmtExpr distinct = SmtMultiArityExpr.Op.DISTINCT.make(smtExprs); + constraint = SmtMultiArityExpr.Op.AND.make(constraint, distinct); + } + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(constraint, declarations); + Assertion scopeAssertion = AlloyUtils.getAssertion(Collections.singletonList(command.pos), + signature.toString() + " scope", exists); + smtScript.addAssertion(scopeAssertion); + } + } + } + } + + private void translatecommandExprList(Command command) + { + assert (command.formula instanceof ExprList); + ExprList list = (ExprList) command.formula; + assert (list.op == ExprList.Op.AND); + + //ToDo: refactor this line which just prints the command as a comment + Assertion comment = new Assertion("", command.toString(), BoolConstant.True); + smtScript.addAssertion(comment); + + for (Expr argument : list.args) + { + // translate only the formulas added by the command and ignore facts + if (!facts.contains(argument)) + { + exprTranslator.translateFormula(argument.toString(), argument); + } + } + } + + //ToDo: refactor this function by storing positions outside + private boolean isFactFormula(Expr argument) + { + List positions = alloyModel.getAllFacts().makeConstList() + .stream().map(p -> p.b.pos).collect(Collectors.toList()); + for (Pos pos : positions) + { + if (pos.contains(argument.pos)) + { + return true; + } + } + return false; + } + + private int getScope(Sig.PrimSig parent, Command command, + Map> childrenScope) + { + int scopeSum = 0; + Map parentMap = childrenScope.get(parent); + for (Sig signature : parent.children()) + { + if (signature.isAbstract == null) + { + Optional optional = command.scope + .stream() + .filter(s -> s.sig == signature) + .findFirst(); + if (optional.isPresent()) + { + CommandScope commandScope = optional.get(); + scopeSum += commandScope.endingScope; + parentMap.put(signature, commandScope.endingScope); + } + else + { + if (signature.isOne != null) + { + scopeSum += 1; + } + else + { + // for some reason, the default scope is not used here + scopeSum += 0; + } + } + } + else + { + childrenScope.put(signature, new HashMap<>()); + int scope = getScope((Sig.PrimSig) signature, command, childrenScope); + parentMap.put(signature, scope); + scopeSum += scope; + } + } + + if (scopeSum == 0) // no explicit scope for children is given + { + scopeSum = command.overall == -1 ? AlloySettings.defaultScope : command.overall; + } + return scopeSum; + } + + public FunctionDeclaration getFuncTranslation(Func func) + { + FunctionDeclaration function; + if(functionsMap.containsKey(func.label)) + { + function = functionsMap.get(func.label); + } + else + { + function = translateFunc(func); + } + return function; + } + + private FunctionDefinition translateFunc(Func func) + { + SmtEnv smtEnv = new SmtEnv(); + List arguments = new ArrayList<>(); + for (Decl decl : func.decls) + { + List variables = exprTranslator.declTranslator.translateDecl(decl, smtEnv); + List setVariables = convertToSetVariables(variables); + arguments.addAll(setVariables); + } + // add arguments to function environment + for (SmtVariable variable : arguments) + { + smtEnv.put(variable.getName(), variable.getVariable()); + } + + SmtExpr smtExpr = exprTranslator.translateExpr(func.getBody(), smtEnv); + + FunctionDefinition function = new FunctionDefinition(func.label, arguments, smtExpr.getSort(), smtExpr, true); + + addFunction(function); + + return function; + } + + private List convertToSetVariables(List variables) + { + List setVariables = new ArrayList<>(); + + for (SmtVariable variable : variables) + { + if (variable.getSort() instanceof TupleSort) + { + Sort sort = new SetSort(variable.getSort()); + SmtVariable newVariable = new SmtVariable(variable.getName(), sort, variable.isOriginal()); + setVariables.add(newVariable); + } + else + { + setVariables.add(variable); + } + } + return setVariables; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/DeclTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/DeclTranslator.java new file mode 100644 index 000000000..330b760ca --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/DeclTranslator.java @@ -0,0 +1,142 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprHasName; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DeclTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + + public DeclTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.translator = exprTranslator.translator; + } + + public List translateDecls(List decls, SmtEnv smtEnv) + { + List variables = new ArrayList<>(); + for (Decl decl : decls) + { + variables.addAll(translateDecl(decl, smtEnv)); + } + return variables; + } + + public List translateDecl(Decl decl, SmtEnv smtEnv) + { + List variables = new ArrayList<>(); + + for (ExprHasName name : decl.names) + { + Decl individualDecl = new Decl(decl.isPrivate, decl.disjoint, decl.disjoint2, decl.isVar, Collections.singletonList(name), decl.expr); + variables.add(translateIndividualDecl(individualDecl, smtEnv)); + } + + // add variables to the environment + for (SmtVariable variable : variables) + { + smtEnv.put(variable.getName(), variable.getVariable()); + } + + return variables; + } + + public SmtVariable translateIndividualDecl(Decl decl, SmtEnv smtEnv) + { + ExprHasName name = decl.names.get(0); + Expr expr = decl.expr; + + if (expr instanceof ExprUnary && ((ExprUnary) expr).op == ExprUnary.Op.NOOP) + { + expr = ((ExprUnary) expr).sub; + } + + SmtEnv newEnv = new SmtEnv(smtEnv); + SmtExpr set = exprTranslator.translateExpr(expr, newEnv); + SetSort setSort = (SetSort) set.getSort(); + Sort sort = setSort; + + // for singletons quantifiers has the same sort of the elements + if (expr instanceof ExprUnary) + { + if (((ExprUnary) expr).op == ExprUnary.Op.ONEOF) + { + sort = setSort.elementSort; + SmtVariable smtVariable = new SmtVariable(name.label, sort, true); + assert (set instanceof SmtUnaryExpr); + assert (((SmtUnaryExpr) set).getOp() == SmtUnaryExpr.Op.SINGLETON); + assert (((SmtUnaryExpr) set).getExpr() instanceof Variable); + Variable variable = (Variable) ((SmtUnaryExpr) set).getExpr(); + SmtExpr constraint = ((SmtVariable) variable.getDeclaration()).getConstraint(); + smtVariable.setConstraint(constraint.replace(variable, smtVariable.getVariable())); + return smtVariable; + } + } + + SmtVariable smtVariable = new SmtVariable(name.label, sort, true); + + if (set instanceof Variable && ((Variable) set).getDeclaration() instanceof SmtVariable) + { + Variable variable = (Variable) set; + SmtExpr constraint = ((SmtVariable) variable.getDeclaration()).getConstraint(); + if (constraint != null) + { + smtVariable.setConstraint(constraint.replace(variable, smtVariable.getVariable())); + } + } + else + { + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(smtVariable.getVariable(), set); + smtVariable.setConstraint(subset); + } + return smtVariable; + } + + public SmtExpr getDisjointConstraints(List decls, SmtEnv smtEnv) + { + SmtExpr disjointConstraints = BoolConstant.True; + + for (Decl decl : decls) + { + // disjoint fields + if (decl.disjoint != null && decl.names.size() > 1) + { + for (int i = 0; i < decl.names.size() - 1; i++) + { + for (int j = i + 1; j < decl.names.size(); j++) + { + SmtExpr variableI = smtEnv.get(decl.names.get(i).label); + SmtExpr variableJ = smtEnv.get(decl.names.get(j).label); + + if (variableJ.getSort() instanceof UninterpretedSort) + { + throw new UnsupportedOperationException(); + } + + if (variableJ.getSort() instanceof TupleSort) + { + variableI = SmtUnaryExpr.Op.SINGLETON.make(variableI); + variableJ = SmtUnaryExpr.Op.SINGLETON.make(variableJ); + } + + SmtExpr intersect = SmtBinaryExpr.Op.INTERSECTION.make(variableI, variableJ); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(variableI.getSort()); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(intersect, emptySet); + disjointConstraints = SmtMultiArityExpr.Op.AND.make(disjointConstraints, equal); + } + } + } + } + return disjointConstraints; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprBinaryTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprBinaryTranslator.java new file mode 100644 index 000000000..4aa38a2af --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprBinaryTranslator.java @@ -0,0 +1,1801 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ExprBinaryTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + + public ExprBinaryTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + translator = exprTranslator.translator; + } + + SmtExpr translateExprBinary(ExprBinary expr, SmtEnv smtEnv) + { + switch (expr.op) + { + case ARROW: + return translateArrow(expr, smtEnv); + case ANY_ARROW_SOME: + return translateAnyArrowSome(expr, smtEnv); + case ANY_ARROW_ONE: + return translateAnyArrowOne(expr, smtEnv); + case ANY_ARROW_LONE: + return translateAnyArrowLone(expr, smtEnv); + case SOME_ARROW_ANY: + return translateSomeArrowAny(expr, smtEnv); + case SOME_ARROW_SOME: + return translateSomeArrowSome(expr, smtEnv); + case SOME_ARROW_ONE: + return translateSomeArrowOne(expr, smtEnv); + case SOME_ARROW_LONE: + return translateSomeArrowLone(expr, smtEnv); + case ONE_ARROW_ANY: + return translateOneArrowAny(expr, smtEnv); + case ONE_ARROW_SOME: + return translateOneArrowSome(expr, smtEnv); + case ONE_ARROW_ONE: + return translateOneArrowOne(expr, smtEnv); + case ONE_ARROW_LONE: + return translateOneArrowLone(expr, smtEnv); + case LONE_ARROW_ANY: + return translateLoneArrowAny(expr, smtEnv); + case LONE_ARROW_SOME: + return translateLoneArrowSome(expr, smtEnv); + case LONE_ARROW_ONE: + return translateLoneArrowOne(expr, smtEnv); + case LONE_ARROW_LONE: + return translateLoneArrowLone(expr, smtEnv); + case ISSEQ_ARROW_LONE: + throw new UnsupportedOperationException(); + + // Relational operators + case JOIN: + return translateJoin(expr, smtEnv); + case DOMAIN: + return translateDomainRestriction(expr, smtEnv); + case RANGE: + return translateRangeRestriction(expr, smtEnv); + case INTERSECT: + return translateSetOperation(expr, SmtBinaryExpr.Op.INTERSECTION, smtEnv); + case PLUSPLUS: + return translatePlusPlus(expr, smtEnv); + case EQUALS: + return translateEqComparison(expr, SmtBinaryExpr.Op.EQ, smtEnv); + case NOT_EQUALS: + return SmtUnaryExpr.Op.NOT.make(translateEqComparison(expr, SmtBinaryExpr.Op.EQ, smtEnv)); + + // Set op + case PLUS: + return translateSetOperation(expr, SmtBinaryExpr.Op.UNION, smtEnv); + case MINUS: + return translateSetOperation(expr, SmtBinaryExpr.Op.SETMINUS, smtEnv); + + // Arithmetic operators + case IPLUS: + return translateArithmetic(expr, SmtBinaryExpr.Op.PLUS, smtEnv); + case IMINUS: + return translateArithmetic(expr, SmtBinaryExpr.Op.MINUS, smtEnv); + case MUL: + return translateArithmetic(expr, SmtBinaryExpr.Op.MULTIPLY, smtEnv); + case DIV: + return translateArithmetic(expr, SmtBinaryExpr.Op.DIVIDE, smtEnv); + case REM: + return translateArithmetic(expr, SmtBinaryExpr.Op.MOD, smtEnv); + // Comparison operators + case LT: + return translateComparison(expr, SmtBinaryExpr.Op.LT, smtEnv); + case LTE: + return translateComparison(expr, SmtBinaryExpr.Op.LTE, smtEnv); + case GT: + return translateComparison(expr, SmtBinaryExpr.Op.GT, smtEnv); + case GTE: + return translateComparison(expr, SmtBinaryExpr.Op.GTE, smtEnv); + case IN: + return translateSubsetOperation(expr, smtEnv); + case NOT_IN: + return SmtUnaryExpr.Op.NOT.make(translateSubsetOperation(expr, smtEnv)); + case IMPLIES: + return translateImplies(expr, smtEnv); + case AND: + return translateAnd(expr, smtEnv); + case OR: + return translateOr(expr, smtEnv); + case IFF: + return translateEqComparison(expr, SmtBinaryExpr.Op.EQ, smtEnv); + case NOT_LT: + return translateComparison(expr, SmtBinaryExpr.Op.GTE, smtEnv); + case NOT_LTE: + return translateComparison(expr, SmtBinaryExpr.Op.GT, smtEnv); + case NOT_GT: + return translateComparison(expr, SmtBinaryExpr.Op.LTE, smtEnv); + case NOT_GTE: + return translateComparison(expr, SmtBinaryExpr.Op.LT, smtEnv); + case SHL: + throw new UnsupportedOperationException(); + case SHA: + throw new UnsupportedOperationException(); + case SHR: + throw new UnsupportedOperationException(); + default: + throw new UnsupportedOperationException(); + } + } + + private SmtExpr translateOneArrowOne(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A one -> one B + // and + // forall x in A . exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet + // and + // forall y in B . exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + return multiplicitySet.getVariable(); + } + + private SmtExpr translateOneArrowSome(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + + // multiplicitySet subset of A one -> some B + // and + // forall x in A . exists y in B . xy in multiplicitySet + // and + // forall y in B . exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateOneArrowAny(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + + // multiplicitySet subset of A one -> set B + // and + // forall y in B . exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateSomeArrowOne(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A some -> one B + // and + // forall x in A . exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet + // and + // forall y in B . exists x in A . xy in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateAnyArrowOne(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A set -> one B + // and + // forall x in A . exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateSomeArrowSome(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + // multiplicitySet subset of A some -> some B + // and + // forall x in A . exists y in B . xy in multiplicitySet + // and + // forall y in B . exists x in A . xy in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember); + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(Arrays.asList(forAllX, forAllY, subset)); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + return multiplicitySet.getVariable(); + } + + private SmtExpr translateSomeArrowAny(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + // multiplicitySet subset of A some -> set B + // and + // forall y in B . exists x in A . xy in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember); + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateAnyArrowSome(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + // multiplicitySet subset of A set -> some B + // and + // forall x in A . exists y in B . xy in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember); + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateOneArrowLone(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A one -> lone B + // and + // forall x in A . + // (forall y in B. xy not in multiplicitySet) + // or + // (exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet) + // and + // forall y in B . exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet + + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr lone = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, y), existsY); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, lone); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateSomeArrowLone(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A some -> lone B + // and + // forall x in A . + // (forall y in B. xy not in multiplicitySet) + // or + // (exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet) + // and + // forall y in B . exists x in A . xy in multiplicitySet + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr lone = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, y), existsY); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, lone); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, existsX); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateAnyArrowLone(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A set -> lone B + // and + // forall x in A . + // (forall y in B. xy not in multiplicitySet) + // or + // (exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet) + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr lone = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, y), existsY); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, lone); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX); + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + return multiplicitySet.getVariable(); + } + + private SmtExpr translateLoneArrowLone(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A lone -> lone B + // and + // forall x in A . + // (forall y in B. xy not in multiplicitySet) + // or + // (exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet) + // and + // forall y in B. + // (forall x in A. xy not in multiplicitySet) + // or + // (exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet) + + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr loneWest = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, y), existsY); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, loneWest); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr loneEast = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, x), existsX); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, loneEast); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateLoneArrowOne(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtVariable v = new SmtVariable("v", BSort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + SmtExpr vMemberB = SmtBinaryExpr.Op.MEMBER.make(v.getVariable(), B); + + // multiplicitySet subset of A lone -> one B + // and + // forall x in A . + // (exists y in B . xy in multiplicitySet and + // forall v in B. v != y implies xv not in multiplicitySet) + // and + // forall y in B. + // (forall x in A. xy not in multiplicitySet) + // or + // (exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet) + + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr xvTuple = getTupleConcatenation(ASort, BSort, x, v); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr xvMember = SmtBinaryExpr.Op.MEMBER.make(xvTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notXV = SmtUnaryExpr.Op.NOT.make(xvMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + SmtExpr vEqualY = SmtBinaryExpr.Op.EQ.make(v.getVariable(), y.getVariable()); + SmtExpr notVEqualY = SmtUnaryExpr.Op.NOT.make(vEqualY); + + SmtExpr vImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(vMemberB, notVEqualY), notXV); + SmtExpr forAllV = SmtQtExpr.Op.FORALL.make(vImplies, v); + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember), forAllV); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr loneEast = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, x), existsX); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, loneEast); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateLoneArrowSome(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + + // multiplicitySet subset of A lone -> some B + // and + // forall x in A . + // (exists y in B . xy in multiplicitySet + // and + // forall y in B. + // (forall x in A. xy not in multiplicitySet) + // or + // (exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet) + + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + + SmtExpr existsYBody = SmtMultiArityExpr.Op.AND.make(yMemberB, xyMember); + + SmtExpr existsY = SmtQtExpr.Op.EXISTS.make(existsYBody, y); + SmtExpr xImplies = SmtBinaryExpr.Op.IMPLIES.make(xMemberA, existsY); + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xImplies, x); + + + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr loneEast = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, x), existsX); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, loneEast); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllX, forAllY); + + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr translateLoneArrowAny(ExprBinary expr, SmtEnv smtEnv) + { + SetSort sort = new SetSort(new TupleSort(AlloyUtils.getExprSorts(expr))); + SmtVariable multiplicitySet = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(multiplicitySet.getVariable(), product); + + SetSort ASort = (SetSort) A.getSort(); + SetSort BSort = (SetSort) B.getSort(); + + SmtVariable x = new SmtVariable("x", ASort.elementSort, false); + SmtVariable y = new SmtVariable("y", BSort.elementSort, false); + SmtExpr xMemberA = SmtBinaryExpr.Op.MEMBER.make(x.getVariable(), A); + SmtExpr yMemberB = SmtBinaryExpr.Op.MEMBER.make(y.getVariable(), B); + + SmtVariable u = new SmtVariable("u", ASort.elementSort, false); + SmtExpr uMemberA = SmtBinaryExpr.Op.MEMBER.make(u.getVariable(), A); + + // multiplicitySet subset of A lone -> set B + // and + // forall y in B. + // (forall x in A. xy not in multiplicitySet) + // or + // (exists x in A . xy in multiplicitySet and + // forall u in A. u != x implies uy not in multiplicitySet) + + + SmtExpr xyTuple = getTupleConcatenation(ASort, BSort, x, y); + SmtExpr uyTuple = getTupleConcatenation(ASort, BSort, u, y); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, multiplicitySet.getVariable()); + SmtExpr uyMember = SmtBinaryExpr.Op.MEMBER.make(uyTuple, multiplicitySet.getVariable()); + + SmtExpr notXY = SmtUnaryExpr.Op.NOT.make(xyMember); + SmtExpr notUY = SmtUnaryExpr.Op.NOT.make(uyMember); + + + SmtExpr uEqualX = SmtBinaryExpr.Op.EQ.make(u.getVariable(), x.getVariable()); + SmtExpr notUEqualX = SmtUnaryExpr.Op.NOT.make(uEqualX); + + SmtExpr uImplies = SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(uMemberA, notUEqualX), notUY); + SmtExpr forAllU = SmtQtExpr.Op.FORALL.make(uImplies, u); + SmtExpr existsXBody = SmtMultiArityExpr.Op.AND.make(SmtMultiArityExpr.Op.AND.make(xMemberA, xyMember), forAllU); + + SmtExpr existsX = SmtQtExpr.Op.EXISTS.make(existsXBody, x); + SmtExpr loneEast = SmtMultiArityExpr.Op.OR.make(SmtQtExpr.Op.FORALL.make(notXY, x), existsX); + SmtExpr yImplies = SmtBinaryExpr.Op.IMPLIES.make(yMemberB, loneEast); + SmtExpr forAllY = SmtQtExpr.Op.FORALL.make(yImplies, y); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(subset, forAllY); + multiplicitySet.setConstraint(and); + smtEnv.addAuxiliaryVariable(multiplicitySet); + + return multiplicitySet.getVariable(); + } + + private SmtExpr getTupleConcatenation(SetSort ASort, SetSort BSort, SmtVariable x, SmtVariable y) + { + List tupleElements = new ArrayList<>(); + for (int i = 0; i < ((TupleSort) ASort.elementSort).elementSorts.size(); i++) + { + IntConstant index = IntConstant.getInstance(i); + tupleElements.add(SmtBinaryExpr.Op.TUPSEL.make(index, x.getVariable())); + } + + for (int i = 0; i < ((TupleSort) BSort.elementSort).elementSorts.size(); i++) + { + IntConstant index = IntConstant.getInstance(i); + tupleElements.add(SmtBinaryExpr.Op.TUPSEL.make(index, y.getVariable())); + } + + return SmtMultiArityExpr.Op.MKTUPLE.make(tupleElements); + } + + private SmtExpr translateImplies(ExprBinary expr, SmtEnv smtEnv) + { + SmtEnv smtEnvA = new SmtEnv(smtEnv); + SmtEnv smtEnvB = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnvA); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnvB); + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(A, B); + + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(implies, smtEnvA); + finalSmtExpr = exprTranslator.addAuxiliaryVariables(finalSmtExpr, smtEnvB); + return finalSmtExpr; + } + + private SmtExpr translateAnd(ExprBinary expr, SmtEnv smtEnv) + { + SmtEnv smtEnvA = new SmtEnv(smtEnv); + SmtEnv smtEnvB = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnvA); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnvB); + SmtExpr and = SmtMultiArityExpr.Op.AND.make(A, B); + + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(and, smtEnvA); + finalSmtExpr = exprTranslator.addAuxiliaryVariables(finalSmtExpr, smtEnvB); + return finalSmtExpr; + } + + private SmtExpr translateOr(ExprBinary expr, SmtEnv smtEnv) + { + SmtEnv smtEnvA = new SmtEnv(smtEnv); + SmtEnv smtEnvB = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnvA); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnvB); + SmtExpr or = SmtMultiArityExpr.Op.OR.make(A, B); + + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(or, smtEnvA); + finalSmtExpr = exprTranslator.addAuxiliaryVariables(finalSmtExpr, smtEnvB); + return finalSmtExpr; + } + + private SmtExpr translateArrow(ExprBinary expr, SmtEnv smtEnv) + { + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + SmtExpr product = SmtBinaryExpr.Op.PRODUCT.make(A, B); + return product; + } + + private SmtExpr translatePlusPlus(ExprBinary expr, SmtEnv smtEnv) + { + int rightExprArity = expr.right.type().arity(); + if (rightExprArity == 1) + { + // ++ is like a single + with arity 1 (i.e. is like a union) + return translateSetOperation(expr, SmtBinaryExpr.Op.UNION, smtEnv); + } + else + { + SmtExpr left = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr right = exprTranslator.translateExpr(expr.right, smtEnv); + SmtExpr join = right; + + for (int i = 0; i < rightExprArity - 1; ++i) + { + join = SmtBinaryExpr.Op.JOIN.make(join, AbstractTranslator.univAtom.getVariable()); + } + for (int i = 0; i < rightExprArity - 1; ++i) + { + join = SmtBinaryExpr.Op.PRODUCT.make(join, AbstractTranslator.univAtom.getVariable()); + } + + SmtExpr intersection = SmtBinaryExpr.Op.INTERSECTION.make(join, left); + SmtExpr difference = SmtBinaryExpr.Op.SETMINUS.make(left, intersection); + SmtExpr union = SmtBinaryExpr.Op.UNION.make(difference, right); + + return union; + + } + } + + private SmtExpr translateDomainRestriction(ExprBinary expr, SmtEnv smtEnv) + { + int arity = expr.right.type().arity(); + + if (arity <= 1) + { + // arity should be greater than one + throw new UnsupportedOperationException(); + } + else + { + SmtExpr left = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr right = exprTranslator.translateExpr(expr.right, smtEnv); + + // right type should be a set of tuples + SetSort rightSort = (SetSort) right.getSort(); + TupleSort tuple = (TupleSort) rightSort.elementSort; + for (int i = 1; i < arity; i++) + { + UninterpretedSort sort = (UninterpretedSort) tuple.elementSorts.get(i); + if (sort.equals(AbstractTranslator.atomSort)) + { + left = SmtBinaryExpr.Op.PRODUCT.make(left, translator.univAtom.getVariable()); + } + else + { + left = SmtBinaryExpr.Op.PRODUCT.make(left, translator.univInt.getVariable()); + } + } + SmtBinaryExpr intersection = SmtBinaryExpr.Op.INTERSECTION.make(left, right); + return intersection; + } + } + + private SmtExpr translateRangeRestriction(ExprBinary expr, SmtEnv smtEnv) + { + int arity = expr.left.type().arity(); + + if (arity <= 1) + { + // arity should be greater than one + throw new UnsupportedOperationException(); + } + else + { + SmtExpr left = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr right = exprTranslator.translateExpr(expr.right, smtEnv); + + // left type should be a set of tuples + SetSort leftSort = (SetSort) left.getSort(); + TupleSort tuple = (TupleSort) leftSort.elementSort; + for (int i = 0; i < arity - 1; i++) + { + UninterpretedSort sort = (UninterpretedSort) tuple.elementSorts.get(i); + if (sort.equals(AbstractTranslator.atomSort)) + { + right = SmtBinaryExpr.Op.PRODUCT.make(translator.univAtom.getVariable(), right); + } + else + { + right = SmtBinaryExpr.Op.PRODUCT.make(translator.univInt.getVariable(), right); + } + } + + SmtBinaryExpr intersection = SmtBinaryExpr.Op.INTERSECTION.make(left, right); + + return intersection; + } + } + + private SmtExpr translateComparison(ExprBinary expr, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + // Right hand side is a expression and right hand side is a constant + if (((expr.left instanceof ExprUnary) && ((ExprUnary) expr.left).op == ExprUnary.Op.CARDINALITY && + (expr.right instanceof ExprConstant))) + { + return translateCardinality(expr, op, smtEnv); + } + else if ((expr.right instanceof ExprUnary) && ((ExprUnary) expr.right).op == ExprUnary.Op.CARDINALITY && + (expr.left instanceof ExprConstant)) + { + return translateCardinality(expr, op, smtEnv); + } + else + { + SmtEnv envA = new SmtEnv(smtEnv); + SmtEnv envB = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, envA); + SmtExpr B = exprTranslator.translateExpr(expr.right, envB); + SmtExpr comparisonExpr = getComparison(op, A, B); + SmtExpr finalExpr = exprTranslator.addAuxiliaryVariables(comparisonExpr, envA); + finalExpr = exprTranslator.addAuxiliaryVariables(finalExpr, envB); + return finalExpr; + } + } + + private SmtExpr getComparison(SmtBinaryExpr.Op op, SmtExpr left, SmtExpr right) + { + SmtVariable x = new SmtVariable("x", AbstractTranslator.uninterpretedInt, false); + SmtVariable y = new SmtVariable("y", AbstractTranslator.uninterpretedInt, false); + SmtExpr xTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, x.getVariable()); + SmtExpr yTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, y.getVariable()); + SmtExpr xSingleton = SmtUnaryExpr.Op.SINGLETON.make(xTuple); + SmtExpr ySingleton = SmtUnaryExpr.Op.SINGLETON.make(yTuple); + SmtExpr xValue = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, x.getVariable()); + SmtExpr yValue = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, y.getVariable()); + + SmtExpr relation1EqualsX = SmtBinaryExpr.Op.EQ.make(xSingleton, left); + SmtExpr relation2EqualsY = SmtBinaryExpr.Op.EQ.make(ySingleton, right); + SmtExpr and1 = SmtMultiArityExpr.Op.AND.make(relation1EqualsX, relation2EqualsY); + + SmtExpr comparison = op.make(xValue, yValue); + SmtExpr and2 = SmtMultiArityExpr.Op.AND.make(and1, comparison); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(and2, Arrays.asList(x, y)); + + //ToDo: remove these 2 lines +// Assertion assertion = new Assertion(left + " " + op + " " + right , exists); +// exprTranslator.translator.smtProgram.addAssertion(assertion); + return exists; + } + + private SmtExpr translateEqComparison(ExprBinary expr, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + + if ((expr.left instanceof ExprUnary && + ((ExprUnary) expr.left).op == ExprUnary.Op.CARDINALITY) || + (expr.right instanceof ExprUnary && + ((ExprUnary) expr.right).op == ExprUnary.Op.CARDINALITY) + ) + { + return translateCardinality(expr, op, smtEnv); + } + + SmtEnv smtEnvA = new SmtEnv(smtEnv); + SmtEnv smtEnvB = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnvA); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnvB); + + A = TranslatorUtils.makeRelation(A); + B = TranslatorUtils.makeRelation(B); + + if (A.getSort().equals(AbstractTranslator.setOfIntSortTuple)) + { + A = exprTranslator.translator.handleIntConstant(A); + } + + if (B.getSort().equals(AbstractTranslator.setOfIntSortTuple)) + { + B = exprTranslator.translator.handleIntConstant(B); + } + + SmtExpr equality = SmtBinaryExpr.Op.EQ.make(A, B); + + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(equality, smtEnvA); + finalSmtExpr = exprTranslator.addAuxiliaryVariables(finalSmtExpr, smtEnvB); + return finalSmtExpr; + } + + private SmtExpr translateCardinality(ExprBinary expr, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + // CVC4 doesn't support comparison between 2 cardinality expressions + if + (expr.left instanceof ExprUnary && + ((ExprUnary) expr.left).op == ExprUnary.Op.CARDINALITY && + expr.right instanceof ExprUnary && + ((ExprUnary) expr.right).op == ExprUnary.Op.CARDINALITY + ) + { + throw new UnsupportedOperationException("CVC4 doesn't support comparision between 2 cardinality expressions."); + } + + if + ( + (expr.left instanceof ExprUnary && + ((ExprUnary) expr.left).op == ExprUnary.Op.CARDINALITY && + (!(expr.right instanceof ExprConstant && + ((ExprConstant) expr.right).op == ExprConstant.Op.NUMBER))) || + (expr.right instanceof ExprUnary && + ((ExprUnary) expr.right).op == ExprUnary.Op.CARDINALITY && + (!(expr.left instanceof ExprConstant && + ((ExprConstant) expr.left).op == ExprConstant.Op.NUMBER))) + ) + { + throw new UnsupportedOperationException("CVC4 only supports cardinality with constant numbers"); + } + + + // translate cardinality differently + if + ((expr.left instanceof ExprUnary && + ((ExprUnary) expr.left).op == ExprUnary.Op.CARDINALITY) + ) + { + int n = ((ExprConstant) expr.right).num; + SmtExpr equality = translateCardinalityComparison((ExprUnary) expr.left, n, op, smtEnv); + return equality; + } + + if + ((expr.right instanceof ExprUnary && + ((ExprUnary) expr.right).op == ExprUnary.Op.CARDINALITY) + ) + { + int n = ((ExprConstant) expr.left).num; + SmtExpr equality = translateCardinalityComparison((ExprUnary) expr.right, n, op, smtEnv); + return equality; + } + + throw new UnsupportedOperationException(); + } + + private SmtExpr translateCardinalityComparison(ExprUnary expr, int n, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + SmtExpr setExpr = exprTranslator.translateExpr(expr.sub, newSmtEnv); + SetSort setSort = (SetSort) setExpr.getSort(); + Sort elementSort = setSort.elementSort; + + // shared code + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(setSort); + SmtExpr isEmpty = SmtBinaryExpr.Op.EQ.make(setExpr, emptySet); + SmtExpr notEmpty = SmtUnaryExpr.Op.NOT.make(isEmpty); + + switch (op) + { + case EQ: + { + if (n < 0) + { + // impossible + return exprTranslator.addAuxiliaryVariables(BoolConstant.False, newSmtEnv); + } + + if (n == 0) + { + // empty set + return exprTranslator.addAuxiliaryVariables(isEmpty, newSmtEnv); + } + + List vars = generateVariables(n, elementSort); + SmtExpr cardinalitySet = generateCardinalitySet(vars); + SmtExpr equalExpr = SmtBinaryExpr.Op.EQ.make(setExpr, cardinalitySet); + SmtExpr andExpr = makeDistinct(equalExpr, vars); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(andExpr, vars); + return exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + } + + case LT: + { + if (n <= 0) + { + // impossible + return exprTranslator.addAuxiliaryVariables(BoolConstant.False, newSmtEnv); + } + + if (n == 1) + { + // empty set + return exprTranslator.addAuxiliaryVariables(isEmpty, newSmtEnv); + } + + List vars = generateVariables(n - 1, elementSort); + SmtExpr cardinalitySet = generateCardinalitySet(vars); + SmtExpr subsetExpr = SmtBinaryExpr.Op.SUBSET.make(setExpr, cardinalitySet); + SmtExpr andExpr = makeDistinct(subsetExpr, vars); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(andExpr, vars); + return exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + } + + case LTE: + { + if (n <= -1) + { + // impossible + return exprTranslator.addAuxiliaryVariables(BoolConstant.False, newSmtEnv); + } + + if (n == 0) + { + // empty set + return exprTranslator.addAuxiliaryVariables(isEmpty, newSmtEnv); + } + + List vars = generateVariables(n, elementSort); + SmtExpr cardinalitySet = generateCardinalitySet(vars); + SmtExpr subsetExpr = SmtBinaryExpr.Op.SUBSET.make(setExpr, cardinalitySet); + SmtExpr andExpr = makeDistinct(subsetExpr, vars); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(andExpr, vars); + return exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + } + + case GT: + { + if (n <= -1) + { + // valid + return exprTranslator.addAuxiliaryVariables(BoolConstant.True, newSmtEnv); + } + if (n == 0) + { + // not empty + return exprTranslator.addAuxiliaryVariables(notEmpty, newSmtEnv); + } + + List vars = generateVariables(n + 1, elementSort); + SmtExpr cardinalitySet = generateCardinalitySet(vars); + SmtExpr subsetExpr = SmtBinaryExpr.Op.SUBSET.make(cardinalitySet, setExpr); + SmtExpr andExpr = makeDistinct(subsetExpr, vars); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(andExpr, vars); + return exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + } + + case GTE: + { + if (n <= 0) + { + // valid + return exprTranslator.addAuxiliaryVariables(BoolConstant.True, newSmtEnv); + } + + if (n == 1) + { + // not empty + return exprTranslator.addAuxiliaryVariables(notEmpty, newSmtEnv); + } + + List vars = generateVariables(n, elementSort); + SmtExpr cardinalitySet = generateCardinalitySet(vars); + SmtExpr subsetExpr = SmtBinaryExpr.Op.SUBSET.make(cardinalitySet, setExpr); + SmtExpr andExpr = makeDistinct(subsetExpr, vars); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(andExpr, vars); + return exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + } + + default: + { + throw new RuntimeException("Unexpected cardinality operator" + op); + } + } + } + + private SmtExpr makeDistinct(SmtExpr boolExpr, List vars) + { + assert (boolExpr.getSort().equals(AbstractTranslator.boolSort)); + if (vars.size() == 1) + { + return boolExpr; + } + List exprs = vars.stream().map(v -> v.getVariable()).collect(Collectors.toList()); + SmtExpr distinct = SmtMultiArityExpr.Op.DISTINCT.make(exprs); + SmtExpr and = SmtMultiArityExpr.Op.AND.make(boolExpr, distinct); + return and; + } + + private SmtExpr generateCardinalitySet(List vars) + { + assert (vars.size() >= 1); + + SmtExpr set = SmtUnaryExpr.Op.SINGLETON.make(vars.get(0).getVariable()); + + if (vars.size() == 1) + { + return set; + } + + for (int i = 1; i < vars.size(); i++) + { + set = SmtMultiArityExpr.Op.INSERT.make(vars.get(i).getVariable(), set); + } + + return set; + } + + private List generateVariables(int n, Sort elementSort) + { + if (n <= 0) + { + throw new RuntimeException(String.format("Expected %1$d to be greater than zero. ", n)); + } + List vars = new ArrayList<>(); + for (int i = 0; i < n; i++) + { + String freshName = TranslatorUtils.getFreshName(elementSort); + vars.add(new SmtVariable(freshName, elementSort, false)); + } + return vars; + } + + private SmtExpr translateSetOperation(ExprBinary expr, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + SmtExpr left = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr right = exprTranslator.translateExpr(expr.right, smtEnv); + + if (left instanceof Variable && + (!(((Variable) left).getDeclaration().getSort() instanceof SetSort))) + { + left = TranslatorUtils.makeRelation((Variable) left); + } + else if (left instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) left).getOp() == SmtMultiArityExpr.Op.MKTUPLE) + { + left = AlloyUtils.mkSingletonOutOfTuple((SmtMultiArityExpr) left); + } + if (right instanceof Variable && + (!(((Variable) right).getDeclaration().getSort() instanceof SetSort))) + { + right = TranslatorUtils.makeRelation((Variable) right); + } + else if (right instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) right).getOp() == SmtMultiArityExpr.Op.MKTUPLE) + { + right = AlloyUtils.mkSingletonOutOfTuple((SmtMultiArityExpr) right); + } + + SmtBinaryExpr operation = op.make(left, right); + return operation; + } + + private SmtExpr translateSubsetOperation(ExprBinary expr, SmtEnv smtEnv) + { + SmtEnv smtEnvA = new SmtEnv(smtEnv); + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnvA); + A = exprTranslator.translator.handleIntConstant(A); + + SmtEnv smtEnvB = new SmtEnv(smtEnvA); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnvB); + B = exprTranslator.translator.handleIntConstant(B); + + // left sort | right sort | Translation + // ------------------------------------- + // tuple | tuple | (= A B) + // tuple | set | (member tuple set) + // set | set | (subset A B) + SmtExpr translation; + if (A.getSort() instanceof TupleSort && B.getSort() instanceof TupleSort) + { + translation = SmtBinaryExpr.Op.EQ.make(A, B); + } + else if (A.getSort() instanceof SetSort && B.getSort() instanceof SetSort) + { + translation = SmtBinaryExpr.Op.SUBSET.make(A, B); + } + else if (A.getSort() instanceof TupleSort && B.getSort() instanceof SetSort) + { + translation = SmtBinaryExpr.Op.MEMBER.make(A, B); + } + else + { + A = SmtMultiArityExpr.Op.MKTUPLE.make(A); + translation = SmtBinaryExpr.Op.MEMBER.make(A, B); + } + + // auxiliary variables for expression A should be handled before coming here + if (!smtEnvA.getAuxiliaryVariables().isEmpty()) + { + for (SmtVariable variable : smtEnvA.getAuxiliaryVariables()) + { + smtEnv.addAuxiliaryVariable(variable); + } + } + + if (!smtEnvB.getAuxiliaryVariables().isEmpty()) + { + //if not empty, there should be a only one auxiliary variable for set B + List variables = smtEnvB.getAuxiliaryVariables(); + assert (variables.size() == 1); + // When there is an auxiliary variable, this means the IN operator is used + // as a multiplicity constraint for A, and not as subset operator. + // Example:'s in (A one -> some A)'. The translation is not (subset s temp) + // where 'temp' is the translation of (A one -> some A). But the translation should + // restrict 's' to satisfy the multiplicity constraint. + + SmtVariable variable = variables.get(0); + // if there is no constraint, there should not be an auxiliary variable + assert (variable.getConstraint() != null); + + if (variable.getSort() instanceof SetSort) + { + SmtExpr solution = exprTranslator.solveForVariable(variable.getVariable(), B, A); + SmtExpr constraint = variable.getConstraint().replace(variable.getVariable(), solution); + return constraint; + } + else + { + SmtExpr choose = SmtUnaryExpr.Op.CHOOSE.make(A); + SmtExpr constraint = variable.getConstraint().replace(variable.getVariable(), choose); + // add a singleton constraint + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(choose); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(singleton, A); + constraint = SmtMultiArityExpr.Op.AND.make(constraint, equal); + return constraint; + } + } + + return translation; + } + + private SmtExpr translateJoin(ExprBinary expr, SmtEnv smtEnv) + { + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + A = TranslatorUtils.makeRelation(A); + B = TranslatorUtils.makeRelation(B); + SmtBinaryExpr join = SmtBinaryExpr.Op.JOIN.make(A, B); + return join; + } + + public SmtExpr translateArithmetic(ExprBinary expr, SmtBinaryExpr.Op op, SmtEnv smtEnv) + { + SmtExpr A = exprTranslator.translateExpr(expr.left, smtEnv); + SmtExpr B = exprTranslator.translateExpr(expr.right, smtEnv); + A = convertIntConstantToSet(A); + + B = convertIntConstantToSet(B); + + if (A.getSort().equals(AbstractTranslator.setOfIntSortTuple)) + { + A = translator.handleIntConstant(A); + } + + if (B.getSort().equals(AbstractTranslator.setOfIntSortTuple)) + { + B = translator.handleIntConstant(B); + } + + String freshName = TranslatorUtils.getFreshName(AbstractTranslator.setOfUninterpretedIntTuple); + + SmtVariable x = new SmtVariable("x", AbstractTranslator.uninterpretedInt, false); + SmtVariable y = new SmtVariable("y", AbstractTranslator.uninterpretedInt, false); + SmtVariable z = new SmtVariable("z", AbstractTranslator.uninterpretedInt, false); + + SmtExpr xTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, x.getVariable()); + SmtExpr yTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, y.getVariable()); + SmtExpr zTuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, z.getVariable()); + + SmtExpr xValue = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, x.getVariable()); + SmtExpr yValue = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, y.getVariable()); + SmtExpr zValue = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, z.getVariable()); + + SmtExpr xyOperation = op.make(xValue, yValue); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(xyOperation, zValue); + + //ToDo: refactor this into optimization +// if (translator.alloySettings.integerSingletonsOnly) +// { +// // A= {x}, B = {y} => Result = {z} where z = (x operation y) +// SmtExpr xSingleton = SmtUnaryExpr.Op.SINGLETON.make(xTuple); +// SmtExpr ySingleton = SmtUnaryExpr.Op.SINGLETON.make(yTuple); +// SmtExpr singletonA = SmtBinaryExpr.Op.EQ.make(A, xSingleton); +// SmtExpr singletonB = SmtBinaryExpr.Op.EQ.make(B, ySingleton); +// +// SmtExpr and = SmtMultiArityExpr.Op.AND.make(equal, singletonA, singletonB); +// +// SmtQtExpr exists = SmtQtExpr.Op.EXISTS.make(and, x, y, z); +// smtEnv.addAuxiliaryFormula(exists); +// return z.getVariable(); +// } + + SmtVariable result = new SmtVariable(freshName, AbstractTranslator.setOfUninterpretedIntTuple, false); + SmtExpr resultSmtExpr = result.getVariable(); + + // for all z : uninterpretedInt. x in Result implies + // exists x, y :uninterpretedInt. x in A and y in B and (x, y, z) in operation + + SmtExpr xMember = SmtBinaryExpr.Op.MEMBER.make(xTuple, A); + SmtExpr yMember = SmtBinaryExpr.Op.MEMBER.make(yTuple, B); + SmtExpr zMember = SmtBinaryExpr.Op.MEMBER.make(zTuple, resultSmtExpr); + + SmtExpr xyMember = SmtMultiArityExpr.Op.AND.make(xMember, yMember); + SmtExpr and2 = SmtMultiArityExpr.Op.AND.make(equal, xyMember); + SmtExpr exists1 = SmtQtExpr.Op.EXISTS.make(and2, x, y); + + SmtExpr implies1 = SmtBinaryExpr.Op.IMPLIES.make(zMember, exists1); + SmtExpr axiom1 = SmtQtExpr.Op.FORALL.make(implies1, z); + + + // for all x, y : uninterpretedInt. x in A and y in B implies + // exists z :uninterpretedInt. x in Result and (x, y, z) in operation + + SmtExpr and3 = SmtMultiArityExpr.Op.AND.make(equal, zMember); + SmtExpr exists2 = SmtQtExpr.Op.EXISTS.make(and3, z); + + SmtExpr implies2 = SmtBinaryExpr.Op.IMPLIES.make(xyMember, exists2); + SmtExpr axiom2 = SmtQtExpr.Op.FORALL.make(implies2, x, y); + + SmtExpr axioms = SmtMultiArityExpr.Op.AND.make(axiom1, axiom2); + + result.setConstraint(axioms); + smtEnv.addAuxiliaryVariable(result); + + return resultSmtExpr; + } + + private SmtExpr convertIntConstantToSet(SmtExpr A) + { + if (A instanceof IntConstant) + { + FunctionDeclaration uninterpretedInt = translator.getUninterpretedIntConstant((IntConstant) A); + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, uninterpretedInt.getVariable()); + if (translator.alloySettings.integerSingletonsOnly) + { + A = SmtUnaryExpr.Op.SINGLETON.make(tuple); + } + else + { + A = tuple; + } + } + return A; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprCallTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprCallTranslator.java new file mode 100644 index 000000000..d096d6e2e --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprCallTranslator.java @@ -0,0 +1,82 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprCall; +import edu.mit.csail.sdg.ast.Func; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.List; + +public class ExprCallTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + + public ExprCallTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.translator = exprTranslator.translator; + } + + SmtExpr translateExprCall(ExprCall exprCall, SmtEnv smtEnv) + { + String funcName = exprCall.fun.label; +// +//// if (exprCall.fun.pos.filename.contains("models/util/ordering.als".replace("/", File.separator))) +//// { +//// return new SmtCallExpr(translator.functionsMap.get(func.label), arguments); +//// } + if (funcName.equals("integer/plus") || funcName.equals("integer/add")) + { + Expr expr = ExprBinary.Op.IPLUS.make(null, null, exprCall.args.get(0), exprCall.args.get(1)); + return exprTranslator.exprBinaryTranslator.translateArithmetic((ExprBinary) expr, SmtBinaryExpr.Op.PLUS, smtEnv); + } + else if (funcName.equals("integer/minus") || funcName.equals("integer/sub")) + { + Expr expr = ExprBinary.Op.IMINUS.make(null, null, exprCall.args.get(0), exprCall.args.get(1)); + return exprTranslator.exprBinaryTranslator.translateArithmetic((ExprBinary) expr, SmtBinaryExpr.Op.MINUS, smtEnv); + } + else if (funcName.equals("integer/mul")) + { + Expr expr = ExprBinary.Op.MUL.make(null, null, exprCall.args.get(0), exprCall.args.get(1)); + return exprTranslator.exprBinaryTranslator.translateArithmetic((ExprBinary) expr, SmtBinaryExpr.Op.MULTIPLY, smtEnv); + } + else if (funcName.equals("integer/div")) + { + Expr expr = ExprBinary.Op.DIV.make(null, null, exprCall.args.get(0), exprCall.args.get(1)); + return exprTranslator.exprBinaryTranslator.translateArithmetic((ExprBinary) expr, SmtBinaryExpr.Op.DIVIDE, smtEnv); + } + else if (funcName.equals("integer/rem")) + { + Expr expr = ExprBinary.Op.REM.make(null, null, exprCall.args.get(0), exprCall.args.get(1)); + return exprTranslator.exprBinaryTranslator.translateArithmetic((ExprBinary) expr, SmtBinaryExpr.Op.MOD, smtEnv); + } + + return buildSmtCallExpr(exprCall, smtEnv); + } + + private SmtExpr buildSmtCallExpr(ExprCall exprCall, SmtEnv smtEnv) + { + Func func = exprCall.fun; + + FunctionDeclaration function = translator.getFuncTranslation(func); + + List arguments = new ArrayList<>(); + + for (int i = 0; i < exprCall.args.size(); i++) + { + SmtExpr expr = exprTranslator.translateExpr(exprCall.args.get(i), smtEnv); + if (function.getSort(i) instanceof TupleSort) + { + expr = SmtUnaryExpr.Op.CHOOSE.make(expr); + } + arguments.add(expr); + } + + SmtCallExpr callExpr = new SmtCallExpr(function, arguments); + return callExpr; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprLetTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprLetTranslator.java new file mode 100644 index 000000000..74ff59c4a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprLetTranslator.java @@ -0,0 +1,49 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.ExprLet; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.smtAst.BoolSort; +import edu.uiowa.smt.smtAst.SmtExpr; +import edu.uiowa.smt.smtAst.SmtLetExpr; +import edu.uiowa.smt.smtAst.SmtVariable; + +import java.util.HashMap; +import java.util.Map; + +public class ExprLetTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + + public ExprLetTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.translator = exprTranslator.translator; + } + + SmtExpr translateExprLet(ExprLet exprLet, SmtEnv smtEnv) + { + SmtEnv letEnv = new SmtEnv(smtEnv); + SmtExpr smtExpr = exprTranslator.translateExpr(exprLet.expr, letEnv); + + SmtVariable declaration = new SmtVariable(exprLet.var.label, + smtExpr.getSort(), true); + Map map = new HashMap<>(); + map.put(declaration, smtExpr); + + letEnv.put(declaration.getName(), declaration.getVariable()); + SmtExpr body = exprTranslator.translateExpr(exprLet.sub, letEnv); + SmtExpr let = new SmtLetExpr(map, body); + if (let.getSort() instanceof BoolSort) + { + SmtExpr finalExpr = exprTranslator.addAuxiliaryVariables(let, letEnv); + return finalExpr; + } + // add auxiliary variables to smtEnv + for (SmtVariable variable : letEnv.getAuxiliaryVariables()) + { + smtEnv.addAuxiliaryVariable(variable); + } + return let; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprQtTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprQtTranslator.java new file mode 100644 index 000000000..a8f563692 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprQtTranslator.java @@ -0,0 +1,350 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.*; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.*; +import java.util.stream.Collectors; + +public class ExprQtTranslator +{ + final ExprTranslator exprTranslator; + final ExprUnaryTranslator exprUnaryTranslator; + final ExprBinaryTranslator exprBinaryTranslator; + final Alloy2SmtTranslator translator; + + public ExprQtTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.exprUnaryTranslator = exprTranslator.exprUnaryTranslator; + this.exprBinaryTranslator = exprTranslator.exprBinaryTranslator; + this.translator = exprTranslator.translator; + } + + SmtExpr translateExprQt(ExprQt exprQt, SmtEnv smtEnv) + { + // create a new scope for quantified variables + SmtEnv declsEnv = new SmtEnv(smtEnv); + List smtVariables = exprTranslator.declTranslator.translateDecls(exprQt.decls, declsEnv); + SmtExpr constraints = exprTranslator.declTranslator.getDisjointConstraints(exprQt.decls, declsEnv); + + // translate the body of the quantified expression + SmtEnv bodyEnv = new SmtEnv(declsEnv); + SmtExpr body = exprTranslator.translateExpr(exprQt.sub, bodyEnv); + body = exprTranslator.addAuxiliaryVariables(body, bodyEnv); + switch (exprQt.op) + { + case ALL: + return translateAllQuantifier(body, smtVariables, declsEnv, constraints); + case NO: + return translateNoQuantifier(body, smtVariables, declsEnv, constraints); + case SOME: + return translateSomeQuantifier(body, smtVariables, declsEnv, constraints); + case ONE: + return translateOneQuantifier(body, smtVariables, declsEnv, constraints); + case LONE: + return translateLoneQuantifier(body, smtVariables, declsEnv, constraints); + case COMPREHENSION: + return translateComprehension(exprQt, body, smtVariables, declsEnv); + default: + throw new UnsupportedOperationException(); + } + } + + private SmtExpr translateComprehension(ExprQt exprQt, SmtExpr body, List smtVariables, SmtEnv smtEnv) + { + // {x: e1, y: e2, ... | f} is translated into + // declare-fun comprehension(freeVariables): (e1 product e2 product ...) + // assert forall x, y,... (x in e1 and y in e2 ... and f <=> + // (x, y, ...) in comprehension(freeVariables)) + + // determine the sort of the alloy comprehension + List elementSorts = new ArrayList<>(); + for (SmtVariable smtVariable : smtVariables) + { + // all variables should be unary + assert (smtVariable.getSort() instanceof TupleSort); + TupleSort tupleSort = (TupleSort) smtVariable.getSort(); + elementSorts.add(tupleSort.elementSorts.get(0)); + } + Sort returnSort = new SetSort(new TupleSort(elementSorts)); + + // determine the free variables for the set comprehension from the environment, and + // add theme as arguments to the comprehension function + LinkedHashMap argumentsMap = smtEnv.getParent().getVariables(); + List argumentSorts = new ArrayList<>(); + List arguments = new ArrayList<>(); + List quantifiedArguments = new ArrayList<>(); + for (Map.Entry argument : argumentsMap.entrySet()) + { + Variable variable = (Variable) argument.getValue(); + // add the variable as an argument to the call expression + arguments.add(variable); + Sort sort = variable.getSort(); + // add the sort of the variable to the declaration of the comprehension function + argumentSorts.add(sort); + quantifiedArguments.add((SmtVariable) variable.getDeclaration()); + } + + FunctionDeclaration setFunction = new FunctionDeclaration(TranslatorUtils.getFreshName(returnSort), argumentSorts, returnSort, false); + translator.smtScript.addFunction(setFunction); + + SmtExpr smtCallExpr; + if (argumentSorts.size() == 0) + { + smtCallExpr = setFunction.getVariable(); + } + else + { + List smtExprs = AlloyUtils.getFunctionCallArguments(quantifiedArguments, argumentsMap); + smtCallExpr = new SmtCallExpr(setFunction, smtExprs); + } + + SmtExpr membership = TranslatorUtils.getVariablesConstraints(smtVariables); + + List quantifiedSmtExprs = smtVariables.stream() + .map(v -> SmtBinaryExpr.Op.TUPSEL.make(IntConstant.getInstance(0), v.getVariable())) + .collect(Collectors.toList()); + + SmtExpr tuple = SmtMultiArityExpr.Op.MKTUPLE.make(quantifiedSmtExprs); + + SmtExpr tupleMember = SmtBinaryExpr.Op.MEMBER.make(tuple, smtCallExpr); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(membership, body); + + SmtExpr equivalence = SmtBinaryExpr.Op.EQ.make(tupleMember, and); + + // add variables defined in functions, predicates or let expression to the list of quantifiers + quantifiedArguments.addAll(smtVariables); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(equivalence, quantifiedArguments); + + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(exprQt.pos), + setFunction.getName() + " = " + exprQt.toString(), forAll); + translator.smtScript.addAssertion(assertion); + + if (argumentSorts.size() == 0) + { + return setFunction.getVariable(); + } + else + { + return new SmtCallExpr(setFunction, arguments); + } + } + + + private SmtVariable getVariableDeclaration(Expr expr, String variableName, SetSort setSort, SmtExpr range) + { + if (expr instanceof Sig) + { + return getVariableDeclaration(variableName, setSort, range); + } + if (expr instanceof ExprUnary) + { + ExprUnary.Op multiplicityOperator = ((ExprUnary) expr).op; + switch (multiplicityOperator) + { + + case ONEOF: + { + return getVariableDeclaration(variableName, setSort, range); + } + case SOMEOF: // same as SETOF + case LONEOF: // same as SETOF + case NOOP: // only happens with relations + case SETOF: + { + SmtVariable declaration = new SmtVariable(variableName, setSort, true); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(declaration.getVariable(), range); + declaration.setConstraint(subset); + return declaration; + } + default: + throw new UnsupportedOperationException(); + } + } + if (expr instanceof ExprBinary) + { + ExprBinary.Op multiplicityOperator = ((ExprBinary) expr).op; + switch (multiplicityOperator) + { + case ARROW: + case ANY_ARROW_SOME: + case ANY_ARROW_ONE: + case ANY_ARROW_LONE: + case SOME_ARROW_ANY: + case SOME_ARROW_SOME: + case SOME_ARROW_ONE: + case SOME_ARROW_LONE: + case ONE_ARROW_ANY: + case ONE_ARROW_SOME: + case ONE_ARROW_ONE: + case ONE_ARROW_LONE: + case LONE_ARROW_ANY: + case LONE_ARROW_SOME: + case LONE_ARROW_ONE: + case LONE_ARROW_LONE: + { + SmtVariable declaration = new SmtVariable(variableName, setSort, true); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(declaration.getVariable(), range); + declaration.setConstraint(subset); + return declaration; + } + default: + throw new UnsupportedOperationException(); + } + } + throw new UnsupportedOperationException(); + } + + private SmtVariable getVariableDeclaration(String variableName, SetSort setSort, SmtExpr range) + { + SmtVariable declaration = new SmtVariable(variableName, setSort.elementSort, true); + SmtExpr member = SmtBinaryExpr.Op.MEMBER.make(declaration.getVariable(), range); + declaration.setConstraint(member); + return declaration; + } + + private SmtExpr getMultiplicityConstraint(Expr expr, SmtVariable variable, SetSort setSort) + { + if (expr instanceof ExprUnary) + { + ExprUnary.Op multiplicityOperator = ((ExprUnary) expr).op; + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(setSort); + switch (multiplicityOperator) + { + case NOOP: // same as ONEOF + case ONEOF: + { + // variable.getSort() is a tuple sort, so there is no constraint + return BoolConstant.True; + } + case SOMEOF: + { + // the set is not empty + SmtExpr empty = SmtBinaryExpr.Op.EQ.make(variable.getVariable(), emptySet); + SmtExpr notEmpty = SmtUnaryExpr.Op.NOT.make(empty); + return notEmpty; + } + case SETOF: + { + // variable.getSort() is a set, so there is no constraint + return BoolConstant.True; + } + case LONEOF: + { + // either the set is empty or a singleton + SmtExpr empty = SmtBinaryExpr.Op.EQ.make(variable.getVariable(), emptySet); + SmtVariable singleElement = new SmtVariable(TranslatorUtils.getFreshName(setSort.elementSort), setSort.elementSort, false); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(singleElement.getVariable()); + SmtExpr isSingleton = SmtBinaryExpr.Op.EQ.make(variable.getVariable(), singleton); + SmtExpr emptyOrSingleton = SmtMultiArityExpr.Op.OR.make(empty, isSingleton); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(emptyOrSingleton, singleElement); + return exists; + } + default: + throw new UnsupportedOperationException(); + } + } + if (expr instanceof ExprBinary) + { + return BoolConstant.True; + } + throw new UnsupportedOperationException(); + } + + private SmtExpr translateAllQuantifier(SmtExpr body, List smtVariables, + SmtEnv smtEnv, SmtExpr constraints) + { + // all x: e1, y: e2, ... | f is translated into + // forall x, y,... (x in e1 and y in e2 and ... and constraints implies f) + + + SmtExpr multiplicity = TranslatorUtils.getVariablesConstraints(smtVariables); + SmtExpr and = SmtMultiArityExpr.Op.AND.make(multiplicity, constraints); + body = SmtBinaryExpr.Op.IMPLIES.make(and, body); + + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(body, smtVariables); + return forAll; + } + + private SmtExpr translateNoQuantifier(SmtExpr body, List smtVariables, + SmtEnv smtEnv, SmtExpr multiplicityConstraints) + { + SmtExpr notBody = SmtUnaryExpr.Op.NOT.make(body); + return translateAllQuantifier(notBody, smtVariables, smtEnv, multiplicityConstraints); + } + + private SmtExpr translateSomeQuantifier(SmtExpr body, List smtVariables, + SmtEnv smtEnv, SmtExpr constraints) + { + + // some x: e1, y: e2, ... | f is translated into + // exists x, y,... (x in e1 and y in e2 and ... and constraints and f) + + SmtExpr multiplicity = TranslatorUtils.getVariablesConstraints(smtVariables); + SmtMultiArityExpr and = SmtMultiArityExpr.Op.AND.make(multiplicity, constraints, body); + + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(and, smtVariables); + return exists; + } + + private SmtExpr translateOneQuantifier(SmtExpr body, List smtVariables, + SmtEnv smtEnv, SmtExpr constraints) + { + // one x: e1, y: e2, ... | f(x, y, ...) is translated into + // exists x, y, ... ( x in e1 and y in e2 and ... and constraints(x, y, ...) and f(x, y, ...) and + // for all x', y', ... (x in e1 and y in e2 ... and constraints(x', y', ...) + // and not (x' = x and y' = y ...) implies not f(x', y', ...))) + + SmtExpr multiplicity = TranslatorUtils.getVariablesConstraints(smtVariables); + SmtExpr existsAnd = SmtMultiArityExpr.Op.AND.make(multiplicity, constraints, body); + + // create new variables x', y', ... + List newVariables = TranslatorUtils.copySmtVariables(smtVariables); + + // build the expr (x' = x and y' = y ...) + SmtExpr oldEqualNew = BoolConstant.True; + for (int i = 0; i < smtVariables.size(); i++) + { + SmtVariable oldVariable = smtVariables.get(i); + SmtVariable newVariable = newVariables.get(i); + oldEqualNew = SmtMultiArityExpr.Op.AND.make(oldEqualNew, SmtBinaryExpr.Op.EQ.make(oldVariable.getVariable(), newVariable.getVariable())); + } + SmtExpr notOldEqualNew = SmtUnaryExpr.Op.NOT.make(oldEqualNew); + + // build a new body from the old one by replacing old variables with new variables + SmtExpr newBody = body; + for (int i = 0; i < smtVariables.size(); i++) + { + newBody = newBody.substitute(smtVariables.get(i).getVariable(), newVariables.get(i).getVariable()); + } + newBody = SmtUnaryExpr.Op.NOT.make(newBody); + + SmtExpr newMultiplicity = TranslatorUtils.getVariablesConstraints(newVariables); + + SmtExpr forAllAnd = SmtMultiArityExpr.Op.AND.make(newMultiplicity, constraints, notOldEqualNew); + + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(forAllAnd, newBody); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, newVariables); + existsAnd = SmtMultiArityExpr.Op.AND.make(existsAnd, forAll); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(existsAnd, smtVariables); + return exists; + } + + private SmtExpr translateLoneQuantifier(SmtExpr body, List smtVariables, + SmtEnv smtEnv, SmtExpr constraints) + { + // lone ... | f is translated into + // (all ... | not f) or (one ... | f) + + SmtExpr notBody = SmtUnaryExpr.Op.NOT.make(body); + SmtExpr allNot = translateAllQuantifier(notBody, smtVariables, smtEnv, constraints); + SmtExpr one = translateOneQuantifier(body, smtVariables, smtEnv, constraints); + SmtExpr or = SmtMultiArityExpr.Op.OR.make(allNot, one); + return or; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprTranslator.java new file mode 100644 index 000000000..d8d88afa8 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprTranslator.java @@ -0,0 +1,358 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.*; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ExprTranslator +{ + final Alloy2SmtTranslator translator; + + final ExprUnaryTranslator exprUnaryTranslator; + + final ExprBinaryTranslator exprBinaryTranslator; + + final ExprQtTranslator exprQtTranslator; + + final ExprCallTranslator exprCallTranslator; + + final ExprLetTranslator exprLetTranslator; + + final ExprVarTranslator exprVarTranslator; + + final DeclTranslator declTranslator; + + public ExprTranslator(Alloy2SmtTranslator translator) + { + this.translator = translator; + this.exprVarTranslator = new ExprVarTranslator(this); + this.exprUnaryTranslator = new ExprUnaryTranslator(this); + this.exprBinaryTranslator = new ExprBinaryTranslator(this); + this.exprQtTranslator = new ExprQtTranslator(this); + this.exprCallTranslator = new ExprCallTranslator(this); + this.exprLetTranslator = new ExprLetTranslator(this); + this.declTranslator = new DeclTranslator(this); + } + + public SmtExpr translateFormula(String label, Expr expr) + { + assert (expr.type() == Type.FORMULA); + SmtEnv smtEnv = new SmtEnv(); + SmtExpr formula = translateExpr(expr, smtEnv); + formula = addAuxiliaryVariables(formula, smtEnv); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(expr.pos), label, formula); + translator.smtScript.addAssertion(assertion); + return formula; + } + + public SmtExpr addAuxiliaryVariables(SmtExpr booleanSmtExpr, SmtEnv smtEnv) + { + assert (booleanSmtExpr.getSort().equals(AbstractTranslator.boolSort)); + List variables = smtEnv.getAuxiliaryVariables(); + if (!variables.isEmpty()) + { + SmtExpr constraints = TranslatorUtils.getVariablesConstraints(variables); + SmtExpr body = SmtMultiArityExpr.Op.AND.make(constraints, booleanSmtExpr); + booleanSmtExpr = SmtQtExpr.Op.EXISTS.make(body, variables); + } + return booleanSmtExpr; + } + + SmtExpr translateExpr(Expr expr, SmtEnv smtEnv) + { + if (expr instanceof Sig || expr instanceof Sig.Field) + { + return getExpression(expr, exprUnaryTranslator.translateExprUnary((ExprUnary) ExprUnary.Op.NOOP.make(null, expr), smtEnv)); + } + if (expr instanceof ExprVar) + { + return getExpression(expr, exprVarTranslator.translateExprVar((ExprVar) expr, smtEnv)); + } + if (expr instanceof ExprUnary) + { + return getExpression(expr, exprUnaryTranslator.translateExprUnary((ExprUnary) expr, smtEnv)); + } + else if (expr instanceof ExprBinary) + { + return getExpression(expr, exprBinaryTranslator.translateExprBinary((ExprBinary) expr, smtEnv)); + } + else if (expr instanceof ExprQt) + { + return getExpression(expr, exprQtTranslator.translateExprQt((ExprQt) expr, smtEnv)); + } + else if (expr instanceof ExprConstant) + { + return getExpression(expr, translateExprConstant((ExprConstant) expr, smtEnv)); + } + else if (expr instanceof ExprList) + { + return getExpression(expr, translateExprList((ExprList) expr, smtEnv)); + } + else if (expr instanceof ExprCall) + { + return getExpression(expr, exprCallTranslator.translateExprCall((ExprCall) expr, smtEnv)); + } + else if (expr instanceof ExprITE) + { + return getExpression(expr, translateExprITE((ExprITE) expr, smtEnv)); + } + else if (expr instanceof ExprLet) + { + return getExpression(expr, exprLetTranslator.translateExprLet((ExprLet) expr, smtEnv)); + } + + throw new UnsupportedOperationException(expr.toString()); + } + + private SmtExpr getExpression(Expr expr, SmtExpr smtExpr) + { + smtExpr.setComment(expr.toString()); + return smtExpr; + } + + public SmtExpr translateExprITE(ExprITE expr, SmtEnv smtEnv) + { + SmtExpr condExpr = translateExpr(expr.cond, smtEnv); + SmtExpr thenExpr = translateExpr(expr.left, smtEnv); + SmtExpr elseExpr = translateExpr(expr.right, smtEnv); + return new SmtIteExpr(condExpr, thenExpr, elseExpr); + } + + public SmtExpr translateExprConstant(ExprConstant expr, SmtEnv smtEnv) + { + switch (expr.op) + { + // alloy only supports integers + case NUMBER: + { + SmtExpr intConstant = IntConstant.getSingletonTuple(expr.num); + return translator.handleIntConstant(intConstant); + } + case IDEN: + return translator.idenAtom.getVariable(); + case TRUE: + return BoolConstant.True; + case FALSE: + return BoolConstant.False; + default: + throw new UnsupportedOperationException(expr.op.name()); + } + } + + SmtExpr translateExprList(ExprList exprList, SmtEnv smtEnv) + { + switch (exprList.op) + { + case AND: + return translateExprListAndOr(SmtMultiArityExpr.Op.AND, exprList, smtEnv); + case OR: + return translateExprListAndOr(SmtMultiArityExpr.Op.OR, exprList, smtEnv); + case DISJOINT: + return translateExprListToDisjBinaryExpressions(SmtMultiArityExpr.Op.DISTINCT, exprList, smtEnv); + case TOTALORDER: + throw new UnsupportedOperationException();// total order should be handled before coming here + default: + throw new UnsupportedOperationException(); + } + } + + SmtExpr translateExprListToDisjBinaryExpressions(SmtMultiArityExpr.Op op, ExprList exprList, SmtEnv smtEnv) + { + List exprs = new ArrayList<>(); + + for (Expr e : exprList.args) + { + exprs.add(translateExpr(e, smtEnv)); + } + SmtExpr finalExpr; + List finalExprs = new ArrayList<>(); + + if (exprs.size() > 1) + { + for (int i = 0; i < exprs.size() - 1; ++i) + { + SmtExpr disjExpr = SmtBinaryExpr.Op.EQ.make(translator.atomNone.getVariable(), SmtBinaryExpr.Op.INTERSECTION.make(exprs.get(i), exprs.get(i + 1))); + finalExprs.add(disjExpr); + } + finalExpr = finalExprs.get(0); + for (int i = 1; i < finalExprs.size(); ++i) + { + finalExpr = SmtMultiArityExpr.Op.AND.make(finalExpr, finalExprs.get(i)); + } + } + else + { + finalExpr = exprs.get(0); + } + return finalExpr; + } + + private SmtExpr translateExprListAndOr(SmtMultiArityExpr.Op op, ExprList exprList, SmtEnv smtEnv) + { + if (op != SmtMultiArityExpr.Op.AND && op != SmtMultiArityExpr.Op.OR) + { + throw new UnsupportedOperationException(op.toString()); + } + + if (exprList.args.size() == 0) + { + if (op == SmtMultiArityExpr.Op.AND) + { + return BoolConstant.True; + } + + if (op == SmtMultiArityExpr.Op.OR) + { + return BoolConstant.False; + } + } + + List smtExprs = new ArrayList<>(); + + for (Expr expr : exprList.args) + { + SmtExpr smtExpr = translateExpr(expr, smtEnv); + smtExprs.add(smtExpr); + } + + return op.make(smtExprs); + } + + /** + * Auxiliary functions + */ + + List getBdVars(Sort sort, int num) + { + List bdVars = new ArrayList<>(); + + for (int i = 0; i < num; i++) + { + bdVars.add(new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false)); + } + return bdVars; + } + + List getBdTupleVars(List sorts, int arity, int num) + { + List elementSorts = new ArrayList<>(); + List bdVars = new ArrayList<>(); + + for (int i = 0; i < arity; i++) + { + elementSorts.add(sorts.get(i)); + } + for (int i = 0; i < num; i++) + { + Sort sort = new TupleSort(elementSorts); + bdVars.add(new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false)); + } + return bdVars; + } + + SmtExpr mkEmptyRelationOfSort(List sorts) + { + if (sorts.isEmpty()) + { + try + { + throw new Exception("Unexpected: sorts is empty!"); + } + catch (Exception ex) + { + Logger.getLogger(ExprTranslator.class.getName()).log(Level.SEVERE, null, ex); + } + } + return SmtUnaryExpr.Op.EMPTYSET.make(new SetSort(new TupleSort(sorts))); + } + + SmtExpr mkUnaryRelationOutOfAtomsOrTuples(List atomOrTupleExprs) + { + List atomTupleExprs = new ArrayList<>(); + + for (SmtExpr e : atomOrTupleExprs) + { + if (e instanceof Variable) + { + if (((Variable) e).getDeclaration().getSort() == translator.atomSort || + ((Variable) e).getDeclaration().getSort() == translator.uninterpretedInt) + { + SmtMultiArityExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, e); + atomTupleExprs.add(tuple); + } + else if (((Variable) e).getDeclaration().getSort() instanceof TupleSort) + { + atomTupleExprs.add(e); + } + else + { + throw new UnsupportedOperationException("Something is wrong here!"); + } + } + else + { + atomTupleExprs.add(e); + } + } + + + SmtUnaryExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(atomTupleExprs.get(0)); + + if (atomTupleExprs.size() > 1) + { + atomTupleExprs.remove(0); + atomTupleExprs.add(singleton); + SmtMultiArityExpr set = SmtMultiArityExpr.Op.INSERT.make(atomTupleExprs); + return set; + } + return singleton; + } + + public SmtExpr solveForVariable(Variable variable, SmtExpr expr, SmtExpr base) + { + if (expr.equals(variable)) + { + return base; + } + if (expr instanceof SmtBinaryExpr) + { + SmtBinaryExpr binaryExpr = (SmtBinaryExpr) expr; + switch (binaryExpr.getOp()) + { + case PRODUCT: + { + if (binaryExpr.getA().containsExpr(variable)) + { + SmtExpr nestedBase = SmtBinaryExpr.Op.JOIN.make(base, binaryExpr.getB()); + SmtExpr solution = solveForVariable(variable, binaryExpr.getA(), nestedBase); + return solution; + } + if (binaryExpr.getB().containsExpr(variable)) + { + SmtExpr nestedBase = SmtBinaryExpr.Op.JOIN.make(binaryExpr.getA(), base); + SmtExpr solution = solveForVariable(variable, binaryExpr.getB(), nestedBase); + return solution; + } + } + } + } + throw new UnsupportedOperationException(); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprUnaryTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprUnaryTranslator.java new file mode 100644 index 000000000..f6311b38a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprUnaryTranslator.java @@ -0,0 +1,285 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Sig; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +public class ExprUnaryTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + final ExprVarTranslator exprVarTranslator; + + public ExprUnaryTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.translator = exprTranslator.translator; + this.exprVarTranslator = exprTranslator.exprVarTranslator; + } + + SmtExpr translateExprUnary(ExprUnary exprUnary, SmtEnv smtEnv) + { + switch (exprUnary.op) + { + case NOOP: + return translateNoop(exprUnary, smtEnv); + case NO: + return translateNo(exprUnary, smtEnv); + case SOME: + return translateSome(exprUnary, smtEnv); + case ONE: + return translateOne(exprUnary, smtEnv); + case ONEOF: + return translateOneOf(exprUnary, smtEnv); + case LONEOF: + return translateLoneOf(exprUnary, smtEnv); + case SOMEOF: + return translateSomeOf(exprUnary, smtEnv); + case SETOF: + return exprTranslator.translateExpr(exprUnary.sub, smtEnv); + case LONE: + return translateLone(exprUnary, smtEnv); + case CARDINALITY: + throw new UnsupportedOperationException("CVC4 doesn't support cardinality operator with finite relations!"); + case TRANSPOSE: + return translateTranspose(exprUnary, smtEnv); + case CLOSURE: + return translateClosure(exprUnary, smtEnv); + case RCLOSURE: + return translateReflexiveClosure(exprUnary, smtEnv); + case NOT: + return translateNot(exprUnary, smtEnv); + case CAST2INT: + return translateCAST2INT(exprUnary, smtEnv); + case CAST2SIGINT: + return translateCAST2SIGINT(exprUnary, smtEnv); + default: + { + throw new UnsupportedOperationException("Not supported yet: " + exprUnary.op); + } + } + } + + private SmtExpr translateCAST2INT(ExprUnary exprUnary, SmtEnv smtEnv) + { + return exprTranslator.translateExpr(exprUnary.sub, smtEnv); + } + + private SmtExpr translateCAST2SIGINT(ExprUnary exprUnary, SmtEnv smtEnv) + { + return exprTranslator.translateExpr(exprUnary.sub, smtEnv); + } + + private SmtExpr translateNot(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtExpr smtExpr = exprTranslator.translateExpr(exprUnary.sub, smtEnv); + SmtExpr not = SmtUnaryExpr.Op.NOT.make(smtExpr); + return not; + } + + private SmtExpr translateClosure(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtExpr smtExpr = exprTranslator.translateExpr(exprUnary.sub, smtEnv); + SmtUnaryExpr closure = SmtUnaryExpr.Op.TCLOSURE.make(smtExpr); + return closure; + } + + private SmtExpr translateReflexiveClosure(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtExpr closure = translateClosure(exprUnary, smtEnv); + SmtBinaryExpr reflexiveClosure; + if (closure.getSort().equals(AbstractTranslator.setOfBinaryAtomSort)) + { + reflexiveClosure = SmtBinaryExpr.Op.UNION.make(closure, AbstractTranslator.idenAtom.getVariable()); + } + else + { + reflexiveClosure = SmtBinaryExpr.Op.UNION.make(closure, AbstractTranslator.idenInt.getVariable()); + } + return reflexiveClosure; + } + + private SmtExpr translateTranspose(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtExpr smtExpr = exprTranslator.translateExpr(exprUnary.sub, smtEnv); + SmtUnaryExpr transpose = SmtUnaryExpr.Op.TRANSPOSE.make(smtExpr); + return transpose; + } + + + private SmtExpr translateNoop(ExprUnary exprUnary, SmtEnv smtEnv) + { + if (exprUnary.sub instanceof Sig) + { + + // alloy built in signatures include: univ, none, iden + if (((Sig) exprUnary.sub).builtin) + { + switch (((Sig) exprUnary.sub).label) + { + case "univ": + return Alloy2SmtTranslator.univAtom.getVariable(); + case "iden": + return Alloy2SmtTranslator.idenAtom.getVariable(); + case "none": + return Alloy2SmtTranslator.atomNone.getVariable(); + case "Int": + return Alloy2SmtTranslator.univInt.getVariable(); + default: + throw new UnsupportedOperationException(); + } + } + else + { + return translator.signaturesMap.get(((Sig) exprUnary.sub)).getVariable(); + } + } + + if (exprUnary.sub instanceof Sig.Field) + { + return translator.fieldsMap.get(((Sig.Field) exprUnary.sub)).getVariable(); + } + + if (exprUnary.sub instanceof ExprVar) + { + return exprVarTranslator.translateExprVar((ExprVar) exprUnary.sub, smtEnv); + } + + return exprTranslator.translateExpr(exprUnary.sub, smtEnv); + } + + private SmtExpr translateNo(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + SmtExpr set = exprTranslator.translateExpr(exprUnary.sub, newSmtEnv); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(set.getSort()); + SmtExpr isEmpty = SmtBinaryExpr.Op.EQ.make(set, emptySet); + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(isEmpty, newSmtEnv); + return finalSmtExpr; + } + + private SmtExpr translateSome(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + SmtExpr set = exprTranslator.translateExpr(exprUnary.sub, newSmtEnv); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(set.getSort()); + SmtExpr equality = SmtBinaryExpr.Op.EQ.make(set, emptySet); + SmtExpr isNotEmpty = SmtUnaryExpr.Op.NOT.make(equality); + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(isNotEmpty, newSmtEnv); + return finalSmtExpr; + } + + private SmtExpr translateOne(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + SmtExpr set = exprTranslator.translateExpr(exprUnary.sub, newSmtEnv); + Sort sort = ((SetSort) set.getSort()).elementSort; + SmtVariable variable = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(variable.getVariable()); + SmtExpr isSingleton = SmtBinaryExpr.Op.EQ.make(set, singleton); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(isSingleton, variable); + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(exists, newSmtEnv); + return finalSmtExpr; + } + + private SmtExpr translateOneOf(ExprUnary expr, SmtEnv smtEnv) + { + // expression has pattern (one A) where type of A is (Set E) + // the translation returns the set (Singleton x) where x satisfies + // (exists ((x E)) (member x A)) + + SmtExpr A = exprTranslator.translateExpr(expr.sub, smtEnv); + SetSort setSort = (SetSort) A.getSort(); + Sort elementSort = setSort.elementSort; + + SmtVariable variable = new SmtVariable(TranslatorUtils.getFreshName(elementSort), elementSort, false); + + SmtExpr member = SmtBinaryExpr.Op.MEMBER.make(variable.getVariable(), A); + variable.setConstraint(member); + + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(variable.getVariable()); + + variable.setConstraint(member); + smtEnv.addAuxiliaryVariable(variable); + return singleton; + } + + private SmtExpr translateLoneOf(ExprUnary expr, SmtEnv smtEnv) + { + // expression has pattern (lone A) where type of A is (Set E) + // the translation returns a set which satisfies + // (exists ((S (Set E))) + // (and + // (subset S A) + // (exists ((x E)) (subset S (singleton x))) )) + + SmtExpr A = exprTranslator.translateExpr(expr.sub, smtEnv); + SetSort setSort = (SetSort) A.getSort(); + Sort elementSort = setSort.elementSort; + SmtVariable setVariable = new SmtVariable(TranslatorUtils.getFreshName(setSort), setSort, false); + SmtExpr subset1 = SmtBinaryExpr.Op.SUBSET.make(setVariable.getVariable(), A); + + SmtVariable variable = new SmtVariable(TranslatorUtils.getFreshName(elementSort), elementSort, false); + + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(variable.getVariable()); + + SmtExpr subset2 = SmtBinaryExpr.Op.SUBSET.make(setVariable.getVariable(), singleton); + + SmtQtExpr exists1 = SmtQtExpr.Op.EXISTS.make(subset2, variable); + SmtExpr andExpr = SmtMultiArityExpr.Op.AND.make(subset1, exists1); + setVariable.setConstraint(andExpr); + smtEnv.addAuxiliaryVariable(setVariable); + return setVariable.getVariable(); + } + + private SmtExpr translateSomeOf(ExprUnary expr, SmtEnv smtEnv) + { + // expression has pattern (some A) where type of A is (Set E) + // the translation returns a set which satisfies + // (exists ((S (Set E))) + // (and + // (subset S A) + // (not (= S (as emptyset (Set E)))) + + SmtExpr A = exprTranslator.translateExpr(expr.sub, smtEnv); + SetSort setSort = (SetSort) A.getSort(); + SmtVariable setVariable = new SmtVariable(TranslatorUtils.getFreshName(setSort), setSort, false); + SmtExpr subset = SmtBinaryExpr.Op.SUBSET.make(setVariable.getVariable(), A); + + SmtExpr emptyset = SmtUnaryExpr.Op.EMPTYSET.make(setSort); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(setVariable.getVariable(), emptyset); + SmtExpr notEmpty = SmtUnaryExpr.Op.NOT.make(equal); + SmtExpr andExpr = SmtMultiArityExpr.Op.AND.make(subset, notEmpty); + setVariable.setConstraint(andExpr); + smtEnv.addAuxiliaryVariable(setVariable); + return setVariable.getVariable(); + } + + private SmtExpr translateLone(ExprUnary exprUnary, SmtEnv smtEnv) + { + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + SmtExpr set = exprTranslator.translateExpr(exprUnary.sub, newSmtEnv); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(set.getSort()); + SmtExpr isEmpty = SmtBinaryExpr.Op.EQ.make(set, emptySet); + Sort sort = ((SetSort) set.getSort()).elementSort; + SmtVariable variable = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(variable.getVariable()); + SmtExpr isSingleton = SmtBinaryExpr.Op.EQ.make(set, singleton); + SmtExpr exists = SmtQtExpr.Op.EXISTS.make(isSingleton, variable); + SmtExpr or = SmtMultiArityExpr.Op.OR.make(isEmpty, exists); + SmtExpr finalSmtExpr = exprTranslator.addAuxiliaryVariables(or, newSmtEnv); + return finalSmtExpr; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprVarTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprVarTranslator.java new file mode 100644 index 000000000..8d31d107c --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/ExprVarTranslator.java @@ -0,0 +1,56 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.ExprVar; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.smtAst.SmtExpr; +import edu.uiowa.smt.smtAst.SmtMultiArityExpr; +import edu.uiowa.smt.smtAst.SmtUnaryExpr; +import edu.uiowa.smt.smtAst.TupleSort; + +public class ExprVarTranslator +{ + final ExprTranslator exprTranslator; + final Alloy2SmtTranslator translator; + + public ExprVarTranslator(ExprTranslator exprTranslator) + { + this.exprTranslator = exprTranslator; + this.translator = exprTranslator.translator; + } + + SmtExpr translateExprVar(ExprVar exprVar, SmtEnv smtEnv) + { + String name = exprVar.label; + + if (smtEnv.containsKey(name)) + { + SmtExpr variable = smtEnv.get(name); + + if (variable.getSort() == AbstractTranslator.atomSort) + { + return SmtUnaryExpr.Op.SINGLETON.make(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, variable)); + } + else if (variable.getSort() == AbstractTranslator.intSort) + { + return SmtUnaryExpr.Op.SINGLETON.make(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, variable)); + } + else if (variable.getSort() instanceof TupleSort) + { + return SmtUnaryExpr.Op.SINGLETON.make(variable); + } + + return variable; + } + else + { + //ToDo: review the semantics of "this" keyword +// if(exprVar.toString().equals("this")) +// { +// Sig sig = exprVar.type().fold().get(0).get(0); +// return translator.signaturesMap.get(sig).getVariable(); +// } + throw new RuntimeException(String.format(" Could not find name %s in the environment", name)); + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/FieldTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/FieldTranslator.java new file mode 100644 index 000000000..acf9c4cfd --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/FieldTranslator.java @@ -0,0 +1,210 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.*; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.smtAst.*; + +import java.util.*; + +public class FieldTranslator +{ + + private final Alloy2SmtTranslator translator; + + public FieldTranslator(Alloy2SmtTranslator translator) + { + this.translator = translator; + } + + void translateFields() + { + for (Sig sig : translator.reachableSigs) + { + List fields = sig.getFields().makeCopy(); + + for (Sig.Field f : fields) + { + translate(f); + } + + translateDisjointFields(sig, fields); + + translateDisjoint2FieldValues(sig, fields); + } + } + + private void translateDisjointFields(Sig sig, List fields) + { + if (fields.size() == 0) + { + return; + } + + // translate disjoint fields + for (Decl decl : sig.getFieldDecls()) + { + // disjoint fields + if (decl.disjoint != null && decl.names.size() > 1) + { + for (int i = 0; i < decl.names.size() - 1; i++) + { + SmtExpr fieldI = getFieldExpression(fields, decl.names.get(i).label); + for (int j = i + 1; j < decl.names.size(); j++) + { + SmtExpr fieldJ = getFieldExpression(fields, decl.names.get(j).label); + SmtExpr intersect = SmtBinaryExpr.Op.INTERSECTION.make(fieldI, fieldJ); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(fieldI.getSort()); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(intersect, emptySet); + List positions = Arrays.asList(decl.names.get(i).pos, decl.names.get(j).pos); + Assertion disjoint = AlloyUtils.getAssertion(positions, + String.format("disj %1$s, %2$s", decl.names.get(i), decl.names.get(j)), equal); + translator.smtScript.addAssertion(disjoint); + } + } + } + } + } + + private void translateDisjoint2FieldValues(Sig sig, List fields) + { + if (fields.size() == 0) + { + return; + } + + // translate disjoint field values + + // sig S {f: disj e} + // all a, b: S | a != b implies no a.f & b.f + + SmtExpr signature = translator.signaturesMap.get(sig).getVariable(); + SetSort setSort = (SetSort) signature.getSort(); + SmtVariable a = new SmtVariable("a", setSort.elementSort, false); + SmtVariable b = new SmtVariable("b", setSort.elementSort, false); + SmtExpr aMember = SmtBinaryExpr.Op.MEMBER.make(a.getVariable(), signature); + SmtExpr bMember = SmtBinaryExpr.Op.MEMBER.make(b.getVariable(), signature); + SmtExpr aSingleton = SmtUnaryExpr.Op.SINGLETON.make(a.getVariable()); + SmtExpr bSingleton = SmtUnaryExpr.Op.SINGLETON.make(b.getVariable()); + + SmtExpr members = SmtMultiArityExpr.Op.AND.make(aMember, bMember); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(a.getVariable(), b.getVariable()); + SmtExpr notEqual = SmtUnaryExpr.Op.NOT.make(equal); + SmtExpr antecedent = SmtMultiArityExpr.Op.AND.make(members, notEqual); + SmtExpr consequent = BoolConstant.True; + + //ToDo: refactor for unsat core + List positions = new ArrayList<>(); + for (Decl decl : sig.getFieldDecls()) + { + if (decl.disjoint2 != null) + { + for (ExprHasName name : decl.names) + { + SmtExpr field = getFieldExpression(fields, name.label); + SmtExpr aJoin = SmtBinaryExpr.Op.JOIN.make(aSingleton, field); + SmtExpr bJoin = SmtBinaryExpr.Op.JOIN.make(bSingleton, field); + SmtExpr intersect = SmtBinaryExpr.Op.INTERSECTION.make(aJoin, bJoin); + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(intersect.getSort()); + SmtExpr isEmpty = SmtBinaryExpr.Op.EQ.make(intersect, emptySet); + consequent = SmtMultiArityExpr.Op.AND.make(consequent, isEmpty); + positions.add(name.pos); + } + } + } + + if (!consequent.equals(BoolConstant.True)) + { + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(antecedent, consequent); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, a, b); + + Assertion disjoint2 = AlloyUtils.getAssertion(positions, sig.label + " disjoint2", forAll); + translator.smtScript.addAssertion(disjoint2); + } + } + + private SmtExpr getFieldExpression(List fields, String label) + { + Optional field = fields.stream() + .filter(f -> f.label.equals(label)) + .findFirst(); + if (!field.isPresent()) + { + throw new RuntimeException("Can not find field " + label); + } + SmtExpr smtExpr = translator.fieldsMap.get(field.get()).getVariable(); + return smtExpr; + } + + void translate(Sig.Field field) + { + + String fieldName = field.sig.label + "/" + field.label; + + if (fieldName.equals("integer/univInt/idenInt")) + { + translator.fieldsMap.put(field, AbstractTranslator.idenInt); + return; + } + + List fieldSorts = new ArrayList<>(); + + for (Sig sig : field.type().fold().get(0)) + { + if (sig.type().is_int()) + { + fieldSorts.add(AbstractTranslator.uninterpretedInt); + } + else + { + fieldSorts.add(AbstractTranslator.atomSort); + } + } + + Sort sort = new SetSort(new TupleSort(fieldSorts)); + FunctionDeclaration fieldDeclaration = new FunctionDeclaration(fieldName, sort, true); + // declare a variable for the field + translator.smtScript.addFunction(fieldDeclaration); + translator.fieldsMap.put(field, fieldDeclaration); + translateMultiplicities(field); + } + + private void translateMultiplicities(Sig.Field field) + { + Expr expr = field.decl().expr; + // Sig A {field: expr} + // all this: A | let $s$ = this.field | $s$ in expr + // field in (A -> removeMultiplicity[expr]) because A is not a type in SMT + ExprVar zis = ExprVar.make(null, "this", field.sig.type()); + Expr zisJoinField = ExprBinary.Op.JOIN.make(null, null, zis, field); + ExprVar s = ExprVar.make(null, "$s$", zisJoinField.type()); + Expr in = ExprBinary.Op.IN.make(null, null, s, expr); + Expr exprLet = ExprLet.make(null, s, zisJoinField, in); + + Expr oneOfSig = ExprUnary.Op.ONEOF.make(null, field.sig); + Decl decl = new Decl(null, null, null, null, Collections.singletonList(zis), oneOfSig); + Expr all = ExprQt.Op.ALL.make(null, null, Collections.singletonList(decl), exprLet); + + SmtEnv smtEnv = new SmtEnv(); + SmtExpr multiplicity = translator.exprTranslator.translateExpr(all, smtEnv); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(field.pos), field.toString() + " multiplicity", multiplicity); + translator.smtScript.addAssertion(assertion); + + Expr noMultiplicity = AlloyUtils.removeMultiplicity(field.decl()); + Expr substituteExpr = AlloyUtils.substituteExpr(noMultiplicity, zis, field.sig); + + Expr product = ExprBinary.Op.ARROW.make(null, null, field.sig, substituteExpr); + Expr subsetExpr = ExprBinary.Op.IN.make(null, null, field, product); + translator.exprTranslator.translateFormula(field.toString() + " subset", subsetExpr); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/SignatureTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/SignatureTranslator.java new file mode 100644 index 000000000..46d13f792 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/SignatureTranslator.java @@ -0,0 +1,750 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.SafeList; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprList; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.Sig; +import edu.uiowa.alloy2smt.utils.AlloyUtils; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +public class SignatureTranslator +{ + + private final Alloy2SmtTranslator translator; + private final FieldTranslator fieldTranslator; + + private List> translatedSigFacts = new ArrayList<>(); + + public SignatureTranslator(Alloy2SmtTranslator translator) + { + this.translator = translator; + this.fieldTranslator = new FieldTranslator(translator); + } + + private void translateSignatureHierarchies() + { + for (Sig sig : translator.reachableSigs) + { + if (sig instanceof Sig.PrimSig) + { + Sig.PrimSig primSig = (Sig.PrimSig) sig; + + if (primSig.isAbstract != null) + { + SafeList children = primSig.children(); + if (children.size() > 0) + { + SmtExpr left = translator.signaturesMap.get(sig).getVariable(); + SmtExpr union = translator.signaturesMap.get(children.get(0)).getVariable(); + + for (int i = 1; i < children.size(); i++) + { + SmtExpr smtExpr = translator.signaturesMap.get(children.get(i)).getVariable(); + union = SmtBinaryExpr.Op.UNION.make(union, smtExpr); + } + + SmtBinaryExpr equality = SmtBinaryExpr.Op.EQ.make(left, union); + List positions = children.makeCopy().stream() + .map(s -> s.pos).collect(Collectors.toList()); + Assertion isAbstract = AlloyUtils.getAssertion(positions, "abstract " + primSig.toString(), equality); + translator.smtScript.addAssertion(isAbstract); + } + } + } + } + + if (translator.topLevelSigs.size() > 0) + { + // The union of all top-level sigs equals to the universe + SmtExpr unionTopSigExprs = translator.signaturesMap.get(translator.topLevelSigs.get(0)).getVariable(); + + for (int i = 1; i < translator.topLevelSigs.size(); ++i) + { + unionTopSigExprs = SmtBinaryExpr.Op.UNION.make(unionTopSigExprs, translator.signaturesMap.get(translator.topLevelSigs.get(i)).getVariable()); + } + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(unionTopSigExprs, translator.univAtom.getVariable()); + List positions = translator.topLevelSigs.stream().map(s -> s.pos).collect(Collectors.toList()); + Assertion assertion = AlloyUtils.getAssertion(positions, "atomUniv is the union of top level signatures", equal); + translator.smtScript.addAssertion(assertion); + + // Top-level sigs are mutually disjoint + if (translator.topLevelSigs.size() > 1) + { + for (int i = 0; i < translator.topLevelSigs.size() - 1; ++i) + { + SmtExpr fstSigExpr = translator.signaturesMap.get(translator.topLevelSigs.get(i)).getVariable(); + + for (int j = i + 1; j < translator.topLevelSigs.size(); ++j) + { + SmtExpr sndSigExpr = translator.signaturesMap.get(translator.topLevelSigs.get(j)).getVariable(); + SmtExpr intersect = SmtBinaryExpr.Op.INTERSECTION.make(fstSigExpr, sndSigExpr); + SmtExpr disjoint = SmtBinaryExpr.Op.EQ.make(intersect, AbstractTranslator.atomNone.getVariable()); + assertion = AlloyUtils.getAssertion(positions, + "Top level signatures are disjoint", disjoint); + translator.smtScript.addAssertion(assertion); + } + } + } + + } + } + + private void translateDisjointSignatures(List signatures) + { + for (int i = 0; i < signatures.size(); i++) + { + Sig signature = signatures.get(i); + SmtExpr left = translator.signaturesMap.get(signature).getVariable(); + + for (int j = i + 1; j < signatures.size(); j++) + { + SmtExpr right = translator.signaturesMap.get(signatures.get(j)).getVariable(); + SmtBinaryExpr disjoint = SmtBinaryExpr.Op.INTERSECTION.make(left, right); + SmtBinaryExpr equality = SmtBinaryExpr.Op.EQ.make(disjoint, translator.atomNone.getVariable()); + + List positions = Arrays.asList(signature.pos, signatures.get(j).pos); + Assertion assertion = AlloyUtils.getAssertion(positions, "Disjoint signatures", equality); + translator.smtScript.addAssertion(assertion); + } + // recursively add disjoint constraints to children + if (signature instanceof Sig.PrimSig) + { + Sig.PrimSig primSig = (Sig.PrimSig) signature; + List children = primSig.children().makeCopy() + .stream().collect(Collectors.toList()); + translateDisjointSignatures(children); + } + } + } + + private void collectReachableSigs() + { + for (Sig sig : translator.alloyModel.getAllReachableSigs()) + { + if (sig.builtin) + { + continue; + } + if (sig.isTopLevel()) + { + translator.topLevelSigs.add(sig); + } + translator.reachableSigs.add(sig); + } + } + + private void translateSignatures() + { + for (Sig sig : translator.reachableSigs) + { + if (sig.type().is_int()) + { + FunctionDeclaration functionDeclaration = declareUnaryIntFunction(sig.toString(), true); + translator.signaturesMap.put(sig, functionDeclaration); + } + else + { + FunctionDeclaration functionDeclaration = declareUnaryAtomFunction(sig.toString(), true); + translator.signaturesMap.put(sig, functionDeclaration); + } + } + + for (Sig sig : translator.reachableSigs) + { + FunctionDeclaration functionDeclaration = translator.signaturesMap.get(sig); + + // if sig extends another signature + if (!sig.isTopLevel()) + { + translateSigSubsetParent(sig, functionDeclaration); + } + + if (sig.isOne != null) + { + translateSignatureOneMultiplicity(sig); + } + else if (sig.isLone != null) + { + translateSignatureLoneMultiplicity(sig); + } + else if (sig.isSome != null) + { + translateSignatureSomeMultiplicity(sig); + } + + for (Expr expr : sig.getFacts()) + { + translator.sigFacts.put(sig, expr); + } + } + + List primSigs = translator.topLevelSigs + .stream().map(s -> (Sig.PrimSig) s).collect(Collectors.toList()); + translateDisjointSignatures(primSigs); + } + + private void translateSignatureOneMultiplicity(Sig sig) + { + SmtExpr expr; + FunctionDeclaration constDecl; + Boolean isInt = sig.type().is_int(); + + FunctionDeclaration signature = translator.signaturesMap.get(sig); + + if (isInt) + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.uninterpretedInt); + constDecl = new FunctionDeclaration(name, AbstractTranslator.uninterpretedInt, false); + } + else + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.atomSort); + constDecl = new FunctionDeclaration(name, AbstractTranslator.atomSort, false); + } + expr = AlloyUtils.mkSingletonOutOfTuple(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, constDecl.getVariable())); + translator.smtScript.addFunction(constDecl); + + SmtBinaryExpr subset = SmtBinaryExpr.Op.EQ.make(signature.getVariable(), expr); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), "one " + sig.label, subset); + translator.smtScript.addAssertion(assertion); + } + + private void translateSignatureLoneMultiplicity(Sig sig) + { + SmtExpr expr; + FunctionDeclaration constDecl; + Boolean isInt = sig.type().is_int(); + FunctionDeclaration signature = translator.signaturesMap.get(sig); + + if (isInt) + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.uninterpretedInt); + constDecl = new FunctionDeclaration(name, AbstractTranslator.uninterpretedInt, false); + expr = AlloyUtils.mkSingletonOutOfTuple(new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, constDecl.getVariable())); + } + else + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.atomSort); + constDecl = new FunctionDeclaration(name, AbstractTranslator.atomSort, false); + expr = AlloyUtils.mkSingletonOutOfTuple(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, constDecl.getVariable())); + } + translator.smtScript.addFunction(constDecl); + + SmtBinaryExpr subset = SmtBinaryExpr.Op.SUBSET.make(signature.getVariable(), expr); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), "lone " + sig.label, subset); + translator.smtScript.addAssertion(assertion); + } + + private void translateSignatureSomeMultiplicity(Sig sig) + { + SmtExpr expr; + FunctionDeclaration constDecl; + Boolean isInt = sig.type().is_int(); + FunctionDeclaration signature = translator.signaturesMap.get(sig); + + if (isInt) + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.uninterpretedInt); + constDecl = new FunctionDeclaration(name, AbstractTranslator.uninterpretedInt, false); + expr = AlloyUtils.mkSingletonOutOfTuple(new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, constDecl.getVariable())); + } + else + { + String name = TranslatorUtils.getFreshName(AbstractTranslator.atomSort); + constDecl = new FunctionDeclaration(name, AbstractTranslator.atomSort, false); + expr = AlloyUtils.mkSingletonOutOfTuple(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, constDecl.getVariable())); + } + translator.smtScript.addFunction(constDecl); + + SmtBinaryExpr subset = SmtBinaryExpr.Op.SUBSET.make(expr, signature.getVariable()); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), "some " + sig.label, subset); + translator.smtScript.addAssertion(assertion); + } + + + private void translateSigSubsetParent(Sig sig, FunctionDeclaration functionDeclaration) + { + if (sig instanceof Sig.PrimSig) + { + Sig parent = ((Sig.PrimSig) sig).parent; + FunctionDeclaration parentDeclaration = translator.signaturesMap.get(parent); + SmtBinaryExpr subsetExpression = SmtBinaryExpr.Op.SUBSET.make(functionDeclaration.getVariable(), parentDeclaration.getVariable()); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), + sig.label + " in " + parent.label, subsetExpression); + translator.smtScript.addAssertion(assertion); + } + else + { + List parents = ((Sig.SubsetSig) sig).parents; + + if (parents.size() == 1) + { + Sig parentSig = parents.get(0); + + // We consider parentSig as int +// if(parentSig == Sig.SIGINT && !translator.signaturesMap.containsKey(parentSig)) +// { +// declareIntSig(); +// } + if (parentSig != Sig.SIGINT) + { + FunctionDeclaration parentDeclaration = translator.signaturesMap.get(parentSig); + SmtBinaryExpr subset = SmtBinaryExpr.Op.SUBSET.make(functionDeclaration.getVariable(), parentDeclaration.getVariable()); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), + sig.label + " in " + parentSig.label, subset); + translator.smtScript.addAssertion(assertion); + } + } + else + { + SmtExpr left = translator.signaturesMap.get(parents.get(0)).getVariable(); + SmtExpr right = translator.signaturesMap.get(parents.get(1)).getVariable(); + SmtBinaryExpr union = SmtBinaryExpr.Op.UNION.make(left, right); + + for (int i = 2; i < parents.size(); i++) + { + SmtExpr smtExpr = translator.signaturesMap.get(parents.get(i)).getVariable(); + union = SmtBinaryExpr.Op.UNION.make(union, smtExpr); + } + + SmtBinaryExpr subset = SmtBinaryExpr.Op.SUBSET.make(functionDeclaration.getVariable(), union); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sig.pos), + sig.toString(), subset); + translator.smtScript.addAssertion(assertion); + } + } + } + + private FunctionDeclaration declareUnaryAtomFunction(String varName, boolean isOriginal) + { + FunctionDeclaration declaration = null; + if (varName != null) + { + declaration = new FunctionDeclaration(varName, translator.setOfUnaryAtomSort, isOriginal); + translator.smtScript.addFunction(declaration); + } + return declaration; + } + + private FunctionDeclaration declareUnaryIntFunction(String varName, boolean isOriginal) + { + FunctionDeclaration declaration = null; + if (varName != null) + { + declaration = new FunctionDeclaration(varName, translator.setOfUninterpretedIntTuple, isOriginal); + translator.smtScript.addFunction(declaration); + } + return declaration; + } + + public void translateSigs() + { + collectReachableSigs(); + translateSignatures(); + translateSignatureHierarchies(); + this.fieldTranslator.translateFields(); + } + + void translateSpecialSigFacts() + { + // Translate facts on signatures + for (Map.Entry sigFact : translator.sigFacts.entrySet()) + { + SmtEnv smtEnv = new SmtEnv(); + Expr expr = sigFact.getValue(); + + // handle total order operator differently + if (expr instanceof ExprUnary && + ((ExprUnary) expr).sub instanceof ExprList && + ((ExprList) ((ExprUnary) expr).sub).op == ExprList.Op.TOTALORDER) + { + translateTotalOrder(sigFact.getKey(), ((ExprList) ((ExprUnary) expr).sub), smtEnv); + this.translatedSigFacts.add(sigFact); + } + } + } + + + void translateSigFacts() + { + // Translate facts on signatures + for (Map.Entry sigFact : translator.sigFacts.entrySet()) + { + // ignore already translated signature facts + if (this.translatedSigFacts.contains(sigFact)) + { + continue; + } + + String name = "this"; + Map boundVariables = new HashMap<>(); + SmtVariable declaration = new SmtVariable(name, AbstractTranslator.atomSort, true); + boundVariables.put(declaration, translator.signaturesMap.get(sigFact.getKey()).getVariable()); + SmtExpr member = AlloyUtils.getMemberExpression(boundVariables, 0); + declaration.setConstraint(member); + SmtEnv smtEnv = new SmtEnv(); + smtEnv.put(name, declaration.getVariable()); + + SmtExpr bodyExpr = translator.exprTranslator.translateExpr(sigFact.getValue(), smtEnv); + + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(member, bodyExpr); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, new ArrayList<>(boundVariables.keySet())); + Assertion assertion = AlloyUtils.getAssertion(Collections.singletonList(sigFact.getValue().pos), + "Signature fact '" + sigFact.getValue().toString() + "' for sig " + sigFact.getKey(), forAll); + translator.smtScript.addAssertion(assertion); + } + } + + private void translateTotalOrder(Sig ordSig, ExprList exprList, SmtEnv smtEnv) + { + if (exprList.args.size() != 3) + { + throw new UnsupportedOperationException(); + } + + Expr set = exprList.args.get(0); + Expr first = exprList.args.get(1); + + // define a new uninterpreted one-to-one mapping from the signature to integers + String label = ordSig.label; + // convert ordA/Ord to ordA_ + String prefix = label.replaceFirst("/Ord", "/"); + String mappingName = prefix + "IntMapping"; + + FunctionDeclaration mapping = defineInjectiveMapping(mappingName, AbstractTranslator.atomSort, translator.intSort); + + SmtExpr setSmtExpr = translator.exprTranslator.translateExpr(set, smtEnv); + SmtExpr firstSmtExpr = translator.exprTranslator.translateExpr(first, smtEnv); + + // ordering/first + SmtExpr firstSet = defineFirstElement(prefix, firstSmtExpr, mapping, setSmtExpr); + + // ordering/last + FunctionDeclaration lastAtom = defineLastElement(prefix, mapping, setSmtExpr); + + // Next relation + FunctionDeclaration ordNext = addOrdNext(prefix, setSmtExpr, mapping, ordSig, firstSet, lastAtom); + + // prev relation + FunctionDeclaration ordPrev = addOrdPrev(prefix, ordNext); + + SmtVariable set1 = new SmtVariable("s1", translator.setOfUnaryAtomSort, false); + SmtVariable set2 = new SmtVariable("s2", translator.setOfUnaryAtomSort, false); + + SmtVariable element1 = new SmtVariable("e1", AbstractTranslator.atomSort, false); + SmtVariable element2 = new SmtVariable("e2", AbstractTranslator.atomSort, false); + + // ordering/prevs + FunctionDefinition prevs = getPrevsNextsDefinition(prefix, set1, ordPrev, "prevs"); + translator.addFunction(prevs); + + // ordering/nexts + FunctionDefinition nexts = getPrevsNextsDefinition(prefix, set1, ordNext, "nexts"); + translator.addFunction(nexts); + + // ordering/lt + FunctionDefinition lt = getComparisonDefinition(prefix, "lt", mapping, set1, set2, element1, element2, SmtBinaryExpr.Op.LT); + translator.addFunction(lt); + + // ordering/gt + FunctionDefinition gt = getComparisonDefinition(prefix, "gt", mapping, set1, set2, element1, element2, SmtBinaryExpr.Op.GT); + translator.addFunction(gt); + + // ordering/lte + FunctionDefinition lte = getComparisonDefinition(prefix, "lte", mapping, set1, set2, element1, element2, SmtBinaryExpr.Op.LTE); + translator.addFunction(lte); + + // ordering/gte + FunctionDefinition gte = getComparisonDefinition(prefix, "gte", mapping, set1, set2, element1, element2, SmtBinaryExpr.Op.GTE); + translator.addFunction(gte); + + //ordering/larger + FunctionDefinition larger = getLargerSmallerDefinition(prefix, "larger", set1, set2, gt); + translator.addFunction(larger); + + //ordering/smaller + FunctionDefinition smaller = getLargerSmallerDefinition(prefix, "smaller", set1, set2, lt); + translator.addFunction(smaller); + + //ordering/max + FunctionDefinition max = getMaxMinDefinition(prefix, "max", set1, ordPrev); + translator.addFunction(max); + + //ordering/min + FunctionDefinition min = getMaxMinDefinition(prefix, "min", set1, ordNext); + translator.addFunction(min); + } + + private FunctionDeclaration defineInjectiveMapping(String mappingName, Sort inputSort, Sort outputSort) + { + FunctionDeclaration mapping = new FunctionDeclaration(mappingName, inputSort, outputSort, true); + translator.addFunction(mapping); + + // the mapping is one-to-one(injective) + // for all x, y (x != y and implies f(x) != f(y)) + SmtVariable x = new SmtVariable("x", AbstractTranslator.atomSort, false); + SmtVariable y = new SmtVariable("y", AbstractTranslator.atomSort, false); + + SmtExpr xEqualsY = SmtBinaryExpr.Op.EQ.make(x.getVariable(), y.getVariable()); + + SmtExpr notXEqualsY = SmtUnaryExpr.Op.NOT.make(xEqualsY); + + SmtExpr mappingXEqualsMappingY = SmtBinaryExpr.Op.EQ.make(new SmtCallExpr(mapping, x.getVariable()), new SmtCallExpr(mapping, y.getVariable())); + + SmtExpr not = SmtUnaryExpr.Op.NOT.make(mappingXEqualsMappingY); + + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(notXEqualsY, not); + + SmtQtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, x, y); + + translator.smtScript.addAssertion(new Assertion("", mappingName + " is injective", forAll)); + + return mapping; + } + + private SmtExpr defineFirstElement(String prefix, SmtExpr firstSmtExpr, FunctionDeclaration mapping, SmtExpr setSmtExpr) + { + final String suffix = "first"; + FunctionDeclaration firstAtom = new FunctionDeclaration(prefix + "FirstAtom", AbstractTranslator.atomSort, true); + FunctionDeclaration first = new FunctionDeclaration(prefix + suffix, AbstractTranslator.setOfUnaryAtomSort, true); + + SmtExpr firstSet = SmtUnaryExpr.Op.SINGLETON.make( + new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, firstAtom.getVariable())); + + translator.smtScript.addFunction(firstAtom); + translator.addFunction(first); + + // there is only one first element + // ordering/first = (singleton (mktuple firstAtom)) + SmtExpr firstSingleton = SmtBinaryExpr.Op.EQ.make(first.getVariable(), firstSet); + translator.smtScript.addAssertion(new Assertion("", prefix + suffix + " = (singleton (mktuple firstAtom))", firstSingleton)); + + // ordering/first = ordering/Ord.First + SmtExpr ordFirstSingleton = SmtBinaryExpr.Op.EQ.make(first.getVariable(), firstSmtExpr); + translator.smtScript.addAssertion(new Assertion("", prefix + suffix + " = " + prefix + "Ord.First", ordFirstSingleton)); + + // each element is greater than or equal to the first element + SmtVariable x = new SmtVariable("x", AbstractTranslator.atomSort, false); + SmtExpr member = SmtBinaryExpr.Op.MEMBER.make(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, x.getVariable()), setSmtExpr); + SmtExpr gte = SmtBinaryExpr.Op.GTE.make(new SmtCallExpr(mapping, x.getVariable()), new SmtCallExpr(mapping, firstAtom.getVariable())); + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(member, gte); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, x); + translator.smtScript.addAssertion(new Assertion("", + "each element is greater than or equal to the first element", forAll)); + + return firstSet; + } + + private FunctionDeclaration defineLastElement(String prefix, FunctionDeclaration mapping, SmtExpr setSmtExpr) + { + final String suffix = "last"; + FunctionDeclaration lastAtom = new FunctionDeclaration(prefix + "LastAtom", AbstractTranslator.atomSort, true); + FunctionDeclaration last = new FunctionDeclaration(prefix + suffix, translator.setOfUnaryAtomSort, true); + + SmtExpr lastSet = SmtUnaryExpr.Op.SINGLETON.make( + new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, lastAtom.getVariable())); + + translator.smtScript.addFunction(lastAtom); + translator.addFunction(last); + + + // last element is a member of the set + SmtExpr lastMember = SmtBinaryExpr.Op.MEMBER.make(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, lastAtom.getVariable()), setSmtExpr); + translator.smtScript.addAssertion(new Assertion("", "last element is a member", lastMember)); + + // there is only one last element + // ordering/last = (singleton (mktuple lastAtom)) + SmtExpr lastSingleton = SmtBinaryExpr.Op.EQ.make(last.getVariable(), lastSet); + translator.smtScript.addAssertion(new Assertion("", prefix + suffix + " = (singleton (mktuple lastAtom))", lastSingleton)); + + // each element is less than or equal to the last element + SmtVariable x = new SmtVariable("x", AbstractTranslator.atomSort, false); + SmtExpr xMember = SmtBinaryExpr.Op.MEMBER.make(new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, x.getVariable()), setSmtExpr); + SmtExpr lte = SmtBinaryExpr.Op.LTE.make(new SmtCallExpr(mapping, x.getVariable()), new SmtCallExpr(mapping, lastAtom.getVariable())); + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(xMember, lte); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, x); + translator.smtScript.addAssertion(new Assertion("", + "each element is less than or equal to the last element", forAll)); + + return lastAtom; + } + + private FunctionDefinition getMaxMinDefinition(String prefix, String suffix, SmtVariable set, FunctionDeclaration declaration) + { + SmtExpr tClosure = SmtUnaryExpr.Op.TCLOSURE.make(declaration.getVariable()); + + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(set.getVariable(), tClosure); + + SmtExpr difference = SmtBinaryExpr.Op.SETMINUS.make(set.getVariable(), join); + + return new FunctionDefinition(prefix + suffix, translator.setOfUnaryAtomSort, + difference, true, set); + } + + private FunctionDefinition getPrevsNextsDefinition(String prefix, SmtVariable set1, FunctionDeclaration ord, String suffix) + { + SmtUnaryExpr tClosure = SmtUnaryExpr.Op.TCLOSURE.make(ord.getVariable()); + SmtBinaryExpr join = SmtBinaryExpr.Op.JOIN.make(set1.getVariable(), tClosure); + String name = prefix + suffix; + FunctionDefinition definition = new FunctionDefinition(name, translator.setOfUnaryAtomSort, join, true, set1); + return definition; + } + + private FunctionDefinition getLargerSmallerDefinition(String prefix, String suffix, SmtVariable set1, SmtVariable set2, FunctionDefinition definition) + { + SmtCallExpr call = new SmtCallExpr(definition, set1.getVariable(), set2.getVariable()); + SmtIteExpr ite = new SmtIteExpr(call, set1.getVariable(), + set2.getVariable()); + return new FunctionDefinition(prefix + suffix, + translator.setOfUnaryAtomSort, + ite, true, + set1, set2 + ); + } + + private FunctionDeclaration addOrdNext(String prefix, SmtExpr setSmtExpr, FunctionDeclaration intMapping, Sig ordSig, SmtExpr firstSet, FunctionDeclaration lastAtom) + { + String nextMapping = prefix + "nextMapping"; + + FunctionDeclaration mapping = new FunctionDeclaration(nextMapping, AbstractTranslator.atomSort, AbstractTranslator.atomSort, true); + translator.addFunction(mapping); + + SmtVariable x = new SmtVariable("x", AbstractTranslator.atomSort, false); + SmtVariable y = new SmtVariable("y", AbstractTranslator.atomSort, false); + + // for all x : x is a member implies intMapping(x) < intMapping (nextMapping(x)) and + // x != lastAtom implies nextMapping(x) is a member + + SmtBinaryExpr xMember = SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(x), setSmtExpr); + SmtBinaryExpr xLessThanNext = SmtBinaryExpr.Op.LT.make(new SmtCallExpr(intMapping, x.getVariable()), new SmtCallExpr(intMapping, + new SmtCallExpr(mapping, x.getVariable()))); + + SmtExpr notXEqualsLast = SmtUnaryExpr.Op.NOT.make( + SmtBinaryExpr.Op.EQ.make(x.getVariable(), lastAtom.getVariable())); + SmtExpr nextIsMember = SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(new SmtCallExpr(mapping, x.getVariable())), setSmtExpr); + + SmtExpr impliesNextIsMember = SmtBinaryExpr.Op.IMPLIES.make(notXEqualsLast, nextIsMember); + + SmtExpr xMemberconsequent = SmtMultiArityExpr.Op.AND.make(xLessThanNext, impliesNextIsMember); + + SmtExpr xMemberImplies = SmtBinaryExpr.Op.IMPLIES.make(xMember, xMemberconsequent); + + SmtExpr forAllX = SmtQtExpr.Op.FORALL.make(xMemberImplies, x); + translator.smtScript.addAssertion( + new Assertion("", "For all x : x is a member implies (intMapping(x) < intMapping (nextMapping(x)) and " + + "(x != lastAtom implies nextMapping(x) is a member))", forAllX)); + + // the next mapping is one-to-one (injective) members + // for all x, y (x != y and x, y members) implies (nextMapping(x) != nextMapping(y))) + SmtExpr xEqualsY = SmtBinaryExpr.Op.EQ.make(x.getVariable(), y.getVariable()); + SmtExpr notXEqualsY = SmtUnaryExpr.Op.NOT.make(xEqualsY); + + SmtExpr xyMembers = SmtMultiArityExpr.Op.AND.make(SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(x), setSmtExpr), SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(y), setSmtExpr)); + + SmtExpr antecedent = SmtMultiArityExpr.Op.AND.make(notXEqualsY, xyMembers); + + SmtExpr mappingXEqualsMappingY = SmtBinaryExpr.Op.EQ.make(new SmtCallExpr(mapping, x.getVariable()), new SmtCallExpr(mapping, y.getVariable())); + + SmtExpr consequent = SmtUnaryExpr.Op.NOT.make(mappingXEqualsMappingY); + + SmtExpr implies = SmtBinaryExpr.Op.IMPLIES.make(antecedent, consequent); + + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implies, x, y); + + translator.smtScript.addAssertion(new Assertion("", nextMapping + " is injective for members", forAll)); + + FunctionDeclaration ordNext = new FunctionDeclaration(prefix + "next", translator.setOfBinaryAtomSort, true); + translator.addFunction(ordNext); + + // for all x, y (x,y) in the next relation iff x, y are members and nextMapping(x) = y + SmtExpr xy = TranslatorUtils.getTuple(x, y); + SmtExpr xyInNext = SmtBinaryExpr.Op.MEMBER.make(xy, ordNext.getVariable()); + + SmtExpr xLessThanY = SmtBinaryExpr.Op.LT.make(new SmtCallExpr(intMapping, x.getVariable()), new SmtCallExpr(intMapping, y.getVariable())); + + SmtExpr nextXEqualsY = SmtBinaryExpr.Op.EQ.make(new SmtCallExpr(mapping, x.getVariable()), y.getVariable()); + + SmtExpr and = SmtMultiArityExpr.Op.AND.make(xyMembers, nextXEqualsY); + + SmtBinaryExpr iff = SmtBinaryExpr.Op.EQ.make(xyInNext, and); + + SmtQtExpr forAllXY = SmtQtExpr.Op.FORALL.make(iff, x, y); + translator.smtScript.addAssertion(new Assertion("", prefix + "next", forAllXY)); + + SmtExpr ordSigSmtExpr = translator.signaturesMap.get(ordSig).getVariable(); + + Sig.Field nextField = StreamSupport + .stream(ordSig.getFields().spliterator(), false) + .filter(field -> field.label.contains("Next")) + .findFirst().get(); + + SmtExpr nextFieldSmtExpr = translator.fieldsMap.get(nextField).getVariable(); + + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(ordSigSmtExpr, nextFieldSmtExpr); + + SmtExpr equality = SmtBinaryExpr.Op.EQ.make(ordNext.getVariable(), join); + + // next = ordSig.Next + translator.smtScript.addAssertion( + new Assertion("", ordNext.getName() + " = " + ordSig.label + "." + nextField.label, equality)); + + // either (next is an empty set and the ordered set is a singleton) or next is nonempty + SmtExpr emptySet = SmtUnaryExpr.Op.EMPTYSET.make(translator.setOfBinaryAtomSort); + SmtExpr nextIsEmpty = SmtBinaryExpr.Op.EQ.make(ordNext.getVariable(), emptySet); + SmtExpr setSingleton = SmtBinaryExpr.Op.EQ.make(setSmtExpr, firstSet); + SmtExpr nextIsNonempty = SmtUnaryExpr.Op.NOT.make(nextIsEmpty); + SmtExpr or = SmtMultiArityExpr.Op.OR.make(SmtMultiArityExpr.Op.AND.make(nextIsEmpty, setSingleton), nextIsNonempty); + + // either (next is an empty set and the ordered set is a singleton) or next is nonempty + translator.smtScript.addAssertion( + new Assertion("", "either (next is an empty set and the ordered set is a singleton) or next is nonempty", or)); + return ordNext; + } + + private FunctionDeclaration addOrdPrev(String prefix, FunctionDeclaration ordNext) + { + FunctionDeclaration ordPrev = new FunctionDeclaration(prefix + "prev", translator.setOfBinaryAtomSort, true); + + SmtUnaryExpr transpose = SmtUnaryExpr.Op.TRANSPOSE.make(ordNext.getVariable()); + + SmtBinaryExpr equality = SmtBinaryExpr.Op.EQ.make(ordPrev.getVariable(), transpose); + + translator.addFunction(ordPrev); + + translator.smtScript.addAssertion(new Assertion("", prefix + "PrevAuxiliary", equality)); + + return ordPrev; + } + + private FunctionDefinition getComparisonDefinition(String prefix, String suffix, FunctionDeclaration mapping, SmtVariable set1, SmtVariable set2, SmtVariable element1, SmtVariable element2, SmtBinaryExpr.Op operator) + { + SmtQtExpr ltExpression = + SmtQtExpr.Op.FORALL.make( + SmtBinaryExpr.Op.IMPLIES.make(SmtMultiArityExpr.Op.AND.make(SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(element1), set1.getVariable()), SmtBinaryExpr.Op.MEMBER.make(TranslatorUtils.getTuple(element2), set2.getVariable())), operator.make(new SmtCallExpr(mapping, element1.getVariable()), new SmtCallExpr(mapping, element1.getVariable()))), + element1, element2 + ); + + return new FunctionDefinition(prefix + suffix, + BoolSort.getInstance(), + ltExpression, true, + set1, set2 + ); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Translation.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Translation.java new file mode 100644 index 000000000..10106c612 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/translators/Translation.java @@ -0,0 +1,125 @@ +package edu.uiowa.alloy2smt.translators; + +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.ast.Expr; +import edu.uiowa.alloy2smt.mapping.Mapper; +import edu.uiowa.alloy2smt.utils.AlloySettings; +import edu.uiowa.smt.optimizer.SmtRewriter; +import edu.uiowa.smt.printers.SmtLibPrinter; +import edu.uiowa.smt.smtAst.SmtScript; + +import java.util.List; + +public class Translation +{ + + private Alloy2SmtTranslator translator; + private final Mapper mapper; + private final AlloySettings alloySettings; + private SmtScript optimizedSmtScript; + + public Translation(Alloy2SmtTranslator translator, SmtScript smtScript, + Mapper mapper, + AlloySettings alloySettings) + { + this.translator = translator; + this.mapper = mapper; + this.alloySettings = alloySettings; + } + + public AlloySettings getAlloySettings() + { + return alloySettings; + } + + /** + * @return a mapper that maps alloy signatures and fields into their + * corresponding functions in the generated smt script + */ + public Mapper getMapper() + { + return mapper; + } + + /** + * @return an abstract syntax tree for the original smt translation + */ + public SmtScript getOriginalSmtScript() + { + return translator.getSmtScript(); + } + + /** + * @return the optimized smt translation for alloy model without commands + */ + public SmtScript getOptimizedSmtScript() + { + return optimizedSmtScript; + } + + /** + * @return the optimized smt translation for the given command + */ + public SmtScript getOptimizedSmtScript(int index) + { + return optimizedSmtScript.getChild(index); + } + + public List getCommands() + { + return translator.commands; + } + + /** + * @param isOptimized + * @return a translation for all commands in smt using (check-sat) + * without getting the models + */ + public String translateAllCommandsWithCheckSat(boolean isOptimized) + { + StringBuilder stringBuilder = new StringBuilder(); + if (isOptimized) + { + stringBuilder.append(getOptimizedSmtScript().print(alloySettings)); + } + else + { + stringBuilder.append(getOriginalSmtScript().print(alloySettings)); + } + for (int i = 0; i < translator.commands.size(); i++) + { + stringBuilder.append(SmtLibPrinter.PUSH + "\n"); + if (isOptimized) + { + stringBuilder.append(getOptimizedSmtScript(i) + "\n"); + } + else + { + stringBuilder.append(getOriginalSmtScript(i) + "\n"); + } + stringBuilder.append(SmtLibPrinter.CHECK_SAT + "\n"); + stringBuilder.append(SmtLibPrinter.POP + "\n"); + } + return stringBuilder.toString(); + } + + private SmtScript getOriginalSmtScript(int index) + { + return translator.smtScript.getChild(index); + } + + /** + * @param expr can be Sig, Field, or Skolem + * @return the unique id of the expr it exists in the idMap, or generate a new id + */ + public int getSigId(Expr expr) + { + return translator.getSigId(expr); + } + + public void optimize() + { + SmtRewriter smtRewriter = new SmtRewriter(); + this.optimizedSmtScript = (SmtScript) smtRewriter.visit(translator.smtScript).smtAst; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloySettings.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloySettings.java new file mode 100644 index 000000000..3c64dce49 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloySettings.java @@ -0,0 +1,32 @@ +package edu.uiowa.alloy2smt.utils; + +import edu.uiowa.smt.smtAst.SmtSettings; + +public class AlloySettings extends SmtSettings +{ + public final static int defaultScope = 3; + public boolean includeCommandScope; + public static final int defaultTimeout = 30000; + public boolean integerSingletonsOnly; + public static AlloySettings Default = new AlloySettings(); + + protected AlloySettings() + { + super(); + putSolverOption(TLIMIT, Integer.toString(defaultTimeout)); + includeCommandScope = false; + integerSingletonsOnly = true; + } + + public static AlloySettings getInstance() + { + return new AlloySettings(Default); + } + + public AlloySettings(AlloySettings settings) + { + super(settings); + this.includeCommandScope = settings.includeCommandScope; + this.integerSingletonsOnly = settings.integerSingletonsOnly; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUnsatCore.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUnsatCore.java new file mode 100644 index 000000000..ef8b2a27e --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUnsatCore.java @@ -0,0 +1,38 @@ +package edu.uiowa.alloy2smt.utils; + +import com.fasterxml.jackson.annotation.JsonProperty; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.uiowa.smt.smtAst.SmtUnsatCore; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@XmlRootElement(name = "AlloyUnsatCore") +public class AlloyUnsatCore +{ + @XmlAttribute(name = "ranges") + @JsonProperty("ranges") + public List ranges = new ArrayList<>(); + + public Set getPositions() + { + return ranges.stream().map(r -> r.toPos()).collect(Collectors.toSet()); + } + + public static AlloyUnsatCore fromSmtUnsatCore(SmtUnsatCore smtUnsatCore) throws IOException + { + AlloyUnsatCore alloyUnsatCore = new AlloyUnsatCore(); + for (String json : smtUnsatCore.getCore()) + { + Range range = Range.fromJson(json); + alloyUnsatCore.ranges.add(range); + } + + return alloyUnsatCore; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUtils.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUtils.java new file mode 100644 index 000000000..e6095eee4 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/AlloyUtils.java @@ -0,0 +1,494 @@ +package edu.uiowa.alloy2smt.utils; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.*; +import edu.uiowa.alloy2smt.Utils; +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +public class AlloyUtils +{ + public static AlloySettings alloySettings = AlloySettings.Default; + + public static List runAlloyString(String alloy, boolean includeScope, AlloySettings alloySettings) throws Exception + { + alloySettings.includeCommandScope = includeScope; + Translation translation = Utils.translate(alloy, alloySettings); + + Cvc4Task task = new Cvc4Task(); + return task.run(translation, includeScope); + } + + public static List runAlloyString(String alloy, boolean includeScope) throws Exception + { + alloySettings.includeCommandScope = includeScope; + Translation translation = Utils.translate(alloy, alloySettings); + + Cvc4Task task = new Cvc4Task(); + return task.run(translation, includeScope); + } + + public synchronized static CommandResult runAlloyFile(String fileName, boolean includeScope, int commandIndex) throws Exception + { + alloySettings.includeCommandScope = includeScope; + Translation translation = Utils.translateFromFile(fileName, alloySettings); + Cvc4Task task = new Cvc4Task(); + CommandResult result = task.run(translation, includeScope, commandIndex); + /* + id_lock.acquire() + app.unique_id = app.unique_id + 1 + app.robots_dictionary[app.unique_id] = None + client_directory = app.upload_directory + '/' + str(app.unique_id) + if not os.path.exists(client_directory): + os.makedirs(client_directory) + id_lock.release() + return jsonify({'id': app.unique_id}) + */ + int index = 0; + String smtFile = fileName.replace(".als", "") + "_" + index + "_" + result.satResult + ".smt2"; + while (Files.exists(Paths.get(smtFile))) + { + index++; + smtFile = fileName.replace(".als", "") + "_" + index + "_" + result.satResult + ".smt2"; + } + + try (Formatter formatter = new Formatter(smtFile)) + { + if (result.satResult.equals("sat")) + { + formatter.format("%s\n", "; EXPECT: sat"); + } + if (result.satResult.equals("unsat")) + { + formatter.format("%s\n", "; EXPECT: unsat"); + } + formatter.format("%s\n", result.smtProgram); + } + + return result; + } + + public static CommandResult runAlloyFileTimeout(int timeout, String fileName, boolean includeScope, int commandIndex) throws Exception + { + Translation translation = Utils.translateFromFile(fileName, alloySettings); + Cvc4Task task = new Cvc4Task(); + return task.run(translation, includeScope, commandIndex); + } + + public static FunctionDefinition getFunctionDefinition(CommandResult commandResult, String name) + { + return TranslatorUtils.getFunctionDefinition(commandResult.smtModel, name); + } + + public static List getExprSorts(Expr expr) + { + List sorts = new ArrayList<>(); + // get the first list of types from the fold function + for (Sig.PrimSig sig : expr.type().fold().get(0)) + { + if (sig.type().is_int()) + { + sorts.add(AbstractTranslator.uninterpretedInt); + } + else + { + sorts.add(AbstractTranslator.atomSort); + } + } + return sorts; + } + + public static SmtBinaryExpr getMemberExpression(Map variableToSetMap, int index) + { + SmtVariable declaration = (new ArrayList<>(variableToSetMap.keySet())).get(index); + SmtExpr rightSetSmtExpr = variableToSetMap.get(declaration); + if (declaration.getSort() instanceof SetSort) + { + return SmtBinaryExpr.Op.SUBSET.make(declaration.getVariable(), rightSetSmtExpr); + } + if (declaration.getSort() instanceof TupleSort) + { + return SmtBinaryExpr.Op.MEMBER.make(declaration.getVariable(), rightSetSmtExpr); + } + if ((declaration.getSort() instanceof UninterpretedSort) || (declaration.getSort() instanceof IntSort)) + { + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, declaration.getVariable()); + return SmtBinaryExpr.Op.MEMBER.make(tuple, rightSetSmtExpr); + } + + throw new UnsupportedOperationException(String.format("%s", declaration.getSort())); + } + + public static SmtExpr mkSingletonOutOfAtoms(List atomExprs) + { + SmtMultiArityExpr tuple = SmtMultiArityExpr.Op.MKTUPLE.make(atomExprs); + SmtUnaryExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tuple); + return singleton; + } + + public static SmtExpr mkSingletonOutOfTuple(SmtExpr tupleExpr) + { + SmtUnaryExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tupleExpr); + return singleton; + } + + public static List getFunctionCallArguments(List quantifiedArguments, + Map argumentsMap) + { + List smtExprs = new ArrayList<>(); + for (SmtVariable declaration : quantifiedArguments) + { + if (declaration.getSort().equals(argumentsMap.get(declaration.getName()).getSort())) + { + smtExprs.add(declaration.getVariable()); + } + else + { + smtExprs.add(SmtUnaryExpr.Op.SINGLETON.make(declaration.getVariable())); + } + } + return smtExprs; + } + + public static Expr substituteExpr(Expr body, ExprVar oldExpr, Expr newExpr) + { + if (body instanceof ExprVar) + { + if (((ExprVar) body).label.equals(oldExpr.label) && + body.type().equals(oldExpr.type())) + { + return newExpr; + } + else + { + return body; + } + } + + if (body instanceof ExprConstant) + { + return body; + } + + if (body instanceof Sig || body instanceof Sig.Field) + { + return body; + } + + if (body instanceof ExprUnary) + { + ExprUnary unary = (ExprUnary) body; + Expr sub = substituteExpr(unary.sub, oldExpr, newExpr); + return unary.op.make(unary.pos, sub); + } + + if (body instanceof ExprBinary) + { + ExprBinary binary = (ExprBinary) body; + Expr left = substituteExpr(binary.left, oldExpr, newExpr); + Expr right = substituteExpr(binary.right, oldExpr, newExpr); + return binary.op.make(binary.pos, binary.closingBracket, left, right); + } + + if (body instanceof ExprQt) + { + ExprQt qt = (ExprQt) body; + Expr sub = qt.sub; + List declList = new ArrayList<>(); + + for (Decl decl : qt.decls) + { + List variables = new ArrayList<>(); + for (ExprHasName name : decl.names) + { + // return the body if the oldExpr is a quantifier + if (oldExpr.label.equals(name.label)) + { + return body; + } + + // change the quantifier name if newExpr contains a free variable with the same name + if (hasFreeVariable((ExprVar) name, newExpr)) + { + ExprVar newName = ExprVar.make(name.pos, TranslatorUtils.getFreshName(null)); + sub = substituteExpr(sub, (ExprVar) name, newName); + variables.add(newName); + } + else + { + variables.add((ExprVar) name); + } + } + + Expr declaredExpr = decl.expr; + declaredExpr = substituteExpr(declaredExpr, oldExpr, newExpr); + + Decl newDecl = new Decl(decl.isPrivate, decl.disjoint, decl.disjoint2, decl.isVar, variables, declaredExpr); + declList.add(newDecl); + } + + sub = substituteExpr(sub, oldExpr, newExpr); + Expr newQt = qt.op.make(qt.pos, qt.closingBracket, declList, sub); + return newQt; + } + + if (body instanceof ExprList) + { + ExprList list = (ExprList) body; + + List arguments = new ArrayList<>(); + for (Expr expr : list.args) + { + Expr newArgument = substituteExpr(expr, oldExpr, newExpr); + arguments.add(newArgument); + } + + return ExprList.make(list.pos, list.closingBracket, list.op, arguments); + } + + if (body instanceof ExprLet) + { + // first expand the let body + + ExprLet let = (ExprLet) body; + + Expr letExpanded = substituteExpr(let.sub, let.var, let.expr); + Expr newLet = substituteExpr(letExpanded, oldExpr, newExpr); + return newLet; + } + + if (body instanceof ExprITE) + { + ExprITE ite = (ExprITE) body; + Expr cond = substituteExpr(ite.cond, oldExpr, newExpr); + Expr left = substituteExpr(ite.left, oldExpr, newExpr); + Expr right = substituteExpr(ite.right, oldExpr, newExpr); + return ExprITE.make(ite.pos, cond, left, right); + } + + if (body instanceof ExprCall) + { + ExprCall call = (ExprCall) body; + + Map arguments = new HashMap<>(); + + for (int i = 0; i < call.args.size(); i++) + { + Expr newArgument = substituteExpr(call.args.get(i), oldExpr, newExpr); + arguments.put(call.fun.get(i), newArgument); + } + + // substitute the old arguments in the function body with the new arguments. + Expr functionBody = call.fun.getBody(); + for (Map.Entry entry : arguments.entrySet()) + { + functionBody = substituteExpr(functionBody, entry.getKey(), entry.getValue()); + } + + return functionBody; + } + + throw new UnsupportedOperationException(); + } + + private static boolean hasFreeVariable(ExprVar variable, Expr expr) + { + if (expr instanceof ExprVar) + { + return variable.label.equals(((ExprVar) expr).label); + } + + if (expr instanceof Sig || expr instanceof Sig.Field) + { + return false; + } + + if (expr instanceof ExprConstant) + { + return false; + } + + if (expr instanceof ExprUnary) + { + return hasFreeVariable(variable, ((ExprUnary) expr).sub); + } + + if (expr instanceof ExprBinary) + { + boolean left = hasFreeVariable(variable, ((ExprBinary) expr).left); + boolean right = hasFreeVariable(variable, ((ExprBinary) expr).right); + return left || right; + } + + if (expr instanceof ExprQt) + { + for (Decl decl : ((ExprQt) expr).decls) + { + for (ExprHasName name : decl.names) + { + if (name.label.equals(variable.label)) + { + return false; + } + } + } + return hasFreeVariable(variable, ((ExprQt) expr).sub); + } + + if (expr instanceof ExprList) + { + ExprList list = (ExprList) expr; + + for (Expr argument : list.args) + { + if (hasFreeVariable(variable, argument)) + { + return true; + } + } + + return false; + } + + if (expr instanceof ExprLet) + { + if (((ExprLet) expr).var.label.equals(variable.label)) + { + return false; + } + + boolean exprBoolean = hasFreeVariable(variable, ((ExprLet) expr).expr); + boolean subBoolean = hasFreeVariable(variable, ((ExprLet) expr).sub); + return exprBoolean || subBoolean; + } + + if (expr instanceof ExprITE) + { + ExprITE ite = (ExprITE) expr; + boolean cond = hasFreeVariable(variable, ite.cond); + boolean left = hasFreeVariable(variable, ite.left); + boolean right = hasFreeVariable(variable, ite.right); + return cond || left || right; + } + + if (expr instanceof ExprCall) + { + ExprCall call = (ExprCall) expr; + + for (Expr argument : call.args) + { + if (hasFreeVariable(variable, argument)) + { + return true; + } + } + + return false; + } + + throw new UnsupportedOperationException(); + } + + public static Expr removeMultiplicity(Decl decl) + { + return removeMultiplicity(decl.expr); + } + + private static Expr removeMultiplicity(Expr expr) + { + if (expr instanceof ExprVar) + { + return expr; + } + + if (expr instanceof Sig || expr instanceof Sig.Field) + { + return expr; + } + + if (expr instanceof ExprConstant) + { + return expr; + } + + if (expr instanceof ExprUnary) + { + return removeMultiplicity(((ExprUnary) expr).sub); + } + + if (expr instanceof ExprBinary) + { + Expr left = removeMultiplicity(((ExprBinary) expr).left); + Expr right = removeMultiplicity(((ExprBinary) expr).right); + ExprBinary.Op op = ((ExprBinary) expr).op; + + switch (op) + { + case ARROW: + case ANY_ARROW_SOME: + case ANY_ARROW_ONE: + case ANY_ARROW_LONE: + case SOME_ARROW_ANY: + case SOME_ARROW_SOME: + case SOME_ARROW_ONE: + case SOME_ARROW_LONE: + case ONE_ARROW_ANY: + case ONE_ARROW_SOME: + case ONE_ARROW_ONE: + case ONE_ARROW_LONE: + case LONE_ARROW_ANY: + case LONE_ARROW_SOME: + case LONE_ARROW_ONE: + case LONE_ARROW_LONE: + case ISSEQ_ARROW_LONE: + return ExprBinary.Op.ARROW.make(expr.pos, expr.closingBracket, left, right); + default: + return op.make(expr.pos, expr.closingBracket, left, right); + } + + + } + throw new UnsupportedOperationException(); + } + + public static String sanitizeAtom(String atom) + { + return atom.replace("@uc_", "") + .replace("$", ""); + } + + public static Assertion getAssertion(List positions, String comment, SmtExpr smtExpr) + { + try + { + StringBuilder stringBuilder = new StringBuilder(); + for (Pos position : positions) + { + Range range = new Range(position); + range.symbolIndex = getFreshSymbol(); + stringBuilder.append(range.toJson()); + } + return new Assertion(stringBuilder.toString(), comment, smtExpr); + } + catch (IOException e) + { + throw new RuntimeException(e.getMessage()); + } + } + + private static int symbolIndex = 0; + + private static int getFreshSymbol() + { + symbolIndex++; + return symbolIndex; + } +} + diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/CommandResult.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/CommandResult.java new file mode 100644 index 000000000..88ce5a0cb --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/CommandResult.java @@ -0,0 +1,17 @@ +package edu.uiowa.alloy2smt.utils; + +import edu.mit.csail.sdg.ast.Command; +import edu.uiowa.smt.Result; + +public class CommandResult extends Result +{ + public final int index; + public final Command command; + + public CommandResult(int index, Command command, String smtProgram, String satResult) + { + super(smtProgram, satResult); + this.index = index; + this.command = command; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Cvc4Task.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Cvc4Task.java new file mode 100644 index 000000000..ef9c61b48 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Cvc4Task.java @@ -0,0 +1,71 @@ +package edu.uiowa.alloy2smt.utils; + +import edu.mit.csail.sdg.ast.Command; +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.smt.cvc4.Cvc4Process; +import edu.uiowa.smt.printers.SmtLibPrinter; + +import java.util.ArrayList; +import java.util.List; + +public class Cvc4Task +{ + public Cvc4Process cvc4Process; + + public Cvc4Task() + { + } + + public List run(Translation translation, boolean includeScope) throws Exception + { + List commandResults = new ArrayList<>(); + String smtScript = translation.getOptimizedSmtScript().print(translation.getAlloySettings()); + if (smtScript != null) + { + cvc4Process = Cvc4Process.start(); + + cvc4Process.sendCommand(smtScript); + + // surround each command except the last one with (push) and (pop) + for (int index = 0; index < translation.getCommands().size(); index++) + { + // (push) + cvc4Process.sendCommand(SmtLibPrinter.PUSH); + CommandResult commandResult = solveCommand(index, includeScope, translation); + // (pop) + cvc4Process.sendCommand(SmtLibPrinter.POP); + commandResults.add(commandResult); + } + return commandResults; + } + return new ArrayList<>(); + } + + public CommandResult run(Translation translation, boolean includeScope, int commandIndex) throws Exception + { + String smtScript = translation.getOptimizedSmtScript().print(translation.getAlloySettings()); + cvc4Process = Cvc4Process.start(); + + cvc4Process.sendCommand(smtScript); + + CommandResult commandResult = solveCommand(commandIndex, includeScope, translation); + + return commandResult; + } + + private CommandResult solveCommand(int index, boolean includeScope, Translation translation) throws Exception + { + Command command = translation.getCommands().get(index); + String commandTranslation = translation.getOptimizedSmtScript(index).toString(); + String result = cvc4Process.sendCommand(commandTranslation + SmtLibPrinter.CHECK_SAT); + String smt = translation.getOptimizedSmtScript() + commandTranslation + SmtLibPrinter.CHECK_SAT; + CommandResult commandResult = new CommandResult(index, command, smt, result); + + if (result.equals("sat")) + { + commandResult.model = cvc4Process.sendCommand(SmtLibPrinter.GET_MODEL); + commandResult.smtModel = commandResult.parseModel(commandResult.model); + } + return commandResult; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Range.java b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Range.java new file mode 100644 index 000000000..4c9fb97ad --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/alloy2smt/utils/Range.java @@ -0,0 +1,71 @@ +package edu.uiowa.alloy2smt.utils; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.mit.csail.sdg.alloy4.Pos; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +@XmlRootElement(name = "Range") +public class Range +{ + public Range() + { + } + + public Range(Pos pos) + { + this.filename = pos.filename; + this.x1 = pos.x; + this.y1 = pos.y; + this.x2 = pos.x2; + this.y2 = pos.y2; + } + + @XmlAttribute(name = "filename") + @JsonProperty("filename") + String filename = ""; + + @XmlAttribute(name = "x1") + @JsonProperty("x1") + int x1; + + @XmlAttribute(name = "y1") + @JsonProperty("y1") + int y1; + + @XmlAttribute(name = "x2") + @JsonProperty("x2") + int x2; + + @XmlAttribute(name = "y2") + @JsonProperty("y2") + int y2; + + @XmlAttribute(name = "symbolIndex") + @JsonProperty("symbolIndex") + int symbolIndex; + + public Pos toPos() + { + return new Pos(filename, x1, y1, x2, y2); + } + + public String toJson() throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + objectMapper.writeValue(outputStream, this); + return outputStream.toString(); + } + + public static Range fromJson(String json) throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + Range range = objectMapper.readValue(json, Range.class); + return range; + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/AbstractTranslator.java b/SMT-Extension/src/main/java/edu/uiowa/smt/AbstractTranslator.java new file mode 100644 index 000000000..fc9e9e8c2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/AbstractTranslator.java @@ -0,0 +1,236 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt; + +import edu.uiowa.smt.smtAst.*; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public abstract class AbstractTranslator +{ + // static members + public final static String intSortName = "Int"; + public final static String boolSortName = "Bool"; + public final static String atom = "Atom"; + public final static String uninterpretedIntName = "UInt"; + public final static String uninterpretedIntValueName = "intValue"; + public final static String plus = "PLUS"; + public final static String minus = "MINUS"; + public final static String multiply = "MUL"; + public final static String divide = "DIV"; + public final static String mod = "MOD"; + public final static IntSort intSort = IntSort.getInstance(); + public final static TupleSort intSortTuple = new TupleSort(intSort); + public final static SetSort setOfIntSortTuple = new SetSort(intSortTuple); + public final static BoolSort boolSort = BoolSort.getInstance(); + public final static UninterpretedSort atomSort = new UninterpretedSort(atom); + public final static UninterpretedSort uninterpretedInt = new UninterpretedSort(uninterpretedIntName); + public final static TupleSort uninterpretedIntTuple = new TupleSort(uninterpretedInt); + public final static SetSort setOfUninterpretedIntTuple = new SetSort(uninterpretedIntTuple); + public final static SetSort setOfUninterpretedIntPairs = new SetSort(new TupleSort(uninterpretedInt, uninterpretedInt)); + public final static TupleSort unaryAtomSort = new TupleSort(atomSort); + public final static TupleSort binaryAtomSort = new TupleSort(atomSort, atomSort); + public final static TupleSort ternaryIntSort = new TupleSort(uninterpretedInt, uninterpretedInt, uninterpretedInt); + public final static SetSort setOfUnaryAtomSort = new SetSort(unaryAtomSort); + public final static SetSort setOfBinaryAtomSort = new SetSort(binaryAtomSort); + public final static SetSort setOfTernaryIntSort = new SetSort(ternaryIntSort); + public final static FunctionDeclaration univAtom = new FunctionDeclaration("univAtom", setOfUnaryAtomSort, false); + public final static FunctionDeclaration atomNone = new FunctionDeclaration("atomNone", setOfUnaryAtomSort, false); + public final static FunctionDeclaration idenAtom = new FunctionDeclaration("idenAtom", setOfBinaryAtomSort, false); + public final static FunctionDeclaration univInt = new FunctionDeclaration("univInt", setOfUninterpretedIntTuple, false); + public final static FunctionDeclaration idenInt = new FunctionDeclaration("idenInt", setOfUninterpretedIntPairs, false); + public final static SmtUnaryExpr intUnivExpr = SmtUnaryExpr.Op.UNIVSET.make(setOfUninterpretedIntTuple); + public final static FunctionDeclaration uninterpretedIntValue = new FunctionDeclaration(uninterpretedIntValueName, uninterpretedInt, intSort, false); + + // special assertions + public final static Assertion noneAssertion = new Assertion("", "Empty unary relation definition for Atom", SmtBinaryExpr.Op.EQ.make(atomNone.getVariable(), SmtUnaryExpr.Op.EMPTYSET.make(setOfUnaryAtomSort))); + + public final static Assertion univAssertion = new Assertion("", "Universe definition for Atom", SmtBinaryExpr.Op.EQ.make(univAtom.getVariable(), SmtUnaryExpr.Op.UNIVSET.make(setOfUnaryAtomSort))); + + public final static Assertion idenAtomAssertion = getIdentityRelation(atomSort, idenAtom); + + public final static Assertion univIntAssertion = new Assertion("", "Universe definition for UninterpretedInt", SmtBinaryExpr.Op.EQ.make(univInt.getVariable(), SmtUnaryExpr.Op.UNIVSET.make(setOfUninterpretedIntTuple))); + + public final static Assertion idenIntAssertion = getIdentityRelation(uninterpretedInt, idenInt); + + public final static Assertion intValueAssertion = getUninterpretedIntValueAssertion(); + + // non static members + public SmtScript smtScript; + public Map functionsMap; + public Map comparisonOperations; + public Map arithmeticOperations; + + public void addFunction(FunctionDeclaration function) + { + this.functionsMap.put(function.getName(), function); + this.smtScript.addFunction(function); + } + + public FunctionDeclaration getFunction(String functionName) + { + FunctionDeclaration function = functionsMap.get(functionName); + if (function == null) + { + throw new RuntimeException("Function " + functionName + " is not found."); + } + return function; + } + + public abstract SmtScript translate(); + + public SmtExpr handleIntConstant(SmtExpr smtExpr) + { + if (smtExpr.getSort().equals(AbstractTranslator.intSortTuple)) + { + SmtExpr intConstant = ((SmtMultiArityExpr) smtExpr).getExprs().get(0); + FunctionDeclaration uninterpretedInt = this.getUninterpretedIntConstant((IntConstant) intConstant); + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, uninterpretedInt.getVariable()); + return tuple; + } + if (smtExpr.getSort().equals(AbstractTranslator.setOfIntSortTuple)) + { + SmtExpr intConstant = ((SmtMultiArityExpr) ((SmtUnaryExpr) smtExpr).getExpr()).getExprs().get(0); + FunctionDeclaration uninterpretedInt = this.getUninterpretedIntConstant((IntConstant) intConstant); + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, uninterpretedInt.getVariable()); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tuple); + return singleton; + } + return smtExpr; + } + + public FunctionDeclaration getUninterpretedIntConstant(IntConstant intConstant) + { + BigInteger value = new BigInteger(intConstant.getValue()); + Map integerConstants = smtScript.getIntegerConstants(); + if (smtScript.getIntegerConstants().containsKey(value)) + { + return integerConstants.get(value); + } + + FunctionDeclaration uninterpretedInt = new FunctionDeclaration(TranslatorUtils.getFreshName(AbstractTranslator.uninterpretedInt) + "_" + value.toString(), + AbstractTranslator.uninterpretedInt, false); + smtScript.putIntegerConstant(value, uninterpretedInt); + SmtExpr callSmtExpr = new SmtCallExpr(AbstractTranslator.uninterpretedIntValue, uninterpretedInt.getVariable()); + SmtExpr equality = SmtBinaryExpr.Op.EQ.make(callSmtExpr, intConstant); + Assertion assertion = new Assertion("", "constant integer", equality); + smtScript.addAssertion(assertion); + return uninterpretedInt; + } + + protected void translateSpecialAssertions() + { + this.smtScript.addAssertion(noneAssertion); + this.smtScript.addAssertion(univAssertion); + this.smtScript.addAssertion(univIntAssertion); + this.smtScript.addAssertion(idenAtomAssertion); + this.smtScript.addAssertion(idenIntAssertion); + this.smtScript.addAssertion(intValueAssertion); + } + + private static Assertion getUninterpretedIntValueAssertion() + { + // uninterpretedIntValue is injective function + SmtVariable X = new SmtVariable("x", uninterpretedInt, false); + SmtVariable Y = new SmtVariable("y", uninterpretedInt, false); + SmtExpr XEqualsY = SmtBinaryExpr.Op.EQ.make(X.getVariable(), Y.getVariable()); + SmtExpr notXEqualsY = SmtUnaryExpr.Op.NOT.make(XEqualsY); + + SmtExpr XValue = new SmtCallExpr(uninterpretedIntValue, X.getVariable()); + SmtExpr YValue = new SmtCallExpr(uninterpretedIntValue, Y.getVariable()); + + SmtExpr XValueEqualsYValue = SmtBinaryExpr.Op.EQ.make(XValue, YValue); + SmtExpr notXValueEqualsYValue = SmtUnaryExpr.Op.NOT.make(XValueEqualsYValue); + SmtExpr implication = SmtBinaryExpr.Op.IMPLIES.make(notXEqualsY, notXValueEqualsYValue); + SmtExpr forAll = SmtQtExpr.Op.FORALL.make(implication, X, Y); + + return new Assertion("", uninterpretedIntValueName + " is injective", forAll); + } + + private static Assertion getIdentityRelation(Sort sort, FunctionDeclaration identity) + { + // Axiom for identity relation + SmtVariable a = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtVariable b = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + + SmtMultiArityExpr tupleAB = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, a.getVariable(), b.getVariable()); + + SmtBinaryExpr member = SmtBinaryExpr.Op.MEMBER.make(tupleAB, identity.getVariable()); + + SmtBinaryExpr equals = SmtBinaryExpr.Op.EQ.make(a.getVariable(), b.getVariable()); + + SmtBinaryExpr equiv = SmtBinaryExpr.Op.EQ.make(member, equals); + + SmtQtExpr forAll = SmtQtExpr.Op.FORALL.make(equiv, a, b); + + Assertion assertion = new Assertion("", "Identity relation definition for " + identity.getName(), forAll); + + return assertion; + } + + public SmtScript getSmtScript() + { + return smtScript; + } + + public static List getUninterpretedIntFunctions(SmtScript script) + { + List functions = new ArrayList<>(Arrays.asList(AbstractTranslator.uninterpretedIntValue, AbstractTranslator.idenInt, AbstractTranslator.univInt)); + + //ToDo: delete when alloy parser supports univInt + List univInt = script.getFunctions().stream() + .filter(f -> f.getName().equals("integer/univInt")) + .collect(Collectors.toList()); + functions.addAll(univInt); + return functions; + } + + public static List getUninterpretedIntAssertions(SmtScript script) + { + List assertions = new ArrayList<>(); + assertions.add(AbstractTranslator.univIntAssertion); + assertions.add(AbstractTranslator.idenIntAssertion); + assertions.add(AbstractTranslator.intValueAssertion); + + //ToDo: remove this when alloy parser supports univInt and idenInt + List assertions1 = script.getAssertions().stream() + .filter(a -> a.getComment().equals("integer/univInt = Int")) + .collect(Collectors.toList()); + + List assertions2 = script.getAssertions().stream() + .filter(a -> a.getComment().equals("(all x,y | x = y <=> x -> y in (integer/univInt <: idenInt))")) + .collect(Collectors.toList()); + + List assertions3 = script.getAssertions().stream() + .filter(a -> a.getComment().equals("universe") && + a.getSmtExpr().getComment().equals("integer/univInt = Int") + ) + .collect(Collectors.toList()); + + List assertions4 = script.getAssertions().stream() + .filter(a -> a.getComment().equals("identity") && + a.getSmtExpr().getComment().equals("(all x,y | x = y <=> x -> y in (integer/univInt <: idenInt))") + ) + .collect(Collectors.toList()); + + assertions.addAll(assertions1); + assertions.addAll(assertions2); + assertions.addAll(assertions3); + assertions.addAll(assertions4); + + return assertions; + } + +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/Result.java b/SMT-Extension/src/main/java/edu/uiowa/smt/Result.java new file mode 100644 index 000000000..2165c0a52 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/Result.java @@ -0,0 +1,72 @@ +package edu.uiowa.smt; + +import edu.uiowa.smt.parser.SmtModelVisitor; +import edu.uiowa.smt.parser.antlr.SmtLexer; +import edu.uiowa.smt.parser.antlr.SmtParser; +import edu.uiowa.smt.smtAst.SmtModel; +import edu.uiowa.smt.smtAst.SmtUnsatCore; +import edu.uiowa.smt.smtAst.SmtValues; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +public class Result +{ + public String smtProgram; + public String satResult; + public String model; + public SmtModel smtModel; + private SmtModelVisitor visitor; + + public Result() + { + } + + public Result(String smtProgram, String satResult) + { + this.smtProgram = smtProgram; + this.satResult = satResult; + } + + public SmtModel parseModel(String model) + { + SmtParser parser = getSmtParser(model); + + ParseTree tree = parser.model(); + visitor = new SmtModelVisitor(); + + SmtModel smtModel = (SmtModel) visitor.visit(tree); + + return smtModel; + } + + public SmtValues parseValues(String values) + { + if (this.visitor == null) + { + throw new RuntimeException("Result.parseValues method should only be called after Result.parseModel is called"); + } + SmtParser parser = getSmtParser(values); + ParseTree tree = parser.getValue(); + SmtValues smtValues = (SmtValues) this.visitor.visit(tree); + return smtValues; + } + + public SmtUnsatCore parseUnsatCore(String core) + { + SmtParser parser = getSmtParser(core); + ParseTree tree = parser.getUnsatCore(); + SmtModelVisitor visitor = new SmtModelVisitor(); + SmtUnsatCore smtUnsatCore = (SmtUnsatCore) visitor.visit(tree); + return smtUnsatCore; + } + + private SmtParser getSmtParser(String values) + { + CharStream charStream = CharStreams.fromString(values); + SmtLexer lexer = new SmtLexer(charStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + return new SmtParser(tokenStream); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/SmtEnv.java b/SMT-Extension/src/main/java/edu/uiowa/smt/SmtEnv.java new file mode 100644 index 000000000..84540b397 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/SmtEnv.java @@ -0,0 +1,103 @@ +package edu.uiowa.smt; + +import edu.uiowa.smt.smtAst.SmtExpr; +import edu.uiowa.smt.smtAst.SmtVariable; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class SmtEnv +{ + private LinkedHashMap variablesMap = new LinkedHashMap<>(); + private List auxiliaryVariables = new ArrayList<>(); + private SmtEnv parent; + + // top level environment + public SmtEnv() + { + parent = null; + variablesMap = new LinkedHashMap<>(); + } + + public SmtEnv(SmtEnv parent) + { + this.parent = parent; + } + + public void put(String key, SmtExpr value) + { + variablesMap.put(key, value); + } + + public void putAll(Map map) + { + for (Map.Entry entry : map.entrySet()) + { + put(entry.getKey(), entry.getValue()); + } + } + + public SmtExpr get(String key) + { + SmtEnv currentSmtEnv = this; + while (currentSmtEnv != null) + { + SmtExpr value = currentSmtEnv.variablesMap.get(key); + if (value != null) + { + return value; + } + currentSmtEnv = currentSmtEnv.parent; + } + throw new RuntimeException(String.format("Can not find the variable %s in the environment", key)); + } + + public boolean containsKey(String key) + { + SmtEnv currentSmtEnv = this; + while (currentSmtEnv != null) + { + if (currentSmtEnv.variablesMap.containsKey(key)) + { + return true; + } + currentSmtEnv = currentSmtEnv.parent; + } + return false; + } + + public SmtEnv getParent() + { + return parent; + } + + public List getAuxiliaryVariables() + { + return auxiliaryVariables; + } + + public LinkedHashMap getVariables() + { + return getVariablesHelper(this); + } + + private LinkedHashMap getVariablesHelper(SmtEnv smtEnv) + { + if (smtEnv.parent == null) + { + return new LinkedHashMap<>(smtEnv.variablesMap); + } + + LinkedHashMap map = getVariablesHelper(smtEnv.parent); + map.putAll(smtEnv.variablesMap); + return map; + } + + public void addAuxiliaryVariable(SmtVariable variable) + { + auxiliaryVariables.add(variable); + variablesMap.put(variable.getName(), variable.getVariable()); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/TranslatorUtils.java b/SMT-Extension/src/main/java/edu/uiowa/smt/TranslatorUtils.java new file mode 100644 index 000000000..cd3422aef --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/TranslatorUtils.java @@ -0,0 +1,383 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt; + + +import edu.uiowa.smt.smtAst.*; + +import java.util.*; +import java.util.stream.Collectors; + +public class TranslatorUtils +{ + private static int freshNameIndex = 0; + + public static String sanitizeWithBars(Declaration declaration) + { + if (declaration.isOriginal()) + { + // add extra space to separate original variables from generated ones + return "|" + declaration.getName() + " |"; + } + return declaration.getName(); + } + + public static String getFreshName(Sort sort) + { + freshNameIndex++; + if (sort != null) + { + if (sort instanceof SetSort) + { + Sort elementSort = ((SetSort) sort).elementSort; + if (elementSort instanceof TupleSort) + { + int arity = ((TupleSort) elementSort).elementSorts.size(); + if (arity > 1) + { + return "r" + arity + "." + freshNameIndex; + } + } + return "s" + "." + freshNameIndex; + } + + if (sort instanceof TupleSort) + { + int arity = ((TupleSort) sort).elementSorts.size(); + if (arity > 1) + { + return "t" + arity + "." + freshNameIndex; + } + Sort tupleSort = ((TupleSort) sort).elementSorts.get(0); + if (tupleSort instanceof UninterpretedSort) + { + UninterpretedSort uninterpretedSort = (UninterpretedSort) tupleSort; + + if (uninterpretedSort.equals(AbstractTranslator.atomSort)) + { + return "tA." + freshNameIndex; + } + + if (uninterpretedSort.equals(AbstractTranslator.uninterpretedInt)) + { + return "tU." + freshNameIndex; + } + } + return "t" + "." + freshNameIndex; + } + + if (sort instanceof UninterpretedSort) + { + UninterpretedSort uninterpretedSort = (UninterpretedSort) sort; + + if (uninterpretedSort.equals(AbstractTranslator.atomSort)) + { + return "a." + freshNameIndex; + } + + if (uninterpretedSort.equals(AbstractTranslator.uninterpretedInt)) + { + return "u." + freshNameIndex; + } + } + } + return "x." + freshNameIndex; + } + + public static void reset() + { + freshNameIndex = 0; + } + + public static Sort getSetSortOfAtomWithArity(int n) + { + List elementSorts = new ArrayList<>(); + for (int i = 0; i < n; ++i) + { + elementSorts.add(AbstractTranslator.atomSort); + } + return new SetSort(new TupleSort(elementSorts)); + } + + public static SmtExpr makeDistinct(SmtExpr... exprs) + { + if (exprs == null) + { + throw new RuntimeException(); + } + else if (exprs.length == 1) + { + return exprs[0]; + } + else + { + return new SmtMultiArityExpr(SmtMultiArityExpr.Op.DISTINCT, exprs); + } + } + + public static SmtExpr makeDistinct(List exprs) + { + if (exprs == null) + { + throw new RuntimeException(); + } + else if (exprs.isEmpty() || exprs.size() == 1) + { + return BoolConstant.True; + } + else + { + return SmtMultiArityExpr.Op.DISTINCT.make(exprs); + } + } + + public static SmtExpr getTuple(Declaration... elements) + { + List smtExprs = Arrays.stream(elements) + .map(Declaration::getVariable).collect(Collectors.toList()); + return SmtMultiArityExpr.Op.MKTUPLE.make(smtExprs); + } + + public static SmtExpr getTuple(SmtExpr... smtExprs) + { + return new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, smtExprs); + } + + public static int getInt(FunctionDefinition definition) + { + return getInt(definition.smtExpr); + } + + public static int getInt(SmtExpr smtExpr) + { + SmtUnaryExpr unary = (SmtUnaryExpr) smtExpr; + if (unary.getOp() == SmtUnaryExpr.Op.EMPTYSET) + { + return 0; // zero is equivalent to an empty set + } + assert (SmtUnaryExpr.Op.SINGLETON == unary.getOp()); + SmtMultiArityExpr tuple = (SmtMultiArityExpr) unary.getExpr(); + assert (SmtMultiArityExpr.Op.MKTUPLE == tuple.getOp()); + IntConstant constant = (IntConstant) tuple.getExprs().get(0); + return Integer.parseInt(constant.getValue()); + } + + public static Set getIntSet(FunctionDefinition definition) + { + return getIntSet(definition.getBody()); + } + + public static Set getIntSet(SmtExpr smtExpr) + { + if (smtExpr instanceof SmtUnaryExpr) + { + return new HashSet<>(Arrays.asList(getInt(smtExpr))); + } + SmtBinaryExpr binary = (SmtBinaryExpr) smtExpr; + Set set = new HashSet<>(); + assert (binary.getOp() == SmtBinaryExpr.Op.UNION); + set.addAll(getIntSet(binary.getA())); + set.addAll(getIntSet(binary.getB())); + return set; + } + + public static Set getAtomSet(FunctionDefinition definition) + { + return getAtomSet(definition.getBody()); + } + + public static Set getAtomSet(SmtExpr smtExpr) + { + if (smtExpr instanceof UninterpretedConstant) + { + UninterpretedConstant constant = (UninterpretedConstant) smtExpr; + return Collections.singleton(constant.getName()); + } + if (smtExpr instanceof SmtUnaryExpr) + { + SmtUnaryExpr unary = (SmtUnaryExpr) smtExpr; + if (unary.getOp() == SmtUnaryExpr.Op.EMPTYSET) + { + return new HashSet<>(); + } + assert (SmtUnaryExpr.Op.SINGLETON == unary.getOp()); + SmtMultiArityExpr tuple = (SmtMultiArityExpr) unary.getExpr(); + assert (SmtMultiArityExpr.Op.MKTUPLE == tuple.getOp()); + UninterpretedConstant constant = (UninterpretedConstant) tuple.getExprs().get(0); + return new HashSet<>(Collections.singletonList(constant.getName())); + } + if (smtExpr instanceof SmtBinaryExpr) + { + SmtBinaryExpr binary = (SmtBinaryExpr) smtExpr; + Set set = new HashSet<>(); + assert (binary.getOp() == SmtBinaryExpr.Op.UNION); + set.addAll(getAtomSet(binary.getA())); + set.addAll(getAtomSet(binary.getB())); + return set; + } + + throw new UnsupportedOperationException("Not supported yet"); + } + + public static Set> getRelation(FunctionDefinition definition) + { + if (!(definition.getSort() instanceof SetSort)) + { + throw new UnsupportedOperationException(definition.getSort().toString()); + } + SetSort setSort = (SetSort) definition.getSort(); + if (!(setSort.elementSort instanceof TupleSort)) + { + throw new UnsupportedOperationException(setSort.elementSort.toString()); + } + return getRelation(definition.getBody()); + } + + public static Set> getRelation(SmtExpr smtExpr) + { + if (smtExpr instanceof SmtUnaryExpr) + { + SmtUnaryExpr unary = (SmtUnaryExpr) smtExpr; + if (unary.getOp() == SmtUnaryExpr.Op.EMPTYSET) + { + return new HashSet<>(); + } + assert (SmtUnaryExpr.Op.SINGLETON == unary.getOp()); + SmtMultiArityExpr tupleExpression = (SmtMultiArityExpr) unary.getExpr(); + assert (SmtMultiArityExpr.Op.MKTUPLE == tupleExpression.getOp()); + List tuple = new ArrayList<>(); + + for (SmtExpr expr : tupleExpression.getExprs()) + { + if (expr instanceof IntConstant) + { + tuple.add(((IntConstant) expr).getValue()); + } + else if (expr instanceof UninterpretedConstant) + { + tuple.add(((UninterpretedConstant) expr).getName()); + } + else + { + throw new UnsupportedOperationException(expr.toString()); + } + } + return new HashSet<>(Collections.singletonList(tuple)); + } + SmtBinaryExpr binary = (SmtBinaryExpr) smtExpr; + Set> set = new HashSet<>(); + assert (binary.getOp() == SmtBinaryExpr.Op.UNION); + set.addAll(getRelation(binary.getA())); + set.addAll(getRelation(binary.getB())); + return set; + } + + + public static FunctionDefinition getFunctionDefinition(SmtModel smtModel, String name) + { + FunctionDefinition definition = (FunctionDefinition) smtModel + .getFunctions().stream() + .filter(f -> f.getName().equals(name)).findFirst().get(); + definition = smtModel.evaluateUninterpretedInt(definition); + return definition; + } + + public static String getFriendlyAtom(String uninterpretedConstant, String replacement) + { + return uninterpretedConstant.replaceFirst("@uc_Atom_", replacement); + } + + public static String getOriginalName(String name) + { + return name.replaceAll("\\|", ""); + } + + public static SmtExpr makeRelationFromDeclarations(List declarations) + { + List variables = declarations + .stream().map(v -> v.getVariable()).collect(Collectors.toList()); + return TranslatorUtils.makeRelation(variables); + } + + public static SmtExpr makeRelation(List smtExprs) + { + if (smtExprs.isEmpty()) + { + throw new RuntimeException("Empty list"); + } + + SmtExpr set = makeRelation(smtExprs.get(smtExprs.size() - 1)); + for (int i = smtExprs.size() - 2; i >= 0; i--) + { + SmtExpr smtExpr = smtExprs.get(i); + if (smtExpr.getSort() instanceof SetSort) + { + set = SmtBinaryExpr.Op.UNION.make(smtExpr, set); + } + else if (smtExpr.getSort() instanceof TupleSort) + { + set = SmtMultiArityExpr.Op.INSERT.make(smtExpr, set); + } + else + { + SmtExpr tuple = SmtMultiArityExpr.Op.MKTUPLE.make(smtExpr); + set = SmtMultiArityExpr.Op.INSERT.make(tuple, set); + } + } + return set; + } + + public static SmtExpr makeRelation(SmtExpr smtExpr) + { + if ((smtExpr.getSort() instanceof UninterpretedSort) || smtExpr.getSort() instanceof IntSort) + { + SmtMultiArityExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, smtExpr); + return SmtUnaryExpr.Op.SINGLETON.make(tuple); + } + else if (smtExpr.getSort() instanceof TupleSort) + { + return SmtUnaryExpr.Op.SINGLETON.make(smtExpr); + } + else + { + return smtExpr; + } + } + + public static List copySmtVariables(List smtVariables) + { + List newVariables = new ArrayList<>(); + for (SmtVariable smtVariable : smtVariables) + { + SmtVariable newVariable = new SmtVariable(TranslatorUtils.getFreshName(smtVariable.getSort()), smtVariable.getSort(), false); + if (smtVariable.getConstraint() != null) + { + SmtExpr newConstraint = smtVariable.getConstraint() + .substitute(smtVariable.getVariable(), newVariable.getVariable()); + newVariable.setConstraint(newConstraint); + } + newVariables.add(newVariable); + } + return newVariables; + } + + public static SmtExpr getVariablesConstraints(List smtVariables) + { + SmtExpr andExpr = BoolConstant.True; + for (SmtVariable smtVariable : smtVariables) + { + if (smtVariable.getConstraint() == null) + { + continue; + } + andExpr = SmtMultiArityExpr.Op.AND.make(andExpr, smtVariable.getConstraint()); + } + return andExpr; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/cvc4/Cvc4Process.java b/SMT-Extension/src/main/java/edu/uiowa/smt/cvc4/Cvc4Process.java new file mode 100644 index 000000000..ac4a103b5 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/cvc4/Cvc4Process.java @@ -0,0 +1,172 @@ +package edu.uiowa.smt.cvc4; + +import java.io.*; +import java.util.*; + + +public class Cvc4Process +{ + + public static final String OS = System.getProperty("os.name"); + public static final String SEP = File.separator; + public static final String BIN_PATH = ".." + SEP + "bin" + SEP; + + private Process process; + private Scanner scanner; + private OutputStream outputStream; + private StringBuilder smtCode; + + private Cvc4Process(Process process) + { + this.process = process; + this.scanner = new Scanner(process.getInputStream()); + this.outputStream = process.getOutputStream(); + this.smtCode = new StringBuilder(); + } + + public static Cvc4Process start() throws Exception + { + ProcessBuilder processBuilder = getProcessBuilder(); + Process process = processBuilder.start(); + return new Cvc4Process(process); + } + + private String runCVC4() throws Exception + { + ProcessBuilder processBuilder = getProcessBuilder(); + + String tempDirectory = System.getProperty("java.io.tmpdir"); + // save the smt file + File smtFile = File.createTempFile("tmp", ".smt2", new File(tempDirectory)); + Formatter formatter = new Formatter(smtFile); + formatter.format("%s", smtCode.toString()); + formatter.close(); + processBuilder.command().add(smtFile.getAbsolutePath()); + + // start the process + Process process = processBuilder.start(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) + { + stringBuilder.append(line); + stringBuilder.append("/n"); + } + process.destroyForcibly(); + return stringBuilder.toString(); + } + + private static ProcessBuilder getProcessBuilder() throws Exception + { + String cvc4; + + if (onWindows()) + { + cvc4 = BIN_PATH + "cvc4_win64.exe"; + } + else if (onMac()) + { + cvc4 = BIN_PATH + "cvc4_mac"; + } + else if (OS.startsWith("Linux")) + { + cvc4 = BIN_PATH + "cvc4_linux"; + } + else + { + throw new Exception("No CVC4 binary available for the OS: " + OS); + } + + File cvc4Binary = new File(cvc4); + + if (!cvc4Binary.exists()) + { + throw new Exception("CVC4 binary does not exist at: " + cvc4); + } + if (!cvc4Binary.canExecute()) + { + throw new Exception("CVC4 binary cannot be executed at: " + cvc4); + } + + ProcessBuilder processBuilder = new ProcessBuilder(); + List command = new ArrayList<>(); + + command.add(cvc4); + + // tell cvc4 the input language is smt2 + command.add("--lang"); + command.add("smtlib2.6"); + + processBuilder.command(command); + processBuilder.redirectErrorStream(true); + return processBuilder; + } + + + public String sendCommand(String command) throws IOException + { + outputStream.write((command + "\n").getBytes()); + smtCode.append(command + "\n"); + System.out.println(command); + try + { + outputStream.flush(); + } + catch (java.io.IOException ioException) + { + if (ioException.getMessage().toLowerCase().contains("pipe")) + { +// System.out.println(smtCode.toString()); + try + { + String error = runCVC4(); + throw new IOException(error); + } + catch (Exception exception) + { + exception.printStackTrace(); + } + + } + throw ioException; + } + return receiveOutput(); + } + + private String receiveOutput() throws IOException + { + String line = ""; + outputStream.write(("(echo success)\n").getBytes()); + outputStream.flush(); + + StringBuilder output = new StringBuilder(); + + while (scanner.hasNextLine()) + { + line = scanner.nextLine(); + + if (line.equals("success")) + { + return output.toString().trim(); + } + output.append(line).append("\n"); + } + return line; + } + + public void destroy() + { + process.destroyForcibly(); + } + + private static boolean onWindows() + { + return System.getProperty("os.name").toLowerCase(Locale.US).startsWith("windows"); + } + + private static boolean onMac() + { + return System.getProperty("mrj.version") != null || System.getProperty("os.name").toLowerCase(Locale.US).startsWith("mac "); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/ISmtRewriter.java b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/ISmtRewriter.java new file mode 100644 index 000000000..749e675a2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/ISmtRewriter.java @@ -0,0 +1,78 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.optimizer; + +import edu.uiowa.smt.smtAst.*; + +public interface ISmtRewriter +{ + SmtRewriteResult visit(SmtAst smtAst); + + SmtRewriteResult visit(Declaration declaration); + + SmtRewriteResult visit(SmtModel model); + + SmtRewriteResult visit(SmtScript script); + + SmtRewriteResult visit(SmtBinaryExpr expr); + + SmtRewriteResult visit(Sort sort); + + SmtRewriteResult visit(IntSort intSort); + + SmtRewriteResult visit(SmtQtExpr quantifiedExpression); + + SmtRewriteResult visit(RealSort realSort); + + SmtRewriteResult visit(SetSort setSort); + + SmtRewriteResult visit(StringSort stringSort); + + SmtRewriteResult visit(TupleSort tupleSort); + + SmtRewriteResult visit(SmtExpr smtExpr); + + SmtRewriteResult visit(SmtUnaryExpr unaryExpression); + + SmtRewriteResult visit(UninterpretedSort uninterpretedSort); + + SmtRewriteResult visit(IntConstant intConstant); + + SmtRewriteResult visit(Variable variable); + + SmtRewriteResult visit(FunctionDeclaration functionDeclaration); + + SmtRewriteResult visit(FunctionDefinition functionDefinition); + + SmtRewriteResult visit(BoolConstant booleanConstant); + + SmtRewriteResult visit(Assertion assertion); + + SmtRewriteResult visit(SmtMultiArityExpr expression); + + SmtRewriteResult visit(SmtCallExpr smtCallExpr); + + SmtRewriteResult visit(SmtVariable smtVariable); + + SmtRewriteResult visit(BoolSort boolSort); + + SmtRewriteResult visit(SmtLetExpr letExpression); + + SmtRewriteResult visit(SmtIteExpr iteExpression); + + SmtRewriteResult visit(UninterpretedConstant uninterpretedConstant); + + SmtRewriteResult visit(SmtSettings smtSettings); + + SmtRewriteResult visit(SmtValues smtValues); + + SmtRewriteResult visit(ExpressionValue expressionValue); + + SmtRewriteResult visit(SmtUnsatCore smtUnsatCore); +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriteResult.java b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriteResult.java new file mode 100644 index 000000000..a27c13999 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriteResult.java @@ -0,0 +1,28 @@ +package edu.uiowa.smt.optimizer; + +import edu.uiowa.smt.smtAst.SmtAst; + +public class SmtRewriteResult +{ + public Status status; + public SmtAst smtAst; + + private SmtRewriteResult(Status status, SmtAst smtAst) + { + this.status = status; + this.smtAst = smtAst; + } + + public enum Status + { + // rewriting is finished + Done, + // rewrite again + RewriteAgain; + + public SmtRewriteResult make(SmtAst smtAst) + { + return new SmtRewriteResult(this, smtAst); + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriter.java b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriter.java new file mode 100644 index 000000000..3f9c47487 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/optimizer/SmtRewriter.java @@ -0,0 +1,1502 @@ +package edu.uiowa.smt.optimizer; + +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SmtRewriter implements ISmtRewriter +{ + @Override + public SmtRewriteResult visit(SmtAst smtAst) + { + if (smtAst instanceof Assertion) + { + return visit((Assertion) smtAst); + } + else if (smtAst instanceof Declaration) + { + return visit((Declaration) smtAst); + } + else if (smtAst instanceof ExpressionValue) + { + return visit((ExpressionValue) smtAst); + } + else if (smtAst instanceof SmtExpr) + { + return visit((SmtExpr) smtAst); + } + else if (smtAst instanceof SmtScript) + { + return visit((SmtScript) smtAst); + } + else if (smtAst instanceof SmtModel) + { + return visit((SmtModel) smtAst); + } + else if (smtAst instanceof SmtSettings) + { + return visit((SmtSettings) smtAst); + } + else if (smtAst instanceof SmtUnsatCore) + { + return visit((SmtUnsatCore) smtAst); + } + else if (smtAst instanceof SmtValues) + { + return visit((SmtValues) smtAst); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtRewriteResult visit(Declaration declaration) + { + if (declaration instanceof FunctionDefinition) + { + return visit((FunctionDefinition) declaration); + } + else if (declaration instanceof FunctionDeclaration) + { + return visit((FunctionDeclaration) declaration); + } + else if (declaration instanceof SmtVariable) + { + return visit((SmtVariable) declaration); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtRewriteResult visit(SmtModel model) + { + return SmtRewriteResult.Status.Done.make(model); + } + + @Override + public SmtRewriteResult visit(SmtScript root) + { + root = optimizeHelper(root, root); + return SmtRewriteResult.Status.Done.make(root); + } + + public SmtScript optimizeHelper(SmtScript root, SmtScript optimizedScript) + { + optimizedScript = visitFunctionDefinitions(optimizedScript); + optimizedScript = visitAssertions(optimizedScript); + optimizedScript = removeTrivialAssertions(optimizedScript); + optimizedScript = removeUninterpretedIntIfNotUsed(root, optimizedScript); + List children = new ArrayList<>(); + children.addAll(optimizedScript.getChildren()); + optimizedScript.clearChildren(); + // optimize children as well + for (SmtScript child : children) + { + SmtScript optimizedChild = optimizeHelper(root, child); + optimizedScript.addChild(optimizedChild); + } + return optimizedScript; + } + + private SmtScript removeTrivialAssertions(SmtScript script) + { + List assertions = script.getAssertions() + .stream() + .filter(a -> !a.getSmtExpr().equals((BoolConstant.True))) + .collect(Collectors.toList()); + script.setAssertions(assertions); + + return script; + } + + public SmtRewriteResult removeTrivialTerms(SmtMultiArityExpr smtMultiArity) + { + List exprs = smtMultiArity.getExprs(); + SmtRewriteResult.Status status = SmtRewriteResult.Status.Done; + SmtExpr smtAst = smtMultiArity; + if (smtMultiArity.getOp() == SmtMultiArityExpr.Op.AND) + { + exprs = exprs.stream().filter(e -> !e.equals(BoolConstant.True)).collect(Collectors.toList()); + if (exprs.size() != smtMultiArity.getExprs().size()) + { + status = SmtRewriteResult.Status.RewriteAgain; + // (and) + if (exprs.isEmpty()) + { + smtAst = BoolConstant.True; + } + else if (exprs.size() == 1) + { + smtAst = exprs.get(0); + } + else + { + smtAst = SmtMultiArityExpr.Op.AND.make(exprs); + } + } + } + if (smtMultiArity.getOp() == SmtMultiArityExpr.Op.OR) + { + //(or true ...) + if (exprs.contains(BoolConstant.True)) + { + smtAst = BoolConstant.True; + status = SmtRewriteResult.Status.RewriteAgain; + } + } + + return status.make(smtAst); + } + + public SmtRewriteResult flattenNestedExprs(SmtMultiArityExpr smtMultiArity, SmtRewriteResult.Status status) + { + SmtExpr smtAst = smtMultiArity; + if (smtMultiArity.getOp() == SmtMultiArityExpr.Op.AND || + smtMultiArity.getOp() == SmtMultiArityExpr.Op.OR) + { + // Original: (and (and p q) ... ) + // Optimized: (and p q ...) + List exprs = new ArrayList<>(); + for (SmtExpr expr : smtMultiArity.getExprs()) + { + if (expr instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) expr).getOp() == smtMultiArity.getOp()) + { + exprs.addAll(((SmtMultiArityExpr) expr).getExprs()); + status = SmtRewriteResult.Status.RewriteAgain; + } + else + { + exprs.add(expr); + } + } + smtAst = smtMultiArity.getOp().make(exprs); + } + return status.make(smtAst); + } + + public SmtScript removeUninterpretedIntIfNotUsed(SmtScript root, SmtScript script) + { + if (!root.isUninterpretedIntUsed()) + { + script.removeSort(AbstractTranslator.uninterpretedInt); + + List uIntFunctions = AbstractTranslator.getUninterpretedIntFunctions(script); + script.removeFunctions(uIntFunctions); + + List uIntAssertions = AbstractTranslator.getUninterpretedIntAssertions(script); + script.removeAssertions(uIntAssertions); + } + return script; + } + + private SmtScript visitAssertions(SmtScript script) + { + List assertions = new ArrayList<>(); + + for (Assertion assertion : script.getAssertions()) + { + assertions.add((Assertion) (visit(assertion)).smtAst); + } + + script.setAssertions(assertions); + return script; + } + + private SmtScript visitFunctionDefinitions(SmtScript script) + { + List functions = new ArrayList<>(); + + for (FunctionDeclaration function : script.getFunctions()) + { + if (function instanceof FunctionDefinition) + { + functions.add((FunctionDefinition) visit((FunctionDefinition) function).smtAst); + } + else + { + functions.add(function); + } + } + + script.setFunctions(functions); + return script; + } + + private SmtRewriteResult optimizedTupleSelectZeroForUnaryTuples(SmtLetExpr letExpr) + { + // Original : (let ((x (mkTuple a))) (= ((_ tupSel 0) x) 5)) + // Optimized: (let ((x (mkTuple a))) (= (a 5)) + + SmtExpr zero = new IntConstant("0"); + + SmtRewriteResult bodyResult = visit(letExpr.getSmtExpr()); + SmtExpr optimizedBody = (SmtExpr) bodyResult.smtAst; + for (Map.Entry entry : letExpr.getLetVariables().entrySet()) + { + SmtVariable smtVariable = entry.getKey(); + SmtExpr expr = entry.getValue(); + + // check if the tuple has arity 1 + if (expr instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) expr).getOp() == SmtMultiArityExpr.Op.MKTUPLE && + ((SmtMultiArityExpr) expr).getExprs().size() == 1) + { + SmtMultiArityExpr makeTuple = (SmtMultiArityExpr) expr; + SmtExpr tupleSelect = SmtBinaryExpr.Op.TUPSEL.make(zero, smtVariable.getVariable()); + optimizedBody = optimizedBody.replace(tupleSelect, makeTuple.get(0)); + } + } + + SmtExpr optimizedLet = new SmtLetExpr(letExpr.getLetVariables(), optimizedBody); + return bodyResult.status.make(optimizedLet); + } + + @Override + public SmtRewriteResult visit(SmtBinaryExpr expr) + { + SmtRewriteResult resultA = visit(expr.getA()); + SmtRewriteResult resultB = visit(expr.getB()); + SmtExpr smtAst = expr.getOp().make((SmtExpr) resultA.smtAst, (SmtExpr) resultB.smtAst); + if (resultA.status == SmtRewriteResult.Status.Done || + resultB.status == SmtRewriteResult.Status.Done) + { + return SmtRewriteResult.Status.Done.make(smtAst); + } + else + { + return SmtRewriteResult.Status.RewriteAgain.make(smtAst); + } + } + + @Override + public SmtRewriteResult visit(Sort sort) + { + if (sort instanceof UninterpretedSort) + { + return visit((UninterpretedSort) sort); + } + else if (sort instanceof SetSort) + { + return visit((SetSort) sort); + } + else if (sort instanceof TupleSort) + { + return visit((TupleSort) sort); + } + else if (sort instanceof IntSort) + { + return visit((IntSort) sort); + } + else if (sort instanceof RealSort) + { + return visit((RealSort) sort); + } + else if (sort instanceof StringSort) + { + return visit((StringSort) sort); + } + else if (sort instanceof BoolSort) + { + return visit((BoolSort) sort); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtRewriteResult visit(IntSort intSort) + { + return SmtRewriteResult.Status.Done.make(intSort); + } + + @Override + public SmtRewriteResult visit(SmtQtExpr smtQtExpr) + { + SmtRewriteResult bodyResult = visit(smtQtExpr.getExpr()); + SmtQtExpr smtAst = smtQtExpr.getOp().make((SmtExpr) bodyResult.smtAst, smtQtExpr.getVariables()); + SmtRewriteResult result = optimizeTupleQuantifiers(smtAst); + if (result.status == SmtRewriteResult.Status.RewriteAgain) + { + return result; + } + return bodyResult.status.make(result.smtAst); + } + + public SmtRewriteResult optimizeTupleQuantifiers(SmtQtExpr smtQtExpr) + { + List declarations = new ArrayList<>(); + Map letVariables = new LinkedHashMap<>(); + for (SmtVariable variable : smtQtExpr.getVariables()) + { + if (variable.getSort() instanceof TupleSort) + { + List tupleSmtExprs = new ArrayList<>(); + // convert tuple quantifiers to uninterpreted quantifiers + TupleSort tupleSort = (TupleSort) variable.getSort(); + for (Sort sort : tupleSort.elementSorts) + { + SmtVariable declaration = new SmtVariable(TranslatorUtils.getFreshName(sort), sort, false); + declarations.add(declaration); + tupleSmtExprs.add(declaration.getVariable()); + } + SmtExpr tuple = SmtMultiArityExpr.Op.MKTUPLE.make(tupleSmtExprs); + letVariables.put(variable, tuple); + } + else + { + declarations.add(variable); + } + } + if (letVariables.size() > 0) + { + SmtExpr let = new SmtLetExpr(letVariables, smtQtExpr.getExpr()); + SmtExpr smtAst = smtQtExpr.getOp().make(let, declarations); + return SmtRewriteResult.Status.RewriteAgain.make(smtAst); + } + else + { + return SmtRewriteResult.Status.Done.make(smtQtExpr); + } + } + + @Override + public SmtRewriteResult visit(RealSort realSort) + { + return SmtRewriteResult.Status.Done.make(realSort); + } + + @Override + public SmtRewriteResult visit(SetSort setSort) + { + return SmtRewriteResult.Status.Done.make(setSort); + } + + @Override + public SmtRewriteResult visit(StringSort stringSort) + { + return SmtRewriteResult.Status.Done.make(stringSort); + } + + @Override + public SmtRewriteResult visit(TupleSort tupleSort) + { + return SmtRewriteResult.Status.Done.make(tupleSort); + } + + @Override + public SmtRewriteResult visit(SmtExpr smtExpr) + { + SmtRewriteResult rewriteResult; + if (smtExpr instanceof Variable) + { + rewriteResult = visit((Variable) smtExpr); + } + else if (smtExpr instanceof SmtUnaryExpr) + { + rewriteResult = visit((SmtUnaryExpr) smtExpr); + } + else if (smtExpr instanceof SmtBinaryExpr) + { + rewriteResult = visit((SmtBinaryExpr) smtExpr); + } + else if (smtExpr instanceof SmtMultiArityExpr) + { + rewriteResult = visit((SmtMultiArityExpr) smtExpr); + } + else if (smtExpr instanceof SmtQtExpr) + { + rewriteResult = visit((SmtQtExpr) smtExpr); + } + else if (smtExpr instanceof Sort) + { + rewriteResult = visit((Sort) smtExpr); + } + else if (smtExpr instanceof IntConstant) + { + rewriteResult = visit((IntConstant) smtExpr); + } + else if (smtExpr instanceof SmtCallExpr) + { + rewriteResult = visit((SmtCallExpr) smtExpr); + } + else if (smtExpr instanceof BoolConstant) + { + rewriteResult = visit((BoolConstant) smtExpr); + } + else if (smtExpr instanceof SmtLetExpr) + { + rewriteResult = visit((SmtLetExpr) smtExpr); + } + else if (smtExpr instanceof SmtIteExpr) + { + rewriteResult = visit((SmtIteExpr) smtExpr); + } + else if (smtExpr instanceof UninterpretedConstant) + { + rewriteResult = visit((UninterpretedConstant) smtExpr); + } + else + { + throw new UnsupportedOperationException(); + } + + if (rewriteResult.status == SmtRewriteResult.Status.Done) + { + return rewriteResult; + } + return visit((SmtExpr) rewriteResult.smtAst); + } + + @Override + public SmtRewriteResult visit(SmtUnaryExpr expr) + { + SmtRewriteResult result = visit(expr.getExpr()); + + SmtExpr smtAst = expr.getOp().make((SmtExpr) result.smtAst); + return result.status.make(smtAst); + } + + @Override + public SmtRewriteResult visit(UninterpretedSort uninterpretedSort) + { + return SmtRewriteResult.Status.Done.make(uninterpretedSort); + } + + @Override + public SmtRewriteResult visit(IntConstant intConstant) + { + return SmtRewriteResult.Status.Done.make(intConstant); + } + + @Override + public SmtRewriteResult visit(Variable variable) + { + return SmtRewriteResult.Status.Done.make(variable); + } + + @Override + public SmtRewriteResult visit(FunctionDeclaration functionDeclaration) + { + return SmtRewriteResult.Status.Done.make(functionDeclaration); + } + + @Override + public SmtRewriteResult visit(FunctionDefinition functionDefinition) + { + SmtRewriteResult bodyResult = visit(functionDefinition.getBody()); + functionDefinition.setBody((SmtExpr) bodyResult.smtAst); + return SmtRewriteResult.Status.Done.make(functionDefinition); + } + + @Override + public SmtRewriteResult visit(BoolConstant booleanConstant) + { + return SmtRewriteResult.Status.Done.make(booleanConstant); + } + + @Override + public SmtRewriteResult visit(Assertion assertion) + { + SmtRewriteResult result = visit(assertion.getSmtExpr()); + SmtExpr smtExpr = optimizeFunctionalRelation((SmtExpr) result.smtAst); + smtExpr = optimizeProductMultiplicity(smtExpr); + smtExpr = optimizeOneArrowAnyMultiplicity(smtExpr); + smtExpr = optimizeAnyArrowOneMultiplicity(smtExpr); + Assertion optimizedAssertion = new Assertion(assertion.getSymbolicName(), assertion.getComment(), smtExpr); + return SmtRewriteResult.Status.Done.make(optimizedAssertion); + } + + private SmtExpr optimizeFunctionalRelation(SmtExpr expr) + { + // change multiplicity translation for one-to-one binary function f: A -> B + // original: + // --------- + // (forall ((a Atom)) + // (let ((t (mkTuple a))) + // (=> + // (member t A) + // (let ((s (join (singleton t) f))) + // (and + // (member (choose s) B) + // (= (singleton (choose s)) s) + // + // optimized: + // --------- + // (and + // (forall ((x Atom) (y Atom) (z Atom)) + // (=> + // (and (member (mkTuple x y) f) (not (= y z))) + // (not (member (mkTuple x z) f)) + // + // (forall ((x Atom)) + // (=> + // (member (mkTuple x) A) + // (exists ((y Atom)) + // (and + // (member (mkTuple y) B + // (member (mkTuple x y) f) + // ) + + if (!(expr instanceof SmtQtExpr)) + { + return expr; + } + + SmtQtExpr smtQtExpr = (SmtQtExpr) expr; + if (smtQtExpr.getOp() != SmtQtExpr.Op.FORALL || smtQtExpr.getVariables().size() != 1) + { + return expr; + } + SmtExpr a = smtQtExpr.getVariables().get(0).getVariable(); + SmtExpr aTuple = SmtMultiArityExpr.Op.MKTUPLE.make(a); + if (!(smtQtExpr.getExpr() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let1 = (SmtLetExpr) smtQtExpr.getExpr(); + if (let1.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr t = let1.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr tExpr = let1.getLetVariables().values().stream().findFirst().get(); + if (!tExpr.equals(aTuple)) + { + return expr; + } + if (!(let1.getSmtExpr() instanceof SmtBinaryExpr)) + { + return expr; + } + SmtBinaryExpr implies = (SmtBinaryExpr) let1.getSmtExpr(); + if (implies.getOp() != SmtBinaryExpr.Op.IMPLIES) + { + return expr; + } + if (!(implies.getA() instanceof SmtBinaryExpr && implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtBinaryExpr operand1 = (SmtBinaryExpr) implies.getA(); + if (!(operand1.getOp() == SmtBinaryExpr.Op.MEMBER && operand1.getA().equals(t))) + { + return expr; + } + SmtExpr setA = operand1.getB(); + if (!(implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let2 = (SmtLetExpr) implies.getB(); + if (let2.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr s = let2.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr sExpr = let2.getLetVariables().values().stream().findFirst().get(); + if (!(sExpr instanceof SmtBinaryExpr)) + { + return sExpr; + } + SmtExpr f = ((SmtBinaryExpr) sExpr).getB(); + SmtExpr singletonT = SmtUnaryExpr.Op.SINGLETON.make(t); + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(singletonT, f); + if (!sExpr.equals(join)) + { + return expr; + } + + if (!(let2.getSmtExpr() instanceof SmtMultiArityExpr)) + { + return expr; + } + + SmtMultiArityExpr and1 = (SmtMultiArityExpr) let2.getSmtExpr(); + + if (!(and1.getOp() == SmtMultiArityExpr.Op.AND && and1.getExprs().size() == 2 && + and1.get(0) instanceof SmtBinaryExpr + )) + { + return expr; + } + + SmtExpr choose = SmtUnaryExpr.Op.CHOOSE.make(s); + operand1 = (SmtBinaryExpr) and1.get(0); + if (!(operand1.getOp() == SmtBinaryExpr.Op.MEMBER && operand1.getA().equals(choose))) + { + return expr; + } + + SmtBinaryExpr operand2 = (SmtBinaryExpr) and1.get(1); + SmtExpr singletonChoose = SmtUnaryExpr.Op.SINGLETON.make(choose); + SmtExpr equal1 = SmtBinaryExpr.Op.EQ.make(singletonChoose, s); + if (!operand2.equals(equal1)) + { + return expr; + } + + SmtExpr setB = operand1.getB(); + TupleSort tupleSortA = (TupleSort) ((SetSort) setA.getSort()).elementSort; + TupleSort tupleSortB = (TupleSort) ((SetSort) setB.getSort()).elementSort; + if (tupleSortA.elementSorts.size() != 1 || tupleSortB.elementSorts.size() != 1) + { + return expr; + } + Sort elementSortA = tupleSortA.elementSorts.get(0); + Sort elementSortB = tupleSortB.elementSorts.get(0); + + SmtVariable x = new SmtVariable("x", elementSortA, false); + SmtVariable y = new SmtVariable("y", elementSortB, false); + SmtVariable z = new SmtVariable("z", elementSortB, false); + + SmtExpr xTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable()); + SmtExpr yTuple = SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable()); + SmtExpr xyTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), y.getVariable()); + SmtExpr xzTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), z.getVariable()); + + SmtExpr xyMember = SmtBinaryExpr.Op.MEMBER.make(xyTuple, f); + SmtExpr equal = SmtBinaryExpr.Op.EQ.make(y.getVariable(), z.getVariable()); + SmtExpr notEqual = SmtUnaryExpr.Op.NOT.make(equal); + SmtExpr and2 = SmtMultiArityExpr.Op.AND.make(xyMember, notEqual); + SmtExpr xzMember = SmtBinaryExpr.Op.MEMBER.make(xzTuple, f); + SmtExpr xzNotMember = SmtUnaryExpr.Op.NOT.make(xzMember); + SmtExpr implies2 = SmtBinaryExpr.Op.IMPLIES.make(and2, xzNotMember); + SmtExpr forall1 = SmtQtExpr.Op.FORALL.make(implies2, x, y, z); + + SmtExpr xMember = SmtBinaryExpr.Op.MEMBER.make(xTuple, setA); + SmtExpr yMember = SmtBinaryExpr.Op.MEMBER.make(yTuple, setB); + SmtExpr and3 = SmtMultiArityExpr.Op.AND.make(yMember, xyMember); + SmtExpr exist = SmtQtExpr.Op.EXISTS.make(and3, y); + SmtExpr implies3 = SmtBinaryExpr.Op.IMPLIES.make(xMember, exist); + + SmtExpr forall2 = SmtQtExpr.Op.FORALL.make(implies3, x); + + SmtExpr and4 = SmtMultiArityExpr.Op.AND.make(forall1, forall2); + return and4; + } + + private SmtExpr optimizeProductMultiplicity(SmtExpr expr) + { + // change multiplicity translation for subset relations f: A -> B -> ... + // original: + // --------- + // ; field (A <: g) multiplicity + //(assert + // (forall ((a Atom)) + // (let ((t (mkTuple a))) + // (=> + // (member t |A |) + // (let ( (s (join (singleton t) f ))) ; s = {t} . f + // (subset s (product B (product C D)))))))) ; s : A x B x C x D + + // optimized: + // --------- + // (assert true) + // We return true here because we already generate the assertion below separately + // ; field f subset + //(assert (subset f (product A (product B (product C D)))))) + + if (!(expr instanceof SmtQtExpr)) + { + return expr; + } + + SmtQtExpr smtQtExpr = (SmtQtExpr) expr; + if (smtQtExpr.getOp() != SmtQtExpr.Op.FORALL || smtQtExpr.getVariables().size() != 1) + { + return expr; + } + SmtExpr a = smtQtExpr.getVariables().get(0).getVariable(); + SmtExpr aTuple = SmtMultiArityExpr.Op.MKTUPLE.make(a); + if (!(smtQtExpr.getExpr() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let1 = (SmtLetExpr) smtQtExpr.getExpr(); + if (let1.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr t = let1.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr tExpr = let1.getLetVariables().values().stream().findFirst().get(); + if (!tExpr.equals(aTuple)) + { + return expr; + } + if (!(let1.getSmtExpr() instanceof SmtBinaryExpr)) + { + return expr; + } + SmtBinaryExpr implies = (SmtBinaryExpr) let1.getSmtExpr(); + if (implies.getOp() != SmtBinaryExpr.Op.IMPLIES) + { + return expr; + } + if (!(implies.getA() instanceof SmtBinaryExpr && implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtBinaryExpr operand1 = (SmtBinaryExpr) implies.getA(); + if (!(operand1.getOp() == SmtBinaryExpr.Op.MEMBER && operand1.getA().equals(t))) + { + return expr; + } + SmtExpr setA = operand1.getB(); + if (!(implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let2 = (SmtLetExpr) implies.getB(); + if (let2.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr s = let2.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr sExpr = let2.getLetVariables().values().stream().findFirst().get(); + if (!(sExpr instanceof SmtBinaryExpr)) + { + return sExpr; + } + SmtExpr f = ((SmtBinaryExpr) sExpr).getB(); + SmtExpr singletonT = SmtUnaryExpr.Op.SINGLETON.make(t); + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(singletonT, f); + if (!sExpr.equals(join)) + { + return expr; + } + + if (!(let2.getSmtExpr() instanceof SmtBinaryExpr && + ((SmtBinaryExpr) let2.getSmtExpr()).getOp() == SmtBinaryExpr.Op.SUBSET)) + { + return expr; + } + + SmtBinaryExpr subset = (SmtBinaryExpr) let2.getSmtExpr(); + + if (!(s.equals(subset.getA()) && subset.getB() instanceof SmtBinaryExpr)) + { + return expr; + } + + SmtBinaryExpr product = (SmtBinaryExpr) subset.getB(); + if (!isProductExpr(product)) + { + return expr; + } + + return BoolConstant.True; + } + + private boolean isProductExpr(SmtExpr expr) + { + // returns true if expr has the form (product A (product B (product C (...)))) + // where A, B, C are variables + if (expr instanceof Variable) + { + return true; + } + if (expr instanceof SmtBinaryExpr) + { + SmtBinaryExpr binaryExpr = (SmtBinaryExpr) expr; + if (binaryExpr.getOp() != SmtBinaryExpr.Op.PRODUCT) + { + return false; + } + return isProductExpr(binaryExpr.getA()) && isProductExpr(binaryExpr.getB()); + } + return false; + } + + private SmtExpr optimizeOneArrowAnyMultiplicity(SmtExpr expr) + { + // change multiplicity translation for sig A {f: B one -> C} + // original: + // --------- + // + //(assert + // (forall ((x Atom)) + // (let ((xTuple (mkTuple x))) + // (=> (member xTuple A) + // (let ((s (join (singleton xTuple) f))) + // (and (subset s (product B C)) + // (forall ((y Atom)) + // (let ((yTuple (mkTuple y))) + // (=> (member yTuple C) + // (exists ((z Atom)) + // (let ((zTuple (mkTuple z))) + // (and (member zTuple B) + // (member (mkTuple z y) s) + // (forall ((w Atom)) + // (let ((wTuple (mkTuple w))) + // (=> + // (and (member wTuple B) (not (= wTuple zTuple))) + // (not (member (mkTuple w y) s))))))))))))))))) + + // optimized: + // --------- + // (assert + // (forall ((x Atom)) + // (=> (member (mkTuple x) A) + // (forall ((y Atom)) + // (=> + // (member (mkTuple y) C) + // (exists (z Atom)) + // (and + // (member (mkTuple z) B) + // (member (mkTuple x z y) f) + // (forall ((w Atom)) + // (=> (not (= w z)) + // (not (member (mkTuple x w y) f)) + // ) + // )))) + + if (!(expr instanceof SmtQtExpr)) + { + return expr; + } + + SmtQtExpr smtQtExpr = (SmtQtExpr) expr; + if (smtQtExpr.getOp() != SmtQtExpr.Op.FORALL || smtQtExpr.getVariables().size() != 1) + { + return expr; + } + SmtVariable x = smtQtExpr.getVariables().get(0); + SmtExpr xTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable()); + if (!(smtQtExpr.getExpr() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let1 = (SmtLetExpr) smtQtExpr.getExpr(); + if (let1.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr t = let1.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr tExpr = let1.getLetVariables().values().stream().findFirst().get(); + if (!tExpr.equals(xTuple)) + { + return expr; + } + if (!(let1.getSmtExpr() instanceof SmtBinaryExpr)) + { + return expr; + } + SmtBinaryExpr implies = (SmtBinaryExpr) let1.getSmtExpr(); + if (implies.getOp() != SmtBinaryExpr.Op.IMPLIES) + { + return expr; + } + if (!(implies.getA() instanceof SmtBinaryExpr && implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtBinaryExpr operand1 = (SmtBinaryExpr) implies.getA(); + if (!(operand1.getOp() == SmtBinaryExpr.Op.MEMBER && operand1.getA().equals(t))) + { + return expr; + } + SmtExpr setA = operand1.getB(); + if (!(implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let2 = (SmtLetExpr) implies.getB(); + if (let2.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr s = let2.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr sExpr = let2.getLetVariables().values().stream().findFirst().get(); + if (!(sExpr instanceof SmtBinaryExpr)) + { + return sExpr; + } + SmtExpr f = ((SmtBinaryExpr) sExpr).getB(); + SmtExpr singletonT = SmtUnaryExpr.Op.SINGLETON.make(t); + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(singletonT, f); + if (!sExpr.equals(join)) + { + return expr; + } + + if (!(let2.getSmtExpr() instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) let2.getSmtExpr()).getOp() == SmtMultiArityExpr.Op.AND)) + { + return expr; + } + + SmtMultiArityExpr and1 = (SmtMultiArityExpr) let2.getSmtExpr(); + if (and1.getExprs().size() != 2) + { + return expr; + } + SmtExpr subset = and1.get(0); + SmtExpr forall1 = and1.get(1); + if (!(subset instanceof SmtBinaryExpr) || ((SmtBinaryExpr) subset).getOp() != SmtBinaryExpr.Op.SUBSET) + { + return expr; + } + if (!((SmtBinaryExpr) subset).getA().equals(s)) + { + return expr; + } + + if (!(((SmtBinaryExpr) subset).getB() instanceof SmtBinaryExpr)) + { + return expr; + } + + SmtBinaryExpr product = (SmtBinaryExpr) ((SmtBinaryExpr) subset).getB(); + if (product.getOp() != SmtBinaryExpr.Op.PRODUCT) + { + return expr; + } + if (!(product.getA() instanceof Variable && product.getB() instanceof Variable)) + { + return expr; + } + + SmtExpr setB = product.getA(); + SmtExpr setC = product.getB(); + + if (!(forall1 instanceof SmtQtExpr && ((SmtQtExpr) forall1).getOp() == SmtQtExpr.Op.FORALL)) + { + return expr; + } + + if (!(((SmtQtExpr) forall1).getVariables().size() == 1 && + ((SmtQtExpr) forall1).getExpr() instanceof SmtLetExpr)) + { + return expr; + } + + SmtLetExpr let3 = (SmtLetExpr) ((SmtQtExpr) forall1).getExpr(); + if (let3.getLetVariables().size() != 1) + { + return expr; + } + SmtVariable y = ((SmtQtExpr) forall1).getVariables().get(0); + Map.Entry entry1 = let3.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry1.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable()))) + { + return expr; + } + if (!(let3.getSmtExpr() instanceof SmtBinaryExpr && + ((SmtBinaryExpr) let3.getSmtExpr()).getOp() == SmtBinaryExpr.Op.IMPLIES)) + { + return expr; + } + + SmtBinaryExpr implies1 = (SmtBinaryExpr) let3.getSmtExpr(); + + if (!implies1.getA().equals(SmtBinaryExpr.Op.MEMBER.make(entry1.getKey().getVariable(), setC))) + { + return expr; + } + + if (!(implies1.getB() instanceof SmtQtExpr && + ((SmtQtExpr) implies1.getB()).getOp() == SmtQtExpr.Op.EXISTS && + ((SmtQtExpr) implies1.getB()).getVariables().size() == 1 && + ((SmtQtExpr) implies1.getB()).getExpr() instanceof SmtLetExpr)) + { + return expr; + } + + + SmtVariable z = ((SmtQtExpr) implies1.getB()).getVariables().get(0); + + SmtLetExpr let4 = (SmtLetExpr) ((SmtQtExpr) implies1.getB()).getExpr(); + Map.Entry entry2 = let4.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry2.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(z.getVariable()))) + { + return expr; + } + SmtExpr zTuple = entry2.getKey().getVariable(); + if (!(let4.getSmtExpr() instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) let4.getSmtExpr()).getOp() == SmtMultiArityExpr.Op.AND && + ((SmtMultiArityExpr) let4.getSmtExpr()).getExprs().size() == 3)) + { + return expr; + } + SmtMultiArityExpr and2 = (SmtMultiArityExpr) let4.getSmtExpr(); + SmtExpr zyTuple = SmtMultiArityExpr.Op.MKTUPLE.make(z.getVariable(), y.getVariable()); + + if (!(and2.get(0).equals(SmtBinaryExpr.Op.MEMBER.make(zTuple, setB)) && + and2.get(1).equals(SmtBinaryExpr.Op.MEMBER.make(zyTuple, s)) && + and2.get(2) instanceof SmtQtExpr && + ((SmtQtExpr) and2.get(2)).getOp() == SmtQtExpr.Op.FORALL && + ((SmtQtExpr) and2.get(2)).getVariables().size() == 1 && + ((SmtQtExpr) and2.get(2)).getExpr() instanceof SmtLetExpr && + ((SmtLetExpr) ((SmtQtExpr) and2.get(2)).getExpr()).getLetVariables().size() == 1 + )) + { + return expr; + } + + SmtQtExpr forall2 = (SmtQtExpr) and2.get(2); + SmtVariable w = forall2.getVariables().get(0); + SmtLetExpr let5 = (SmtLetExpr) ((SmtQtExpr) and2.get(2)).getExpr(); + + Map.Entry entry3 = let5.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry3.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(w.getVariable()))) + { + return expr; + } + + SmtExpr wTuple = entry3.getKey().getVariable(); + SmtExpr and3 = SmtMultiArityExpr.Op.AND.make( + SmtBinaryExpr.Op.MEMBER.make(wTuple, setB), + SmtUnaryExpr.Op.NOT.make(SmtBinaryExpr.Op.EQ.make(wTuple, zTuple))); + + SmtExpr wyTuple = SmtMultiArityExpr.Op.MKTUPLE.make(w.getVariable(), y.getVariable()); + + SmtExpr not = SmtUnaryExpr.Op.NOT.make(SmtBinaryExpr.Op.MEMBER.make(wyTuple, s)); + SmtExpr implies2 = SmtBinaryExpr.Op.IMPLIES.make(and3, not); + if (!let5.getSmtExpr().equals(implies2)) + { + return expr; + } + + x = new SmtVariable("x", x.getSort(), false); + y = new SmtVariable("y", y.getSort(), false); + z = new SmtVariable("z", z.getSort(), false); + w = new SmtVariable("w", w.getSort(), false); + + xTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable()); + SmtExpr yTuple = SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable()); + zTuple = SmtMultiArityExpr.Op.MKTUPLE.make(z.getVariable()); + wTuple = SmtMultiArityExpr.Op.MKTUPLE.make(w.getVariable()); + + SmtExpr xzyTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), z.getVariable(), y.getVariable()); + SmtExpr xwyTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), w.getVariable(), y.getVariable()); + + SmtExpr xMember = SmtBinaryExpr.Op.MEMBER.make(xTuple, setA); + SmtExpr xzyMember = SmtBinaryExpr.Op.MEMBER.make(xzyTuple, f); +// SmtExpr exists1 = SmtQtExpr.Op.EXISTS.make(xzyMember, y, z); +// SmtExpr and4 = SmtMultiArityExpr.Op.AND.make(xMember, exists1); + + + SmtExpr yMember = SmtBinaryExpr.Op.MEMBER.make(yTuple, setC); + SmtExpr zMember = SmtBinaryExpr.Op.MEMBER.make(zTuple, setB); + SmtExpr xwyMember = SmtBinaryExpr.Op.MEMBER.make(xwyTuple, f); + SmtExpr xwyNotMember = SmtUnaryExpr.Op.NOT.make(xwyMember); + + SmtExpr wzEqual = SmtBinaryExpr.Op.EQ.make(w.getVariable(), z.getVariable()); + SmtExpr wzNotEqual = SmtUnaryExpr.Op.NOT.make(wzEqual); + SmtExpr implies3 = SmtBinaryExpr.Op.IMPLIES.make(wzNotEqual, xwyNotMember); + SmtExpr forall3 = SmtQtExpr.Op.FORALL.make(implies3, w); + SmtExpr and5 = SmtMultiArityExpr.Op.AND.make(zMember, xzyMember, forall3); + SmtExpr exists2 = SmtQtExpr.Op.EXISTS.make(and5, z); + + SmtExpr implies4 = SmtBinaryExpr.Op.IMPLIES.make(yMember, exists2); + SmtExpr forall4 = SmtQtExpr.Op.FORALL.make(implies4, y); + + SmtExpr implies5 = SmtBinaryExpr.Op.IMPLIES.make(xMember, forall4); + + SmtExpr forall6 = SmtQtExpr.Op.FORALL.make(implies5, x); + + return forall6; + } + + private SmtExpr optimizeAnyArrowOneMultiplicity(SmtExpr expr) + { + // change multiplicity translation for sig A {f: B one -> C} + // original: + // --------- + // + //(assert + // (forall ((x Atom)) + // (let ((xTuple (mkTuple x))) + // (=> (member xTuple A) + // (let ((s (join (singleton xTuple) f))) + // (and (subset s (product B C)) + // (forall ((y Atom)) + // (let ((yTuple (mkTuple y))) + // (=> (member yTuple B) + // (exists ((z Atom)) + // (let ((zTuple (mkTuple z))) + // (and (member zTuple C) + // (member (mkTuple y z) s) + // (forall ((w Atom)) + // (let ((wTuple (mkTuple w))) + // (=> + // (and (member wTuple C) (not (= wTuple zTuple))) + // (not (member (mkTuple y w) s))))))))))))))))) + + // optimized: + // --------- + // (assert + // (forall ((x Atom)) + // (=> (member (mkTuple x) A) + // (forall ((y Atom)) + // (=> + // (member (mkTuple y) B) + // (exists (z Atom)) + // (and + // (member (mkTuple z) C) + // (member (mkTuple x y z) f) + // (forall ((w Atom)) + // (=> (not (= w z)) + // (not (member (mkTuple x y w) f)) + // ) + // )))) + + if (!(expr instanceof SmtQtExpr)) + { + return expr; + } + + SmtQtExpr smtQtExpr = (SmtQtExpr) expr; + if (smtQtExpr.getOp() != SmtQtExpr.Op.FORALL || smtQtExpr.getVariables().size() != 1) + { + return expr; + } + SmtVariable x = smtQtExpr.getVariables().get(0); + SmtExpr xTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable()); + if (!(smtQtExpr.getExpr() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let1 = (SmtLetExpr) smtQtExpr.getExpr(); + if (let1.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr t = let1.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr tExpr = let1.getLetVariables().values().stream().findFirst().get(); + if (!tExpr.equals(xTuple)) + { + return expr; + } + if (!(let1.getSmtExpr() instanceof SmtBinaryExpr)) + { + return expr; + } + SmtBinaryExpr implies = (SmtBinaryExpr) let1.getSmtExpr(); + if (implies.getOp() != SmtBinaryExpr.Op.IMPLIES) + { + return expr; + } + if (!(implies.getA() instanceof SmtBinaryExpr && implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtBinaryExpr operand1 = (SmtBinaryExpr) implies.getA(); + if (!(operand1.getOp() == SmtBinaryExpr.Op.MEMBER && operand1.getA().equals(t))) + { + return expr; + } + SmtExpr setA = operand1.getB(); + if (!(implies.getB() instanceof SmtLetExpr)) + { + return expr; + } + SmtLetExpr let2 = (SmtLetExpr) implies.getB(); + if (let2.getLetVariables().size() != 1) + { + return expr; + } + SmtExpr s = let2.getLetVariables().keySet().stream().findFirst().get().getVariable(); + SmtExpr sExpr = let2.getLetVariables().values().stream().findFirst().get(); + if (!(sExpr instanceof SmtBinaryExpr)) + { + return sExpr; + } + SmtExpr f = ((SmtBinaryExpr) sExpr).getB(); + SmtExpr singletonT = SmtUnaryExpr.Op.SINGLETON.make(t); + SmtExpr join = SmtBinaryExpr.Op.JOIN.make(singletonT, f); + if (!sExpr.equals(join)) + { + return expr; + } + + if (!(let2.getSmtExpr() instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) let2.getSmtExpr()).getOp() == SmtMultiArityExpr.Op.AND)) + { + return expr; + } + + SmtMultiArityExpr and1 = (SmtMultiArityExpr) let2.getSmtExpr(); + if (and1.getExprs().size() != 2) + { + return expr; + } + SmtExpr subset = and1.get(0); + SmtExpr forall1 = and1.get(1); + if (!(subset instanceof SmtBinaryExpr) || ((SmtBinaryExpr) subset).getOp() != SmtBinaryExpr.Op.SUBSET) + { + return expr; + } + if (!((SmtBinaryExpr) subset).getA().equals(s)) + { + return expr; + } + + if (!(((SmtBinaryExpr) subset).getB() instanceof SmtBinaryExpr)) + { + return expr; + } + + SmtBinaryExpr product = (SmtBinaryExpr) ((SmtBinaryExpr) subset).getB(); + if (product.getOp() != SmtBinaryExpr.Op.PRODUCT) + { + return expr; + } + if (!(product.getA() instanceof Variable && product.getB() instanceof Variable)) + { + return expr; + } + + SmtExpr setB = product.getA(); + SmtExpr setC = product.getB(); + + if (!(forall1 instanceof SmtQtExpr && ((SmtQtExpr) forall1).getOp() == SmtQtExpr.Op.FORALL)) + { + return expr; + } + + if (!(((SmtQtExpr) forall1).getVariables().size() == 1 && + ((SmtQtExpr) forall1).getExpr() instanceof SmtLetExpr)) + { + return expr; + } + + SmtLetExpr let3 = (SmtLetExpr) ((SmtQtExpr) forall1).getExpr(); + if (let3.getLetVariables().size() != 1) + { + return expr; + } + SmtVariable y = ((SmtQtExpr) forall1).getVariables().get(0); + Map.Entry entry1 = let3.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry1.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable()))) + { + return expr; + } + if (!(let3.getSmtExpr() instanceof SmtBinaryExpr && + ((SmtBinaryExpr) let3.getSmtExpr()).getOp() == SmtBinaryExpr.Op.IMPLIES)) + { + return expr; + } + + SmtBinaryExpr implies1 = (SmtBinaryExpr) let3.getSmtExpr(); + + if (!implies1.getA().equals(SmtBinaryExpr.Op.MEMBER.make(entry1.getKey().getVariable(), setB))) + { + return expr; + } + + if (!(implies1.getB() instanceof SmtQtExpr && + ((SmtQtExpr) implies1.getB()).getOp() == SmtQtExpr.Op.EXISTS && + ((SmtQtExpr) implies1.getB()).getVariables().size() == 1 && + ((SmtQtExpr) implies1.getB()).getExpr() instanceof SmtLetExpr)) + { + return expr; + } + + + SmtVariable z = ((SmtQtExpr) implies1.getB()).getVariables().get(0); + + SmtLetExpr let4 = (SmtLetExpr) ((SmtQtExpr) implies1.getB()).getExpr(); + Map.Entry entry2 = let4.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry2.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(z.getVariable()))) + { + return expr; + } + SmtExpr zTuple = entry2.getKey().getVariable(); + if (!(let4.getSmtExpr() instanceof SmtMultiArityExpr && + ((SmtMultiArityExpr) let4.getSmtExpr()).getOp() == SmtMultiArityExpr.Op.AND && + ((SmtMultiArityExpr) let4.getSmtExpr()).getExprs().size() == 3)) + { + return expr; + } + SmtMultiArityExpr and2 = (SmtMultiArityExpr) let4.getSmtExpr(); + SmtExpr yzTuple = SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable(), z.getVariable()); + + if (!(and2.get(0).equals(SmtBinaryExpr.Op.MEMBER.make(zTuple, setC)) && + and2.get(1).equals(SmtBinaryExpr.Op.MEMBER.make(yzTuple, s)) && + and2.get(2) instanceof SmtQtExpr && + ((SmtQtExpr) and2.get(2)).getOp() == SmtQtExpr.Op.FORALL && + ((SmtQtExpr) and2.get(2)).getVariables().size() == 1 && + ((SmtQtExpr) and2.get(2)).getExpr() instanceof SmtLetExpr && + ((SmtLetExpr) ((SmtQtExpr) and2.get(2)).getExpr()).getLetVariables().size() == 1 + )) + { + return expr; + } + + SmtQtExpr forall2 = (SmtQtExpr) and2.get(2); + SmtVariable w = forall2.getVariables().get(0); + SmtLetExpr let5 = (SmtLetExpr) ((SmtQtExpr) and2.get(2)).getExpr(); + + Map.Entry entry3 = let5.getLetVariables().entrySet().stream().findFirst().get(); + if (!entry3.getValue().equals(SmtMultiArityExpr.Op.MKTUPLE.make(w.getVariable()))) + { + return expr; + } + + SmtExpr wTuple = entry3.getKey().getVariable(); + SmtExpr and3 = SmtMultiArityExpr.Op.AND.make( + SmtBinaryExpr.Op.MEMBER.make(wTuple, setC), + SmtUnaryExpr.Op.NOT.make(SmtBinaryExpr.Op.EQ.make(wTuple, zTuple))); + + SmtExpr ywTuple = SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable(), w.getVariable()); + + SmtExpr not = SmtUnaryExpr.Op.NOT.make(SmtBinaryExpr.Op.MEMBER.make(ywTuple, s)); + SmtExpr implies2 = SmtBinaryExpr.Op.IMPLIES.make(and3, not); + if (!let5.getSmtExpr().equals(implies2)) + { + return expr; + } + + x = new SmtVariable("x", x.getSort(), false); + y = new SmtVariable("y", y.getSort(), false); + z = new SmtVariable("z", z.getSort(), false); + w = new SmtVariable("w", w.getSort(), false); + + xTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable()); + SmtExpr yTuple = SmtMultiArityExpr.Op.MKTUPLE.make(y.getVariable()); + zTuple = SmtMultiArityExpr.Op.MKTUPLE.make(z.getVariable()); + wTuple = SmtMultiArityExpr.Op.MKTUPLE.make(w.getVariable()); + + SmtExpr xyzTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), y.getVariable(), z.getVariable()); + SmtExpr xywTuple = SmtMultiArityExpr.Op.MKTUPLE.make(x.getVariable(), y.getVariable(), w.getVariable()); + + SmtExpr xMember = SmtBinaryExpr.Op.MEMBER.make(xTuple, setA); + SmtExpr xyzMember = SmtBinaryExpr.Op.MEMBER.make(xyzTuple, f); + + SmtExpr yMember = SmtBinaryExpr.Op.MEMBER.make(yTuple, setB); + SmtExpr zMember = SmtBinaryExpr.Op.MEMBER.make(zTuple, setC); + SmtExpr xywMember = SmtBinaryExpr.Op.MEMBER.make(xywTuple, f); + SmtExpr xywNotMember = SmtUnaryExpr.Op.NOT.make(xywMember); + + SmtExpr wzEqual = SmtBinaryExpr.Op.EQ.make(w.getVariable(), z.getVariable()); + SmtExpr wzNotEqual = SmtUnaryExpr.Op.NOT.make(wzEqual); + SmtExpr implies3 = SmtBinaryExpr.Op.IMPLIES.make(wzNotEqual, xywNotMember); + SmtExpr forall3 = SmtQtExpr.Op.FORALL.make(implies3, w); + SmtExpr and5 = SmtMultiArityExpr.Op.AND.make(zMember, xyzMember, forall3); + SmtExpr exists2 = SmtQtExpr.Op.EXISTS.make(and5, z); + + SmtExpr implies4 = SmtBinaryExpr.Op.IMPLIES.make(yMember, exists2); + SmtExpr forall4 = SmtQtExpr.Op.FORALL.make(implies4, y); + + SmtExpr implies5 = SmtBinaryExpr.Op.IMPLIES.make(xMember, forall4); + + SmtExpr forall6 = SmtQtExpr.Op.FORALL.make(implies5, x); + + return forall6; + } + + @Override + public SmtRewriteResult visit(SmtMultiArityExpr original) + { + List results = new ArrayList<>(); + for (SmtExpr expr : original.getExprs()) + { + SmtRewriteResult exprResult = visit(expr); + results.add(exprResult); + } + List exprs = results.stream() + .map(r -> (SmtExpr) r.smtAst) + .collect(Collectors.toList()); + + SmtMultiArityExpr multiArityExpr = original.getOp().make(exprs); + SmtRewriteResult result = removeTrivialTerms(multiArityExpr); + if (result.smtAst instanceof SmtMultiArityExpr) + { + result = flattenNestedExprs((SmtMultiArityExpr) result.smtAst, result.status); + } + return result; + } + + @Override + public SmtRewriteResult visit(SmtCallExpr smtCallExpr) + { + List results = new ArrayList<>(); + + for (SmtExpr expr : smtCallExpr.getArguments()) + { + SmtRewriteResult exprResult = visit(expr); + results.add(exprResult); + } + + List exprs = results.stream() + .map(r -> (SmtExpr) r.smtAst) + .collect(Collectors.toList()); + SmtExpr smtAst = new SmtCallExpr(smtCallExpr.getFunction(), exprs); + return SmtRewriteResult.Status.Done.make(smtAst); + } + + @Override + public SmtRewriteResult visit(SmtVariable smtVariable) + { + return SmtRewriteResult.Status.Done.make(smtVariable); + } + + @Override + public SmtRewriteResult visit(BoolSort boolSort) + { + return SmtRewriteResult.Status.Done.make(boolSort); + } + + @Override + public SmtRewriteResult visit(SmtLetExpr smtLetExpr) + { + return optimizedTupleSelectZeroForUnaryTuples(smtLetExpr); + } + + @Override + public SmtRewriteResult visit(SmtIteExpr ite) + { + SmtRewriteResult conditionResult = visit(ite.getCondExpr()); + SmtRewriteResult thenResult = visit(ite.getThenExpr()); + SmtRewriteResult elseResult = visit(ite.getElseExpr()); + SmtExpr smtAst = new SmtIteExpr((SmtExpr) conditionResult.smtAst, + (SmtExpr) thenResult.smtAst, + (SmtExpr) elseResult.smtAst); + return SmtRewriteResult.Status.Done.make(smtAst); + } + + @Override + public SmtRewriteResult visit(UninterpretedConstant uninterpretedConstant) + { + return SmtRewriteResult.Status.Done.make(uninterpretedConstant); + } + + @Override + public SmtRewriteResult visit(SmtSettings smtSettings) + { + return SmtRewriteResult.Status.Done.make(smtSettings); + } + + @Override + public SmtRewriteResult visit(SmtValues smtValues) + { + return SmtRewriteResult.Status.Done.make(smtValues); + } + + @Override + public SmtRewriteResult visit(ExpressionValue expressionValue) + { + return SmtRewriteResult.Status.Done.make(expressionValue); + } + + @Override + public SmtRewriteResult visit(SmtUnsatCore smtUnsatCore) + { + return SmtRewriteResult.Status.Done.make(smtUnsatCore); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/SmtModelVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/SmtModelVisitor.java new file mode 100644 index 000000000..027ba51b9 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/SmtModelVisitor.java @@ -0,0 +1,363 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.parser; + +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.SmtEnv; +import edu.uiowa.smt.parser.antlr.SmtBaseVisitor; +import edu.uiowa.smt.parser.antlr.SmtParser; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SmtModelVisitor extends SmtBaseVisitor +{ + private SmtEnv root = new SmtEnv(); + + @Override + public SmtAst visitModel(SmtParser.ModelContext ctx) + { + SmtModel model = new SmtModel(); + + for (SmtParser.SortDeclarationContext context : ctx.sortDeclaration()) + { + model.addSort((Sort) this.visitSortDeclaration(context)); + } + + for (SmtParser.FunctionDefinitionContext context : ctx.functionDefinition()) + { + // ignore named formulas + if (context.getText().contains("\"filename\":")) + { + //ToDo: support functions of named formulas + continue; + } + FunctionDefinition definition = (FunctionDefinition) this.visitFunctionDefinition(context); + model.addFunction(definition); + if (definition.getInputVariables().size() == 0) + { + root.put(definition.getName(), definition.getVariable()); + } + //ToDo: handle functions and lambda expressions + } + + return model; + } + + @Override + public SmtAst visitSortDeclaration(SmtParser.SortDeclarationContext ctx) + { + String sortName = ctx.sortName().getText(); + int arity = Integer.parseInt(ctx.arity().getText()); + Sort sort = new Sort(sortName, arity); + return sort; + } + + @Override + public SmtAst visitSort(SmtParser.SortContext ctx) + { + if (ctx.sortName() != null) + { + switch (ctx.sortName().getText()) + { + case AbstractTranslator.atom: + return AbstractTranslator.atomSort; + case AbstractTranslator.intSortName: + return AbstractTranslator.intSort; + case AbstractTranslator.uninterpretedIntName: + return AbstractTranslator.uninterpretedInt; + case AbstractTranslator.boolSortName: + return AbstractTranslator.boolSort; + default: + throw new UnsupportedOperationException(String.format("Unknown sort '%s'", ctx.sortName().getText())); + } + } + + if (ctx.tupleSort() != null) + { + return this.visitTupleSort(ctx.tupleSort()); + } + + if (ctx.setSort() != null) + { + return this.visitSetSort(ctx.setSort()); + } + throw new UnsupportedOperationException(); + } + + @Override + public SmtAst visitTupleSort(SmtParser.TupleSortContext ctx) + { + List sorts = new ArrayList<>(ctx.sort().size()); + + for (SmtParser.SortContext sortContext : ctx.sort()) + { + Sort sort = (Sort) this.visitSort(sortContext); + sorts.add(sort); + } + + return new TupleSort(sorts); + } + + @Override + public SmtAst visitSetSort(SmtParser.SetSortContext ctx) + { + Sort elementSort = (Sort) this.visitSort(ctx.sort()); + return new SetSort(elementSort); + } + + @Override + public SmtAst visitFunctionDefinition(SmtParser.FunctionDefinitionContext ctx) + { + String name = ctx.functionName().getText(); + name = processName(name); + List smtVariables = ctx.variableDeclaration().stream() + .map(argument -> (SmtVariable) this.visitVariableDeclaration(argument)) + .collect(Collectors.toList()); + Map arguments = smtVariables + .stream() + .collect(Collectors + .toMap(v -> v.getName(), v -> v.getVariable())); + SmtEnv smtEnv = new SmtEnv(root); + smtEnv.putAll(arguments); + Sort returnSort = (Sort) visitSort(ctx.sort()); + + SmtExpr smtExpr = (SmtExpr) this.visitExpression(ctx.expression(), smtEnv); + + FunctionDefinition definition = new FunctionDefinition(name, smtVariables, returnSort, smtExpr, true); + + return definition; + } + + private String processName(String name) + { + return name.replaceAll("\\|", "").trim(); + } + + @Override + public SmtAst visitVariableDeclaration(SmtParser.VariableDeclarationContext ctx) + { + String name = processName(ctx.variableName().getText()); + Sort sort = (Sort) this.visitSort(ctx.sort()); + return new SmtVariable(name, sort, true); + } + + public SmtAst visitExpression(SmtParser.ExpressionContext ctx, SmtEnv smtEnv) + { + if (ctx.constant() != null) + { + return this.visitConstant(ctx.constant()); + } + if (ctx.variable() != null) + { + return this.visitVariable(ctx.variable(), smtEnv); + } + if (ctx.unaryExpression() != null) + { + return this.visitUnaryExpression(ctx.unaryExpression(), smtEnv); + } + if (ctx.binaryExpression() != null) + { + return this.visitBinaryExpression(ctx.binaryExpression(), smtEnv); + } + if (ctx.ternaryExpression() != null) + { + return this.visitTernaryExpression(ctx.ternaryExpression(), smtEnv); + } + if (ctx.multiArityExpression() != null) + { + return this.visitMultiArityExpression(ctx.multiArityExpression(), smtEnv); + } + if (ctx.quantifiedExpression() != null) + { + return this.visitQuantifiedExpression(ctx.quantifiedExpression(), smtEnv); + } + if (ctx.functionCallExpression() != null) + { + return this.visitFunctionCallExpression(ctx.functionCallExpression(), smtEnv); + } + if (ctx.expression() != null) + { + return this.visitExpression(ctx.expression(), smtEnv); + } + throw new UnsupportedOperationException(); + } + + public SmtAst visitUnaryExpression(SmtParser.UnaryExpressionContext ctx, SmtEnv smtEnv) + { + SmtExpr smtExpr = (SmtExpr) this.visitExpression(ctx.expression(), smtEnv); + SmtUnaryExpr.Op operator = SmtUnaryExpr.Op.getOp(ctx.UnaryOperator().getText()); + return operator.make(smtExpr); + } + + public SmtAst visitBinaryExpression(SmtParser.BinaryExpressionContext ctx, SmtEnv smtEnv) + { + SmtExpr left = (SmtExpr) this.visitExpression(ctx.expression(0), smtEnv); + SmtExpr right = (SmtExpr) this.visitExpression(ctx.expression(1), smtEnv); + + SmtBinaryExpr.Op operator = SmtBinaryExpr.Op.getOp(ctx.BinaryOperator().getText()); + return operator.make(left, right); + } + + public SmtAst visitTernaryExpression(SmtParser.TernaryExpressionContext ctx, SmtEnv smtEnv) + { + List smtExprs = ctx.expression().stream() + .map(expression -> (SmtExpr) this.visitExpression(expression, smtEnv)) + .collect(Collectors.toList()); + + return new SmtIteExpr(smtExprs.get(0), smtExprs.get(1), smtExprs.get(2)); + } + + public SmtAst visitMultiArityExpression(SmtParser.MultiArityExpressionContext ctx, SmtEnv smtEnv) + { + List smtExprs = ctx.expression().stream() + .map(expression -> (SmtExpr) this.visitExpression(expression, smtEnv)) + .collect(Collectors.toList()); + + SmtMultiArityExpr.Op operator = SmtMultiArityExpr.Op.getOp(ctx.MultiArityOperator().getText()); + return operator.make(smtExprs); + } + + public SmtAst visitQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx, SmtEnv smtEnv) + { + List smtVariables = ctx.variableDeclaration().stream() + .map(argument -> (SmtVariable) this.visitVariableDeclaration(argument)) + .collect(Collectors.toList()); + Map variables = smtVariables + .stream() + .collect(Collectors + .toMap(v -> v.getName(), v -> v.getVariable())); + SmtEnv newSmtEnv = new SmtEnv(smtEnv); + newSmtEnv.putAll(variables); + SmtExpr smtExpr = (SmtExpr) this.visitExpression(ctx.expression(), newSmtEnv); + + SmtQtExpr.Op operator = SmtQtExpr.Op.getOp(ctx.Quantifier().getText()); + return operator.make(smtExpr, smtVariables); + } + + public SmtAst visitFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx, SmtEnv smtEnv) + { + List smtExprs = ctx.expression().stream() + .map(expression -> (SmtExpr) this.visitExpression(expression, smtEnv)) + .collect(Collectors.toList()); + Variable function = (Variable) smtEnv.get(processName(ctx.Identifier().getText())); + SmtExpr call = new SmtCallExpr((FunctionDeclaration) function.getDeclaration(), smtExprs); + return call; + } + + @Override + public SmtAst visitConstant(SmtParser.ConstantContext ctx) + { + if (ctx.boolConstant() != null) + { + return this.visitBoolConstant(ctx.boolConstant()); + } + if (ctx.integerConstant() != null) + { + return this.visitIntegerConstant(ctx.integerConstant()); + } + if (ctx.uninterpretedConstant() != null) + { + return this.visitUninterpretedConstant(ctx.uninterpretedConstant()); + } + if (ctx.emptySet() != null) + { + return this.visitEmptySet(ctx.emptySet()); + } + throw new UnsupportedOperationException(); + } + + @Override + public SmtAst visitBoolConstant(SmtParser.BoolConstantContext ctx) + { + if (ctx.True() != null) + { + return BoolConstant.True; + } + else + { + return BoolConstant.False; + } + } + + @Override + public SmtAst visitIntegerConstant(SmtParser.IntegerConstantContext ctx) + { + int constant = Integer.parseInt(ctx.getText()); + return IntConstant.getInstance(constant); + } + + @Override + public SmtAst visitUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx) + { + if (ctx.AtomPrefix() != null) + { + return new UninterpretedConstant(ctx.getText(), AbstractTranslator.atomSort); + } + if (ctx.UninterpretedIntPrefix() != null) + { + return new UninterpretedConstant(ctx.getText(), AbstractTranslator.uninterpretedInt); + } + throw new UnsupportedOperationException(String.format("Unknown constant value '%s'", ctx.getText())); + } + + @Override + public SmtAst visitEmptySet(SmtParser.EmptySetContext ctx) + { + Sort elementSort = (Sort) this.visitSort(ctx.sort()); + Sort setSort = new SetSort(elementSort); + return SmtUnaryExpr.Op.EMPTYSET.make(setSort); + } + + public SmtAst visitVariable(SmtParser.VariableContext ctx, SmtEnv smtEnv) + { + String variableName = processName(ctx.getText()); + if (!smtEnv.containsKey(variableName)) + { + throw new RuntimeException(String.format("The variable '%s' is undefined", variableName)); + } + SmtExpr variable = smtEnv.get(variableName); + return variable; + } + + @Override + public SmtAst visitGetValue(SmtParser.GetValueContext ctx) + { + List values = new ArrayList<>(); + + for (int i = 0; i < ctx.expression().size(); i = i + 2) + { + SmtExpr smtExpr = (SmtExpr) visitExpression(ctx.expression(i), root); + SmtExpr value = (SmtExpr) visitExpression(ctx.expression(i + 1), root); + ExpressionValue expressionValue = new ExpressionValue(smtExpr, value); + values.add(expressionValue); + } + + return new SmtValues(values); + } + + @Override + public SmtAst visitGetUnsatCore(SmtParser.GetUnsatCoreContext ctx) + { + List core = ctx.Identifier().stream() + .map(i -> processName(i.getText())) + .collect(Collectors.toList()); + + return new SmtUnsatCore(core); + } + + @Override + public SmtAst visitExpression(SmtParser.ExpressionContext ctx) + { + throw new UnsupportedOperationException("Use the overloaded method visitExpression(SmtParser.ExpressionContext ctx, Map arguments)"); + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.g4 b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.g4 new file mode 100644 index 000000000..c92d5ae34 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.g4 @@ -0,0 +1,104 @@ +grammar Smt; + +// parser rules + +model : '(' 'model' sortDeclaration* functionDefinition* ')' ; + +sortDeclaration : '(' 'declare-sort' sortName arity ')' ; + +functionDefinition : '(' 'define-fun' functionName '(' smtVariable* ')' sort + expression ')' ; + +smtVariable : '(' variableName sort ')' ; + +sort : sortName | '(' tupleSort ')' | '(' setSort ')' ; + +setSort : 'Set' sort ; + +tupleSort : 'Tuple' sort+ ; + +sortName : Identifier ; + +arity : Integer ; + +functionName : Identifier ; + +variableName : Identifier ; + +expression : constant + | variable + | unaryExpression + | binaryExpression + | ternaryExpression + | multiArityExpression + | quantifiedExpression + | functionCallExpression + | '(' expression ')'; + + +unaryExpression : UnaryOperator expression ; + +binaryExpression : BinaryOperator expression expression ; + +ternaryExpression : TernaryOperator expression expression expression ; + +multiArityExpression : MultiArityOperator expression+ ; + +quantifiedExpression : Quantifier '(' smtVariable+ ')' '(' expression ')' ; + +functionCallExpression : Identifier expression+ ; + +variable : Identifier; + +constant : boolConstant + | integerConstant + | uninterpretedConstant + | emptySet ; + +boolConstant : True | False; + +integerConstant : '-' Integer | Integer ; + +uninterpretedConstant : (AtomPrefix | UninterpretedIntPrefix) Integer; + +emptySet : 'as' 'emptyset' '(' 'Set' sort ')' ; + +getValue : '(' ('(' expression expression ')' )+ ')'; + +getUnsatCore : '(' Identifier* ')'; + +// lexer rules + +True : 'true' ; + +False : 'false' ; + +Quantifier : 'forall' | 'exists' ; + +UnaryOperator : 'not' | 'singleton' | 'complement' | 'transpose' | 'tclosure' ; + +BinaryOperator : '=' | '>' | '>=' | '<' | '<=' + | '+' | '-' | '*' | '/' | 'mod' + | '=>' + | 'union' | 'intersection' | 'setminus' | 'member' | 'subset' + | 'join' | 'product' ; + +TernaryOperator : 'ite' ; + +MultiArityOperator : 'mkTuple' | 'insert' | 'distinct' | 'or' | 'and' ; + +AtomPrefix : '@uc_Atom_'; + +UninterpretedIntPrefix : '@uc_UInt_' ; + +Identifier : IdentifierLetter (IdentifierLetter | Digit)* | ('|' .*? '|'); + +IdentifierLetter : 'a'..'z'|'A'..'Z'|'_'|'/' | '\'' | '"' | '$' | '.' | '-'; + +Integer : Digit+ ; + +Digit : '0'..'9' ; + +Comment : ';' ~( '\r' | '\n' )* -> skip ; + +Whitespace : [ \t\r\n]+ -> skip ; \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.interp b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.interp new file mode 100644 index 000000000..ac45ba135 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.interp @@ -0,0 +1,87 @@ +token literal names: +null +'(' +'model' +')' +'declare-sort' +'define-fun' +'Set' +'Tuple' +'-' +'as' +'emptyset' +'true' +'false' +null +null +null +'ite' +null +'@uc_Atom_' +'@uc_UInt_' +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +True +False +Quantifier +UnaryOperator +BinaryOperator +TernaryOperator +MultiArityOperator +AtomPrefix +UninterpretedIntPrefix +Identifier +IdentifierLetter +Integer +Digit +Comment +Whitespace + +rule names: +model +sortDeclaration +functionDefinition +smtVariable +sort +setSort +tupleSort +sortName +arity +functionName +variableName +expression +unaryExpression +binaryExpression +ternaryExpression +multiArityExpression +quantifiedExpression +functionCallExpression +variable +constant +boolConstant +integerConstant +uninterpretedConstant +emptySet +getValue +getUnsatCore + + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 27, 221, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 3, 2, 3, 2, 3, 2, 7, 2, 58, 10, 2, 12, 2, 14, 2, 61, 11, 2, 3, 2, 7, 2, 64, 10, 2, 12, 2, 14, 2, 67, 11, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 7, 4, 82, 10, 4, 12, 4, 14, 4, 85, 11, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 106, 10, 6, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 6, 8, 113, 10, 8, 13, 8, 14, 8, 114, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 5, 13, 137, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 6, 17, 153, 10, 17, 13, 17, 14, 17, 154, 3, 18, 3, 18, 3, 18, 6, 18, 160, 10, 18, 13, 18, 14, 18, 161, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 6, 19, 171, 10, 19, 13, 19, 14, 19, 172, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 181, 10, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 6, 26, 206, 10, 26, 13, 26, 14, 26, 207, 3, 26, 3, 26, 3, 27, 3, 27, 7, 27, 214, 10, 27, 12, 27, 14, 27, 217, 11, 27, 3, 27, 3, 27, 3, 27, 2, 2, 28, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 2, 4, 3, 2, 13, 14, 3, 2, 20, 21, 2, 217, 2, 54, 3, 2, 2, 2, 4, 70, 3, 2, 2, 2, 6, 76, 3, 2, 2, 2, 8, 91, 3, 2, 2, 2, 10, 105, 3, 2, 2, 2, 12, 107, 3, 2, 2, 2, 14, 110, 3, 2, 2, 2, 16, 116, 3, 2, 2, 2, 18, 118, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 122, 3, 2, 2, 2, 24, 136, 3, 2, 2, 2, 26, 138, 3, 2, 2, 2, 28, 141, 3, 2, 2, 2, 30, 145, 3, 2, 2, 2, 32, 150, 3, 2, 2, 2, 34, 156, 3, 2, 2, 2, 36, 168, 3, 2, 2, 2, 38, 174, 3, 2, 2, 2, 40, 180, 3, 2, 2, 2, 42, 182, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 189, 3, 2, 2, 2, 48, 192, 3, 2, 2, 2, 50, 199, 3, 2, 2, 2, 52, 211, 3, 2, 2, 2, 54, 55, 7, 3, 2, 2, 55, 59, 7, 4, 2, 2, 56, 58, 5, 4, 3, 2, 57, 56, 3, 2, 2, 2, 58, 61, 3, 2, 2, 2, 59, 57, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 65, 3, 2, 2, 2, 61, 59, 3, 2, 2, 2, 62, 64, 5, 6, 4, 2, 63, 62, 3, 2, 2, 2, 64, 67, 3, 2, 2, 2, 65, 63, 3, 2, 2, 2, 65, 66, 3, 2, 2, 2, 66, 68, 3, 2, 2, 2, 67, 65, 3, 2, 2, 2, 68, 69, 7, 5, 2, 2, 69, 3, 3, 2, 2, 2, 70, 71, 7, 3, 2, 2, 71, 72, 7, 6, 2, 2, 72, 73, 5, 16, 9, 2, 73, 74, 5, 18, 10, 2, 74, 75, 7, 5, 2, 2, 75, 5, 3, 2, 2, 2, 76, 77, 7, 3, 2, 2, 77, 78, 7, 7, 2, 2, 78, 79, 5, 20, 11, 2, 79, 83, 7, 3, 2, 2, 80, 82, 5, 8, 5, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 86, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 87, 7, 5, 2, 2, 87, 88, 5, 10, 6, 2, 88, 89, 5, 24, 13, 2, 89, 90, 7, 5, 2, 2, 90, 7, 3, 2, 2, 2, 91, 92, 7, 3, 2, 2, 92, 93, 5, 22, 12, 2, 93, 94, 5, 10, 6, 2, 94, 95, 7, 5, 2, 2, 95, 9, 3, 2, 2, 2, 96, 106, 5, 16, 9, 2, 97, 98, 7, 3, 2, 2, 98, 99, 5, 14, 8, 2, 99, 100, 7, 5, 2, 2, 100, 106, 3, 2, 2, 2, 101, 102, 7, 3, 2, 2, 102, 103, 5, 12, 7, 2, 103, 104, 7, 5, 2, 2, 104, 106, 3, 2, 2, 2, 105, 96, 3, 2, 2, 2, 105, 97, 3, 2, 2, 2, 105, 101, 3, 2, 2, 2, 106, 11, 3, 2, 2, 2, 107, 108, 7, 8, 2, 2, 108, 109, 5, 10, 6, 2, 109, 13, 3, 2, 2, 2, 110, 112, 7, 9, 2, 2, 111, 113, 5, 10, 6, 2, 112, 111, 3, 2, 2, 2, 113, 114, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 15, 3, 2, 2, 2, 116, 117, 7, 22, 2, 2, 117, 17, 3, 2, 2, 2, 118, 119, 7, 24, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 22, 2, 2, 121, 21, 3, 2, 2, 2, 122, 123, 7, 22, 2, 2, 123, 23, 3, 2, 2, 2, 124, 137, 5, 40, 21, 2, 125, 137, 5, 38, 20, 2, 126, 137, 5, 26, 14, 2, 127, 137, 5, 28, 15, 2, 128, 137, 5, 30, 16, 2, 129, 137, 5, 32, 17, 2, 130, 137, 5, 34, 18, 2, 131, 137, 5, 36, 19, 2, 132, 133, 7, 3, 2, 2, 133, 134, 5, 24, 13, 2, 134, 135, 7, 5, 2, 2, 135, 137, 3, 2, 2, 2, 136, 124, 3, 2, 2, 2, 136, 125, 3, 2, 2, 2, 136, 126, 3, 2, 2, 2, 136, 127, 3, 2, 2, 2, 136, 128, 3, 2, 2, 2, 136, 129, 3, 2, 2, 2, 136, 130, 3, 2, 2, 2, 136, 131, 3, 2, 2, 2, 136, 132, 3, 2, 2, 2, 137, 25, 3, 2, 2, 2, 138, 139, 7, 16, 2, 2, 139, 140, 5, 24, 13, 2, 140, 27, 3, 2, 2, 2, 141, 142, 7, 17, 2, 2, 142, 143, 5, 24, 13, 2, 143, 144, 5, 24, 13, 2, 144, 29, 3, 2, 2, 2, 145, 146, 7, 18, 2, 2, 146, 147, 5, 24, 13, 2, 147, 148, 5, 24, 13, 2, 148, 149, 5, 24, 13, 2, 149, 31, 3, 2, 2, 2, 150, 152, 7, 19, 2, 2, 151, 153, 5, 24, 13, 2, 152, 151, 3, 2, 2, 2, 153, 154, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 33, 3, 2, 2, 2, 156, 157, 7, 15, 2, 2, 157, 159, 7, 3, 2, 2, 158, 160, 5, 8, 5, 2, 159, 158, 3, 2, 2, 2, 160, 161, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 163, 3, 2, 2, 2, 163, 164, 7, 5, 2, 2, 164, 165, 7, 3, 2, 2, 165, 166, 5, 24, 13, 2, 166, 167, 7, 5, 2, 2, 167, 35, 3, 2, 2, 2, 168, 170, 7, 22, 2, 2, 169, 171, 5, 24, 13, 2, 170, 169, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 170, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 37, 3, 2, 2, 2, 174, 175, 7, 22, 2, 2, 175, 39, 3, 2, 2, 2, 176, 181, 5, 42, 22, 2, 177, 181, 5, 44, 23, 2, 178, 181, 5, 46, 24, 2, 179, 181, 5, 48, 25, 2, 180, 176, 3, 2, 2, 2, 180, 177, 3, 2, 2, 2, 180, 178, 3, 2, 2, 2, 180, 179, 3, 2, 2, 2, 181, 41, 3, 2, 2, 2, 182, 183, 9, 2, 2, 2, 183, 43, 3, 2, 2, 2, 184, 185, 7, 10, 2, 2, 185, 188, 7, 24, 2, 2, 186, 188, 7, 24, 2, 2, 187, 184, 3, 2, 2, 2, 187, 186, 3, 2, 2, 2, 188, 45, 3, 2, 2, 2, 189, 190, 9, 3, 2, 2, 190, 191, 7, 24, 2, 2, 191, 47, 3, 2, 2, 2, 192, 193, 7, 11, 2, 2, 193, 194, 7, 12, 2, 2, 194, 195, 7, 3, 2, 2, 195, 196, 7, 8, 2, 2, 196, 197, 5, 10, 6, 2, 197, 198, 7, 5, 2, 2, 198, 49, 3, 2, 2, 2, 199, 205, 7, 3, 2, 2, 200, 201, 7, 3, 2, 2, 201, 202, 5, 24, 13, 2, 202, 203, 5, 24, 13, 2, 203, 204, 7, 5, 2, 2, 204, 206, 3, 2, 2, 2, 205, 200, 3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 205, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 210, 7, 5, 2, 2, 210, 51, 3, 2, 2, 2, 211, 215, 7, 3, 2, 2, 212, 214, 7, 22, 2, 2, 213, 212, 3, 2, 2, 2, 214, 217, 3, 2, 2, 2, 215, 213, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 218, 3, 2, 2, 2, 217, 215, 3, 2, 2, 2, 218, 219, 7, 5, 2, 2, 219, 53, 3, 2, 2, 2, 15, 59, 65, 83, 105, 114, 136, 154, 161, 172, 180, 187, 207, 215] \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.tokens b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.tokens new file mode 100644 index 000000000..d1e203bbf --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/Smt.tokens @@ -0,0 +1,40 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +True=11 +False=12 +Quantifier=13 +UnaryOperator=14 +BinaryOperator=15 +TernaryOperator=16 +MultiArityOperator=17 +AtomPrefix=18 +UninterpretedIntPrefix=19 +Identifier=20 +IdentifierLetter=21 +Integer=22 +Digit=23 +Comment=24 +Whitespace=25 +'('=1 +'model'=2 +')'=3 +'declare-sort'=4 +'define-fun'=5 +'Set'=6 +'Tuple'=7 +'-'=8 +'as'=9 +'emptyset'=10 +'true'=11 +'false'=12 +'ite'=16 +'@uc_Atom_'=18 +'@uc_UInt_'=19 diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseListener.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseListener.java new file mode 100644 index 000000000..fde2fbc56 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseListener.java @@ -0,0 +1,574 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link SmtListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class SmtBaseListener implements SmtListener +{ + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterModel(SmtParser.ModelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitModel(SmtParser.ModelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSortDeclaration(SmtParser.SortDeclarationContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSortDeclaration(SmtParser.SortDeclarationContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterFunctionDefinition(SmtParser.FunctionDefinitionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitFunctionDefinition(SmtParser.FunctionDefinitionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterVariableDeclaration(SmtParser.VariableDeclarationContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitVariableDeclaration(SmtParser.VariableDeclarationContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSort(SmtParser.SortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSort(SmtParser.SortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSetSort(SmtParser.SetSortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSetSort(SmtParser.SetSortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterTupleSort(SmtParser.TupleSortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitTupleSort(SmtParser.TupleSortContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSortName(SmtParser.SortNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSortName(SmtParser.SortNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterArity(SmtParser.ArityContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitArity(SmtParser.ArityContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterFunctionName(SmtParser.FunctionNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitFunctionName(SmtParser.FunctionNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterVariableName(SmtParser.VariableNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitVariableName(SmtParser.VariableNameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterExpression(SmtParser.ExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitExpression(SmtParser.ExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterUnaryExpression(SmtParser.UnaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitUnaryExpression(SmtParser.UnaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterBinaryExpression(SmtParser.BinaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitBinaryExpression(SmtParser.BinaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterTernaryExpression(SmtParser.TernaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitTernaryExpression(SmtParser.TernaryExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterMultiArityExpression(SmtParser.MultiArityExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitMultiArityExpression(SmtParser.MultiArityExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterVariable(SmtParser.VariableContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitVariable(SmtParser.VariableContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterConstant(SmtParser.ConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitConstant(SmtParser.ConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterBoolConstant(SmtParser.BoolConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitBoolConstant(SmtParser.BoolConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterIntegerConstant(SmtParser.IntegerConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitIntegerConstant(SmtParser.IntegerConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterEmptySet(SmtParser.EmptySetContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitEmptySet(SmtParser.EmptySetContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterGetValue(SmtParser.GetValueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitGetValue(SmtParser.GetValueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterGetUnsatCore(SmtParser.GetUnsatCoreContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitGetUnsatCore(SmtParser.GetUnsatCoreContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterEveryRule(ParserRuleContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitEveryRule(ParserRuleContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void visitTerminal(TerminalNode node) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void visitErrorNode(ErrorNode node) + { + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseVisitor.java new file mode 100644 index 000000000..63bef56ab --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtBaseVisitor.java @@ -0,0 +1,327 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link SmtVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class SmtBaseVisitor extends AbstractParseTreeVisitor implements SmtVisitor +{ + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitModel(SmtParser.ModelContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitSortDeclaration(SmtParser.SortDeclarationContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitFunctionDefinition(SmtParser.FunctionDefinitionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitVariableDeclaration(SmtParser.VariableDeclarationContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitSort(SmtParser.SortContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitSetSort(SmtParser.SetSortContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitTupleSort(SmtParser.TupleSortContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitSortName(SmtParser.SortNameContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitArity(SmtParser.ArityContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitFunctionName(SmtParser.FunctionNameContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitVariableName(SmtParser.VariableNameContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitExpression(SmtParser.ExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitUnaryExpression(SmtParser.UnaryExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitBinaryExpression(SmtParser.BinaryExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitTernaryExpression(SmtParser.TernaryExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitMultiArityExpression(SmtParser.MultiArityExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitVariable(SmtParser.VariableContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitConstant(SmtParser.ConstantContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitBoolConstant(SmtParser.BoolConstantContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitIntegerConstant(SmtParser.IntegerConstantContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitEmptySet(SmtParser.EmptySetContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitGetValue(SmtParser.GetValueContext ctx) + { + return visitChildren(ctx); + } + + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override + public T visitGetUnsatCore(SmtParser.GetUnsatCoreContext ctx) + { + return visitChildren(ctx); + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.interp b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.interp new file mode 100644 index 000000000..b4dd26a5d --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.interp @@ -0,0 +1,92 @@ +token literal names: +null +'(' +'model' +')' +'declare-sort' +'define-fun' +'Set' +'Tuple' +'-' +'as' +'emptyset' +'true' +'false' +null +null +null +'ite' +null +'@uc_Atom_' +'@uc_UInt_' +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +True +False +Quantifier +UnaryOperator +BinaryOperator +TernaryOperator +MultiArityOperator +AtomPrefix +UninterpretedIntPrefix +Identifier +IdentifierLetter +Integer +Digit +Comment +Whitespace + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +T__7 +T__8 +T__9 +True +False +Quantifier +UnaryOperator +BinaryOperator +TernaryOperator +MultiArityOperator +AtomPrefix +UninterpretedIntPrefix +Identifier +IdentifierLetter +Integer +Digit +Comment +Whitespace + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 27, 334, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 5, 14, 135, 10, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 176, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 238, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 270, 10, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 7, 21, 295, 10, 21, 12, 21, 14, 21, 298, 11, 21, 3, 21, 3, 21, 7, 21, 302, 10, 21, 12, 21, 14, 21, 305, 11, 21, 3, 21, 5, 21, 308, 10, 21, 3, 22, 3, 22, 3, 23, 6, 23, 313, 10, 23, 13, 23, 14, 23, 314, 3, 24, 3, 24, 3, 25, 3, 25, 7, 25, 321, 10, 25, 12, 25, 14, 25, 324, 11, 25, 3, 25, 3, 25, 3, 26, 6, 26, 329, 10, 26, 13, 26, 14, 26, 330, 3, 26, 3, 26, 3, 303, 2, 27, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 3, 2, 6, 5, 2, 44, 45, 47, 47, 49, 49, 9, 2, 36, 36, 38, 38, 41, 41, 47, 49, 67, 92, 97, 97, 99, 124, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 2, 362, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 3, 53, 3, 2, 2, 2, 5, 55, 3, 2, 2, 2, 7, 61, 3, 2, 2, 2, 9, 63, 3, 2, 2, 2, 11, 76, 3, 2, 2, 2, 13, 87, 3, 2, 2, 2, 15, 91, 3, 2, 2, 2, 17, 97, 3, 2, 2, 2, 19, 99, 3, 2, 2, 2, 21, 102, 3, 2, 2, 2, 23, 111, 3, 2, 2, 2, 25, 116, 3, 2, 2, 2, 27, 134, 3, 2, 2, 2, 29, 175, 3, 2, 2, 2, 31, 237, 3, 2, 2, 2, 33, 239, 3, 2, 2, 2, 35, 269, 3, 2, 2, 2, 37, 271, 3, 2, 2, 2, 39, 281, 3, 2, 2, 2, 41, 307, 3, 2, 2, 2, 43, 309, 3, 2, 2, 2, 45, 312, 3, 2, 2, 2, 47, 316, 3, 2, 2, 2, 49, 318, 3, 2, 2, 2, 51, 328, 3, 2, 2, 2, 53, 54, 7, 42, 2, 2, 54, 4, 3, 2, 2, 2, 55, 56, 7, 111, 2, 2, 56, 57, 7, 113, 2, 2, 57, 58, 7, 102, 2, 2, 58, 59, 7, 103, 2, 2, 59, 60, 7, 110, 2, 2, 60, 6, 3, 2, 2, 2, 61, 62, 7, 43, 2, 2, 62, 8, 3, 2, 2, 2, 63, 64, 7, 102, 2, 2, 64, 65, 7, 103, 2, 2, 65, 66, 7, 101, 2, 2, 66, 67, 7, 110, 2, 2, 67, 68, 7, 99, 2, 2, 68, 69, 7, 116, 2, 2, 69, 70, 7, 103, 2, 2, 70, 71, 7, 47, 2, 2, 71, 72, 7, 117, 2, 2, 72, 73, 7, 113, 2, 2, 73, 74, 7, 116, 2, 2, 74, 75, 7, 118, 2, 2, 75, 10, 3, 2, 2, 2, 76, 77, 7, 102, 2, 2, 77, 78, 7, 103, 2, 2, 78, 79, 7, 104, 2, 2, 79, 80, 7, 107, 2, 2, 80, 81, 7, 112, 2, 2, 81, 82, 7, 103, 2, 2, 82, 83, 7, 47, 2, 2, 83, 84, 7, 104, 2, 2, 84, 85, 7, 119, 2, 2, 85, 86, 7, 112, 2, 2, 86, 12, 3, 2, 2, 2, 87, 88, 7, 85, 2, 2, 88, 89, 7, 103, 2, 2, 89, 90, 7, 118, 2, 2, 90, 14, 3, 2, 2, 2, 91, 92, 7, 86, 2, 2, 92, 93, 7, 119, 2, 2, 93, 94, 7, 114, 2, 2, 94, 95, 7, 110, 2, 2, 95, 96, 7, 103, 2, 2, 96, 16, 3, 2, 2, 2, 97, 98, 7, 47, 2, 2, 98, 18, 3, 2, 2, 2, 99, 100, 7, 99, 2, 2, 100, 101, 7, 117, 2, 2, 101, 20, 3, 2, 2, 2, 102, 103, 7, 103, 2, 2, 103, 104, 7, 111, 2, 2, 104, 105, 7, 114, 2, 2, 105, 106, 7, 118, 2, 2, 106, 107, 7, 123, 2, 2, 107, 108, 7, 117, 2, 2, 108, 109, 7, 103, 2, 2, 109, 110, 7, 118, 2, 2, 110, 22, 3, 2, 2, 2, 111, 112, 7, 118, 2, 2, 112, 113, 7, 116, 2, 2, 113, 114, 7, 119, 2, 2, 114, 115, 7, 103, 2, 2, 115, 24, 3, 2, 2, 2, 116, 117, 7, 104, 2, 2, 117, 118, 7, 99, 2, 2, 118, 119, 7, 110, 2, 2, 119, 120, 7, 117, 2, 2, 120, 121, 7, 103, 2, 2, 121, 26, 3, 2, 2, 2, 122, 123, 7, 104, 2, 2, 123, 124, 7, 113, 2, 2, 124, 125, 7, 116, 2, 2, 125, 126, 7, 99, 2, 2, 126, 127, 7, 110, 2, 2, 127, 135, 7, 110, 2, 2, 128, 129, 7, 103, 2, 2, 129, 130, 7, 122, 2, 2, 130, 131, 7, 107, 2, 2, 131, 132, 7, 117, 2, 2, 132, 133, 7, 118, 2, 2, 133, 135, 7, 117, 2, 2, 134, 122, 3, 2, 2, 2, 134, 128, 3, 2, 2, 2, 135, 28, 3, 2, 2, 2, 136, 137, 7, 112, 2, 2, 137, 138, 7, 113, 2, 2, 138, 176, 7, 118, 2, 2, 139, 140, 7, 117, 2, 2, 140, 141, 7, 107, 2, 2, 141, 142, 7, 112, 2, 2, 142, 143, 7, 105, 2, 2, 143, 144, 7, 110, 2, 2, 144, 145, 7, 103, 2, 2, 145, 146, 7, 118, 2, 2, 146, 147, 7, 113, 2, 2, 147, 176, 7, 112, 2, 2, 148, 149, 7, 101, 2, 2, 149, 150, 7, 113, 2, 2, 150, 151, 7, 111, 2, 2, 151, 152, 7, 114, 2, 2, 152, 153, 7, 110, 2, 2, 153, 154, 7, 103, 2, 2, 154, 155, 7, 111, 2, 2, 155, 156, 7, 103, 2, 2, 156, 157, 7, 112, 2, 2, 157, 176, 7, 118, 2, 2, 158, 159, 7, 118, 2, 2, 159, 160, 7, 116, 2, 2, 160, 161, 7, 99, 2, 2, 161, 162, 7, 112, 2, 2, 162, 163, 7, 117, 2, 2, 163, 164, 7, 114, 2, 2, 164, 165, 7, 113, 2, 2, 165, 166, 7, 117, 2, 2, 166, 176, 7, 103, 2, 2, 167, 168, 7, 118, 2, 2, 168, 169, 7, 101, 2, 2, 169, 170, 7, 110, 2, 2, 170, 171, 7, 113, 2, 2, 171, 172, 7, 117, 2, 2, 172, 173, 7, 119, 2, 2, 173, 174, 7, 116, 2, 2, 174, 176, 7, 103, 2, 2, 175, 136, 3, 2, 2, 2, 175, 139, 3, 2, 2, 2, 175, 148, 3, 2, 2, 2, 175, 158, 3, 2, 2, 2, 175, 167, 3, 2, 2, 2, 176, 30, 3, 2, 2, 2, 177, 238, 4, 63, 64, 2, 178, 179, 7, 64, 2, 2, 179, 238, 7, 63, 2, 2, 180, 238, 7, 62, 2, 2, 181, 182, 7, 62, 2, 2, 182, 238, 7, 63, 2, 2, 183, 238, 9, 2, 2, 2, 184, 185, 7, 111, 2, 2, 185, 186, 7, 113, 2, 2, 186, 238, 7, 102, 2, 2, 187, 188, 7, 63, 2, 2, 188, 238, 7, 64, 2, 2, 189, 190, 7, 119, 2, 2, 190, 191, 7, 112, 2, 2, 191, 192, 7, 107, 2, 2, 192, 193, 7, 113, 2, 2, 193, 238, 7, 112, 2, 2, 194, 195, 7, 107, 2, 2, 195, 196, 7, 112, 2, 2, 196, 197, 7, 118, 2, 2, 197, 198, 7, 103, 2, 2, 198, 199, 7, 116, 2, 2, 199, 200, 7, 117, 2, 2, 200, 201, 7, 103, 2, 2, 201, 202, 7, 101, 2, 2, 202, 203, 7, 118, 2, 2, 203, 204, 7, 107, 2, 2, 204, 205, 7, 113, 2, 2, 205, 238, 7, 112, 2, 2, 206, 207, 7, 117, 2, 2, 207, 208, 7, 103, 2, 2, 208, 209, 7, 118, 2, 2, 209, 210, 7, 111, 2, 2, 210, 211, 7, 107, 2, 2, 211, 212, 7, 112, 2, 2, 212, 213, 7, 119, 2, 2, 213, 238, 7, 117, 2, 2, 214, 215, 7, 111, 2, 2, 215, 216, 7, 103, 2, 2, 216, 217, 7, 111, 2, 2, 217, 218, 7, 100, 2, 2, 218, 219, 7, 103, 2, 2, 219, 238, 7, 116, 2, 2, 220, 221, 7, 117, 2, 2, 221, 222, 7, 119, 2, 2, 222, 223, 7, 100, 2, 2, 223, 224, 7, 117, 2, 2, 224, 225, 7, 103, 2, 2, 225, 238, 7, 118, 2, 2, 226, 227, 7, 108, 2, 2, 227, 228, 7, 113, 2, 2, 228, 229, 7, 107, 2, 2, 229, 238, 7, 112, 2, 2, 230, 231, 7, 114, 2, 2, 231, 232, 7, 116, 2, 2, 232, 233, 7, 113, 2, 2, 233, 234, 7, 102, 2, 2, 234, 235, 7, 119, 2, 2, 235, 236, 7, 101, 2, 2, 236, 238, 7, 118, 2, 2, 237, 177, 3, 2, 2, 2, 237, 178, 3, 2, 2, 2, 237, 180, 3, 2, 2, 2, 237, 181, 3, 2, 2, 2, 237, 183, 3, 2, 2, 2, 237, 184, 3, 2, 2, 2, 237, 187, 3, 2, 2, 2, 237, 189, 3, 2, 2, 2, 237, 194, 3, 2, 2, 2, 237, 206, 3, 2, 2, 2, 237, 214, 3, 2, 2, 2, 237, 220, 3, 2, 2, 2, 237, 226, 3, 2, 2, 2, 237, 230, 3, 2, 2, 2, 238, 32, 3, 2, 2, 2, 239, 240, 7, 107, 2, 2, 240, 241, 7, 118, 2, 2, 241, 242, 7, 103, 2, 2, 242, 34, 3, 2, 2, 2, 243, 244, 7, 111, 2, 2, 244, 245, 7, 109, 2, 2, 245, 246, 7, 86, 2, 2, 246, 247, 7, 119, 2, 2, 247, 248, 7, 114, 2, 2, 248, 249, 7, 110, 2, 2, 249, 270, 7, 103, 2, 2, 250, 251, 7, 107, 2, 2, 251, 252, 7, 112, 2, 2, 252, 253, 7, 117, 2, 2, 253, 254, 7, 103, 2, 2, 254, 255, 7, 116, 2, 2, 255, 270, 7, 118, 2, 2, 256, 257, 7, 102, 2, 2, 257, 258, 7, 107, 2, 2, 258, 259, 7, 117, 2, 2, 259, 260, 7, 118, 2, 2, 260, 261, 7, 107, 2, 2, 261, 262, 7, 112, 2, 2, 262, 263, 7, 101, 2, 2, 263, 270, 7, 118, 2, 2, 264, 265, 7, 113, 2, 2, 265, 270, 7, 116, 2, 2, 266, 267, 7, 99, 2, 2, 267, 268, 7, 112, 2, 2, 268, 270, 7, 102, 2, 2, 269, 243, 3, 2, 2, 2, 269, 250, 3, 2, 2, 2, 269, 256, 3, 2, 2, 2, 269, 264, 3, 2, 2, 2, 269, 266, 3, 2, 2, 2, 270, 36, 3, 2, 2, 2, 271, 272, 7, 66, 2, 2, 272, 273, 7, 119, 2, 2, 273, 274, 7, 101, 2, 2, 274, 275, 7, 97, 2, 2, 275, 276, 7, 67, 2, 2, 276, 277, 7, 118, 2, 2, 277, 278, 7, 113, 2, 2, 278, 279, 7, 111, 2, 2, 279, 280, 7, 97, 2, 2, 280, 38, 3, 2, 2, 2, 281, 282, 7, 66, 2, 2, 282, 283, 7, 119, 2, 2, 283, 284, 7, 101, 2, 2, 284, 285, 7, 97, 2, 2, 285, 286, 7, 87, 2, 2, 286, 287, 7, 75, 2, 2, 287, 288, 7, 112, 2, 2, 288, 289, 7, 118, 2, 2, 289, 290, 7, 97, 2, 2, 290, 40, 3, 2, 2, 2, 291, 296, 5, 43, 22, 2, 292, 295, 5, 43, 22, 2, 293, 295, 5, 47, 24, 2, 294, 292, 3, 2, 2, 2, 294, 293, 3, 2, 2, 2, 295, 298, 3, 2, 2, 2, 296, 294, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 308, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 299, 303, 7, 126, 2, 2, 300, 302, 11, 2, 2, 2, 301, 300, 3, 2, 2, 2, 302, 305, 3, 2, 2, 2, 303, 304, 3, 2, 2, 2, 303, 301, 3, 2, 2, 2, 304, 306, 3, 2, 2, 2, 305, 303, 3, 2, 2, 2, 306, 308, 7, 126, 2, 2, 307, 291, 3, 2, 2, 2, 307, 299, 3, 2, 2, 2, 308, 42, 3, 2, 2, 2, 309, 310, 9, 3, 2, 2, 310, 44, 3, 2, 2, 2, 311, 313, 5, 47, 24, 2, 312, 311, 3, 2, 2, 2, 313, 314, 3, 2, 2, 2, 314, 312, 3, 2, 2, 2, 314, 315, 3, 2, 2, 2, 315, 46, 3, 2, 2, 2, 316, 317, 4, 50, 59, 2, 317, 48, 3, 2, 2, 2, 318, 322, 7, 61, 2, 2, 319, 321, 10, 4, 2, 2, 320, 319, 3, 2, 2, 2, 321, 324, 3, 2, 2, 2, 322, 320, 3, 2, 2, 2, 322, 323, 3, 2, 2, 2, 323, 325, 3, 2, 2, 2, 324, 322, 3, 2, 2, 2, 325, 326, 8, 25, 2, 2, 326, 50, 3, 2, 2, 2, 327, 329, 9, 5, 2, 2, 328, 327, 3, 2, 2, 2, 329, 330, 3, 2, 2, 2, 330, 328, 3, 2, 2, 2, 330, 331, 3, 2, 2, 2, 331, 332, 3, 2, 2, 2, 332, 333, 8, 26, 2, 2, 333, 52, 3, 2, 2, 2, 14, 2, 134, 175, 237, 269, 294, 296, 303, 307, 314, 322, 330, 3, 8, 2, 2] \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.java new file mode 100644 index 000000000..acce23560 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.java @@ -0,0 +1,278 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.LexerATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class SmtLexer extends Lexer +{ + static + { + RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); + } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, T__7 = 8, T__8 = 9, + T__9 = 10, True = 11, False = 12, Quantifier = 13, UnaryOperator = 14, BinaryOperator = 15, + TernaryOperator = 16, MultiArityOperator = 17, AtomPrefix = 18, UninterpretedIntPrefix = 19, + Identifier = 20, IdentifierLetter = 21, Integer = 22, Digit = 23, Comment = 24, + Whitespace = 25; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + private static String[] makeRuleNames() + { + return new String[]{ + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "True", "False", "Quantifier", "UnaryOperator", "BinaryOperator", + "TernaryOperator", "MultiArityOperator", "AtomPrefix", "UninterpretedIntPrefix", + "Identifier", "IdentifierLetter", "Integer", "Digit", "Comment", "Whitespace" + }; + } + + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() + { + return new String[]{ + null, "'('", "'model'", "')'", "'declare-sort'", "'define-fun'", "'Set'", + "'Tuple'", "'-'", "'as'", "'emptyset'", "'true'", "'false'", null, null, + null, "'ite'", null, "'@uc_Atom_'", "'@uc_UInt_'" + }; + } + + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + + private static String[] makeSymbolicNames() + { + return new String[]{ + null, null, null, null, null, null, null, null, null, null, null, "True", + "False", "Quantifier", "UnaryOperator", "BinaryOperator", "TernaryOperator", + "MultiArityOperator", "AtomPrefix", "UninterpretedIntPrefix", "Identifier", + "IdentifierLetter", "Integer", "Digit", "Comment", "Whitespace" + }; + } + + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + + static + { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) + { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) + { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) + { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() + { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() + { + return VOCABULARY; + } + + + public SmtLexer(CharStream input) + { + super(input); + _interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @Override + public String getGrammarFileName() + { + return "Smt.g4"; + } + + @Override + public String[] getRuleNames() + { + return ruleNames; + } + + @Override + public String getSerializedATN() + { + return _serializedATN; + } + + @Override + public String[] getChannelNames() + { + return channelNames; + } + + @Override + public String[] getModeNames() + { + return modeNames; + } + + @Override + public ATN getATN() + { + return _ATN; + } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\33\u014e\b\1\4\2" + + "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4" + + "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22" + + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31" + + "\t\31\4\32\t\32\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3" + + "\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6" + + "\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\n\3\n\3" + + "\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3" + + "\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3" + + "\16\3\16\3\16\5\16\u0087\n\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17" + + "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17" + + "\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17" + + "\3\17\3\17\3\17\5\17\u00b0\n\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20" + + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20" + + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20" + + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20" + + "\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\5\20\u00ee\n\20\3\21" + + "\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22" + + "\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22" + + "\3\22\5\22\u010e\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23" + + "\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\7\25" + + "\u0127\n\25\f\25\16\25\u012a\13\25\3\25\3\25\7\25\u012e\n\25\f\25\16\25" + + "\u0131\13\25\3\25\5\25\u0134\n\25\3\26\3\26\3\27\6\27\u0139\n\27\r\27" + + "\16\27\u013a\3\30\3\30\3\31\3\31\7\31\u0141\n\31\f\31\16\31\u0144\13\31" + + "\3\31\3\31\3\32\6\32\u0149\n\32\r\32\16\32\u014a\3\32\3\32\3\u012f\2\33" + + "\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20" + + "\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\3\2\6\5\2,-//\61\61" + + "\t\2$$&&))/\61C\\aac|\4\2\f\f\17\17\5\2\13\f\17\17\"\"\2\u016a\2\3\3\2" + + "\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17" + + "\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2" + + "\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3" + + "\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3" + + "\2\2\2\2\63\3\2\2\2\3\65\3\2\2\2\5\67\3\2\2\2\7=\3\2\2\2\t?\3\2\2\2\13" + + "L\3\2\2\2\rW\3\2\2\2\17[\3\2\2\2\21a\3\2\2\2\23c\3\2\2\2\25f\3\2\2\2\27" + + "o\3\2\2\2\31t\3\2\2\2\33\u0086\3\2\2\2\35\u00af\3\2\2\2\37\u00ed\3\2\2" + + "\2!\u00ef\3\2\2\2#\u010d\3\2\2\2%\u010f\3\2\2\2\'\u0119\3\2\2\2)\u0133" + + "\3\2\2\2+\u0135\3\2\2\2-\u0138\3\2\2\2/\u013c\3\2\2\2\61\u013e\3\2\2\2" + + "\63\u0148\3\2\2\2\65\66\7*\2\2\66\4\3\2\2\2\678\7o\2\289\7q\2\29:\7f\2" + + "\2:;\7g\2\2;<\7n\2\2<\6\3\2\2\2=>\7+\2\2>\b\3\2\2\2?@\7f\2\2@A\7g\2\2" + + "AB\7e\2\2BC\7n\2\2CD\7c\2\2DE\7t\2\2EF\7g\2\2FG\7/\2\2GH\7u\2\2HI\7q\2" + + "\2IJ\7t\2\2JK\7v\2\2K\n\3\2\2\2LM\7f\2\2MN\7g\2\2NO\7h\2\2OP\7k\2\2PQ" + + "\7p\2\2QR\7g\2\2RS\7/\2\2ST\7h\2\2TU\7w\2\2UV\7p\2\2V\f\3\2\2\2WX\7U\2" + + "\2XY\7g\2\2YZ\7v\2\2Z\16\3\2\2\2[\\\7V\2\2\\]\7w\2\2]^\7r\2\2^_\7n\2\2" + + "_`\7g\2\2`\20\3\2\2\2ab\7/\2\2b\22\3\2\2\2cd\7c\2\2de\7u\2\2e\24\3\2\2" + + "\2fg\7g\2\2gh\7o\2\2hi\7r\2\2ij\7v\2\2jk\7{\2\2kl\7u\2\2lm\7g\2\2mn\7" + + "v\2\2n\26\3\2\2\2op\7v\2\2pq\7t\2\2qr\7w\2\2rs\7g\2\2s\30\3\2\2\2tu\7" + + "h\2\2uv\7c\2\2vw\7n\2\2wx\7u\2\2xy\7g\2\2y\32\3\2\2\2z{\7h\2\2{|\7q\2" + + "\2|}\7t\2\2}~\7c\2\2~\177\7n\2\2\177\u0087\7n\2\2\u0080\u0081\7g\2\2\u0081" + + "\u0082\7z\2\2\u0082\u0083\7k\2\2\u0083\u0084\7u\2\2\u0084\u0085\7v\2\2" + + "\u0085\u0087\7u\2\2\u0086z\3\2\2\2\u0086\u0080\3\2\2\2\u0087\34\3\2\2" + + "\2\u0088\u0089\7p\2\2\u0089\u008a\7q\2\2\u008a\u00b0\7v\2\2\u008b\u008c" + + "\7u\2\2\u008c\u008d\7k\2\2\u008d\u008e\7p\2\2\u008e\u008f\7i\2\2\u008f" + + "\u0090\7n\2\2\u0090\u0091\7g\2\2\u0091\u0092\7v\2\2\u0092\u0093\7q\2\2" + + "\u0093\u00b0\7p\2\2\u0094\u0095\7e\2\2\u0095\u0096\7q\2\2\u0096\u0097" + + "\7o\2\2\u0097\u0098\7r\2\2\u0098\u0099\7n\2\2\u0099\u009a\7g\2\2\u009a" + + "\u009b\7o\2\2\u009b\u009c\7g\2\2\u009c\u009d\7p\2\2\u009d\u00b0\7v\2\2" + + "\u009e\u009f\7v\2\2\u009f\u00a0\7t\2\2\u00a0\u00a1\7c\2\2\u00a1\u00a2" + + "\7p\2\2\u00a2\u00a3\7u\2\2\u00a3\u00a4\7r\2\2\u00a4\u00a5\7q\2\2\u00a5" + + "\u00a6\7u\2\2\u00a6\u00b0\7g\2\2\u00a7\u00a8\7v\2\2\u00a8\u00a9\7e\2\2" + + "\u00a9\u00aa\7n\2\2\u00aa\u00ab\7q\2\2\u00ab\u00ac\7u\2\2\u00ac\u00ad" + + "\7w\2\2\u00ad\u00ae\7t\2\2\u00ae\u00b0\7g\2\2\u00af\u0088\3\2\2\2\u00af" + + "\u008b\3\2\2\2\u00af\u0094\3\2\2\2\u00af\u009e\3\2\2\2\u00af\u00a7\3\2" + + "\2\2\u00b0\36\3\2\2\2\u00b1\u00ee\4?@\2\u00b2\u00b3\7@\2\2\u00b3\u00ee" + + "\7?\2\2\u00b4\u00ee\7>\2\2\u00b5\u00b6\7>\2\2\u00b6\u00ee\7?\2\2\u00b7" + + "\u00ee\t\2\2\2\u00b8\u00b9\7o\2\2\u00b9\u00ba\7q\2\2\u00ba\u00ee\7f\2" + + "\2\u00bb\u00bc\7?\2\2\u00bc\u00ee\7@\2\2\u00bd\u00be\7w\2\2\u00be\u00bf" + + "\7p\2\2\u00bf\u00c0\7k\2\2\u00c0\u00c1\7q\2\2\u00c1\u00ee\7p\2\2\u00c2" + + "\u00c3\7k\2\2\u00c3\u00c4\7p\2\2\u00c4\u00c5\7v\2\2\u00c5\u00c6\7g\2\2" + + "\u00c6\u00c7\7t\2\2\u00c7\u00c8\7u\2\2\u00c8\u00c9\7g\2\2\u00c9\u00ca" + + "\7e\2\2\u00ca\u00cb\7v\2\2\u00cb\u00cc\7k\2\2\u00cc\u00cd\7q\2\2\u00cd" + + "\u00ee\7p\2\2\u00ce\u00cf\7u\2\2\u00cf\u00d0\7g\2\2\u00d0\u00d1\7v\2\2" + + "\u00d1\u00d2\7o\2\2\u00d2\u00d3\7k\2\2\u00d3\u00d4\7p\2\2\u00d4\u00d5" + + "\7w\2\2\u00d5\u00ee\7u\2\2\u00d6\u00d7\7o\2\2\u00d7\u00d8\7g\2\2\u00d8" + + "\u00d9\7o\2\2\u00d9\u00da\7d\2\2\u00da\u00db\7g\2\2\u00db\u00ee\7t\2\2" + + "\u00dc\u00dd\7u\2\2\u00dd\u00de\7w\2\2\u00de\u00df\7d\2\2\u00df\u00e0" + + "\7u\2\2\u00e0\u00e1\7g\2\2\u00e1\u00ee\7v\2\2\u00e2\u00e3\7l\2\2\u00e3" + + "\u00e4\7q\2\2\u00e4\u00e5\7k\2\2\u00e5\u00ee\7p\2\2\u00e6\u00e7\7r\2\2" + + "\u00e7\u00e8\7t\2\2\u00e8\u00e9\7q\2\2\u00e9\u00ea\7f\2\2\u00ea\u00eb" + + "\7w\2\2\u00eb\u00ec\7e\2\2\u00ec\u00ee\7v\2\2\u00ed\u00b1\3\2\2\2\u00ed" + + "\u00b2\3\2\2\2\u00ed\u00b4\3\2\2\2\u00ed\u00b5\3\2\2\2\u00ed\u00b7\3\2" + + "\2\2\u00ed\u00b8\3\2\2\2\u00ed\u00bb\3\2\2\2\u00ed\u00bd\3\2\2\2\u00ed" + + "\u00c2\3\2\2\2\u00ed\u00ce\3\2\2\2\u00ed\u00d6\3\2\2\2\u00ed\u00dc\3\2" + + "\2\2\u00ed\u00e2\3\2\2\2\u00ed\u00e6\3\2\2\2\u00ee \3\2\2\2\u00ef\u00f0" + + "\7k\2\2\u00f0\u00f1\7v\2\2\u00f1\u00f2\7g\2\2\u00f2\"\3\2\2\2\u00f3\u00f4" + + "\7o\2\2\u00f4\u00f5\7m\2\2\u00f5\u00f6\7V\2\2\u00f6\u00f7\7w\2\2\u00f7" + + "\u00f8\7r\2\2\u00f8\u00f9\7n\2\2\u00f9\u010e\7g\2\2\u00fa\u00fb\7k\2\2" + + "\u00fb\u00fc\7p\2\2\u00fc\u00fd\7u\2\2\u00fd\u00fe\7g\2\2\u00fe\u00ff" + + "\7t\2\2\u00ff\u010e\7v\2\2\u0100\u0101\7f\2\2\u0101\u0102\7k\2\2\u0102" + + "\u0103\7u\2\2\u0103\u0104\7v\2\2\u0104\u0105\7k\2\2\u0105\u0106\7p\2\2" + + "\u0106\u0107\7e\2\2\u0107\u010e\7v\2\2\u0108\u0109\7q\2\2\u0109\u010e" + + "\7t\2\2\u010a\u010b\7c\2\2\u010b\u010c\7p\2\2\u010c\u010e\7f\2\2\u010d" + + "\u00f3\3\2\2\2\u010d\u00fa\3\2\2\2\u010d\u0100\3\2\2\2\u010d\u0108\3\2" + + "\2\2\u010d\u010a\3\2\2\2\u010e$\3\2\2\2\u010f\u0110\7B\2\2\u0110\u0111" + + "\7w\2\2\u0111\u0112\7e\2\2\u0112\u0113\7a\2\2\u0113\u0114\7C\2\2\u0114" + + "\u0115\7v\2\2\u0115\u0116\7q\2\2\u0116\u0117\7o\2\2\u0117\u0118\7a\2\2" + + "\u0118&\3\2\2\2\u0119\u011a\7B\2\2\u011a\u011b\7w\2\2\u011b\u011c\7e\2" + + "\2\u011c\u011d\7a\2\2\u011d\u011e\7W\2\2\u011e\u011f\7K\2\2\u011f\u0120" + + "\7p\2\2\u0120\u0121\7v\2\2\u0121\u0122\7a\2\2\u0122(\3\2\2\2\u0123\u0128" + + "\5+\26\2\u0124\u0127\5+\26\2\u0125\u0127\5/\30\2\u0126\u0124\3\2\2\2\u0126" + + "\u0125\3\2\2\2\u0127\u012a\3\2\2\2\u0128\u0126\3\2\2\2\u0128\u0129\3\2" + + "\2\2\u0129\u0134\3\2\2\2\u012a\u0128\3\2\2\2\u012b\u012f\7~\2\2\u012c" + + "\u012e\13\2\2\2\u012d\u012c\3\2\2\2\u012e\u0131\3\2\2\2\u012f\u0130\3" + + "\2\2\2\u012f\u012d\3\2\2\2\u0130\u0132\3\2\2\2\u0131\u012f\3\2\2\2\u0132" + + "\u0134\7~\2\2\u0133\u0123\3\2\2\2\u0133\u012b\3\2\2\2\u0134*\3\2\2\2\u0135" + + "\u0136\t\3\2\2\u0136,\3\2\2\2\u0137\u0139\5/\30\2\u0138\u0137\3\2\2\2" + + "\u0139\u013a\3\2\2\2\u013a\u0138\3\2\2\2\u013a\u013b\3\2\2\2\u013b.\3" + + "\2\2\2\u013c\u013d\4\62;\2\u013d\60\3\2\2\2\u013e\u0142\7=\2\2\u013f\u0141" + + "\n\4\2\2\u0140\u013f\3\2\2\2\u0141\u0144\3\2\2\2\u0142\u0140\3\2\2\2\u0142" + + "\u0143\3\2\2\2\u0143\u0145\3\2\2\2\u0144\u0142\3\2\2\2\u0145\u0146\b\31" + + "\2\2\u0146\62\3\2\2\2\u0147\u0149\t\5\2\2\u0148\u0147\3\2\2\2\u0149\u014a" + + "\3\2\2\2\u014a\u0148\3\2\2\2\u014a\u014b\3\2\2\2\u014b\u014c\3\2\2\2\u014c" + + "\u014d\b\32\2\2\u014d\64\3\2\2\2\16\2\u0086\u00af\u00ed\u010d\u0126\u0128" + + "\u012f\u0133\u013a\u0142\u014a\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + + static + { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) + { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.tokens b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.tokens new file mode 100644 index 000000000..d1e203bbf --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtLexer.tokens @@ -0,0 +1,40 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +True=11 +False=12 +Quantifier=13 +UnaryOperator=14 +BinaryOperator=15 +TernaryOperator=16 +MultiArityOperator=17 +AtomPrefix=18 +UninterpretedIntPrefix=19 +Identifier=20 +IdentifierLetter=21 +Integer=22 +Digit=23 +Comment=24 +Whitespace=25 +'('=1 +'model'=2 +')'=3 +'declare-sort'=4 +'define-fun'=5 +'Set'=6 +'Tuple'=7 +'-'=8 +'as'=9 +'emptyset'=10 +'true'=11 +'false'=12 +'ite'=16 +'@uc_Atom_'=18 +'@uc_UInt_'=19 diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtListener.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtListener.java new file mode 100644 index 000000000..e7cab354c --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtListener.java @@ -0,0 +1,375 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link SmtParser}. + */ +public interface SmtListener extends ParseTreeListener +{ + /** + * Enter a parse tree produced by {@link SmtParser#model}. + * + * @param ctx the parse tree + */ + void enterModel(SmtParser.ModelContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#model}. + * + * @param ctx the parse tree + */ + void exitModel(SmtParser.ModelContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#sortDeclaration}. + * + * @param ctx the parse tree + */ + void enterSortDeclaration(SmtParser.SortDeclarationContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#sortDeclaration}. + * + * @param ctx the parse tree + */ + void exitSortDeclaration(SmtParser.SortDeclarationContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#functionDefinition}. + * + * @param ctx the parse tree + */ + void enterFunctionDefinition(SmtParser.FunctionDefinitionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#functionDefinition}. + * + * @param ctx the parse tree + */ + void exitFunctionDefinition(SmtParser.FunctionDefinitionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#variableDeclaration}. + * + * @param ctx the parse tree + */ + void enterVariableDeclaration(SmtParser.VariableDeclarationContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#variableDeclaration}. + * + * @param ctx the parse tree + */ + void exitVariableDeclaration(SmtParser.VariableDeclarationContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#sort}. + * + * @param ctx the parse tree + */ + void enterSort(SmtParser.SortContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#sort}. + * + * @param ctx the parse tree + */ + void exitSort(SmtParser.SortContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#setSort}. + * + * @param ctx the parse tree + */ + void enterSetSort(SmtParser.SetSortContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#setSort}. + * + * @param ctx the parse tree + */ + void exitSetSort(SmtParser.SetSortContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#tupleSort}. + * + * @param ctx the parse tree + */ + void enterTupleSort(SmtParser.TupleSortContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#tupleSort}. + * + * @param ctx the parse tree + */ + void exitTupleSort(SmtParser.TupleSortContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#sortName}. + * + * @param ctx the parse tree + */ + void enterSortName(SmtParser.SortNameContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#sortName}. + * + * @param ctx the parse tree + */ + void exitSortName(SmtParser.SortNameContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#arity}. + * + * @param ctx the parse tree + */ + void enterArity(SmtParser.ArityContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#arity}. + * + * @param ctx the parse tree + */ + void exitArity(SmtParser.ArityContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#functionName}. + * + * @param ctx the parse tree + */ + void enterFunctionName(SmtParser.FunctionNameContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#functionName}. + * + * @param ctx the parse tree + */ + void exitFunctionName(SmtParser.FunctionNameContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#variableName}. + * + * @param ctx the parse tree + */ + void enterVariableName(SmtParser.VariableNameContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#variableName}. + * + * @param ctx the parse tree + */ + void exitVariableName(SmtParser.VariableNameContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#expression}. + * + * @param ctx the parse tree + */ + void enterExpression(SmtParser.ExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#expression}. + * + * @param ctx the parse tree + */ + void exitExpression(SmtParser.ExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#unaryExpression}. + * + * @param ctx the parse tree + */ + void enterUnaryExpression(SmtParser.UnaryExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#unaryExpression}. + * + * @param ctx the parse tree + */ + void exitUnaryExpression(SmtParser.UnaryExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#binaryExpression}. + * + * @param ctx the parse tree + */ + void enterBinaryExpression(SmtParser.BinaryExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#binaryExpression}. + * + * @param ctx the parse tree + */ + void exitBinaryExpression(SmtParser.BinaryExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#ternaryExpression}. + * + * @param ctx the parse tree + */ + void enterTernaryExpression(SmtParser.TernaryExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#ternaryExpression}. + * + * @param ctx the parse tree + */ + void exitTernaryExpression(SmtParser.TernaryExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#multiArityExpression}. + * + * @param ctx the parse tree + */ + void enterMultiArityExpression(SmtParser.MultiArityExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#multiArityExpression}. + * + * @param ctx the parse tree + */ + void exitMultiArityExpression(SmtParser.MultiArityExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#quantifiedExpression}. + * + * @param ctx the parse tree + */ + void enterQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#quantifiedExpression}. + * + * @param ctx the parse tree + */ + void exitQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#functionCallExpression}. + * + * @param ctx the parse tree + */ + void enterFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#functionCallExpression}. + * + * @param ctx the parse tree + */ + void exitFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#variable}. + * + * @param ctx the parse tree + */ + void enterVariable(SmtParser.VariableContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#variable}. + * + * @param ctx the parse tree + */ + void exitVariable(SmtParser.VariableContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#constant}. + * + * @param ctx the parse tree + */ + void enterConstant(SmtParser.ConstantContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#constant}. + * + * @param ctx the parse tree + */ + void exitConstant(SmtParser.ConstantContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#boolConstant}. + * + * @param ctx the parse tree + */ + void enterBoolConstant(SmtParser.BoolConstantContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#boolConstant}. + * + * @param ctx the parse tree + */ + void exitBoolConstant(SmtParser.BoolConstantContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#integerConstant}. + * + * @param ctx the parse tree + */ + void enterIntegerConstant(SmtParser.IntegerConstantContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#integerConstant}. + * + * @param ctx the parse tree + */ + void exitIntegerConstant(SmtParser.IntegerConstantContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#uninterpretedConstant}. + * + * @param ctx the parse tree + */ + void enterUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#uninterpretedConstant}. + * + * @param ctx the parse tree + */ + void exitUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#emptySet}. + * + * @param ctx the parse tree + */ + void enterEmptySet(SmtParser.EmptySetContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#emptySet}. + * + * @param ctx the parse tree + */ + void exitEmptySet(SmtParser.EmptySetContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#getValue}. + * + * @param ctx the parse tree + */ + void enterGetValue(SmtParser.GetValueContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#getValue}. + * + * @param ctx the parse tree + */ + void exitGetValue(SmtParser.GetValueContext ctx); + + /** + * Enter a parse tree produced by {@link SmtParser#getUnsatCore}. + * + * @param ctx the parse tree + */ + void enterGetUnsatCore(SmtParser.GetUnsatCoreContext ctx); + + /** + * Exit a parse tree produced by {@link SmtParser#getUnsatCore}. + * + * @param ctx the parse tree + */ + void exitGetUnsatCore(SmtParser.GetUnsatCoreContext ctx); +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtParser.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtParser.java new file mode 100644 index 000000000..c0822dede --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtParser.java @@ -0,0 +1,2792 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.ParserATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; +import org.antlr.v4.runtime.tree.TerminalNode; + +import java.util.List; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class SmtParser extends Parser +{ + static + { + RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); + } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, T__7 = 8, T__8 = 9, + T__9 = 10, True = 11, False = 12, Quantifier = 13, UnaryOperator = 14, BinaryOperator = 15, + TernaryOperator = 16, MultiArityOperator = 17, AtomPrefix = 18, UninterpretedIntPrefix = 19, + Identifier = 20, IdentifierLetter = 21, Integer = 22, Digit = 23, Comment = 24, + Whitespace = 25; + public static final int + RULE_model = 0, RULE_sortDeclaration = 1, RULE_functionDefinition = 2, + RULE_variableDeclaration = 3, RULE_sort = 4, RULE_setSort = 5, RULE_tupleSort = 6, + RULE_sortName = 7, RULE_arity = 8, RULE_functionName = 9, RULE_variableName = 10, + RULE_expression = 11, RULE_unaryExpression = 12, RULE_binaryExpression = 13, + RULE_ternaryExpression = 14, RULE_multiArityExpression = 15, RULE_quantifiedExpression = 16, + RULE_functionCallExpression = 17, RULE_variable = 18, RULE_constant = 19, + RULE_boolConstant = 20, RULE_integerConstant = 21, RULE_uninterpretedConstant = 22, + RULE_emptySet = 23, RULE_getValue = 24, RULE_getUnsatCore = 25; + + private static String[] makeRuleNames() + { + return new String[]{ + "model", "sortDeclaration", "functionDefinition", "variableDeclaration", + "sort", "setSort", "tupleSort", "sortName", "arity", "functionName", + "variableName", "expression", "unaryExpression", "binaryExpression", + "ternaryExpression", "multiArityExpression", "quantifiedExpression", + "functionCallExpression", "variable", "constant", "boolConstant", "integerConstant", + "uninterpretedConstant", "emptySet", "getValue", "getUnsatCore" + }; + } + + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() + { + return new String[]{ + null, "'('", "'model'", "')'", "'declare-sort'", "'define-fun'", "'Set'", + "'Tuple'", "'-'", "'as'", "'emptyset'", "'true'", "'false'", null, null, + null, "'ite'", null, "'@uc_Atom_'", "'@uc_UInt_'" + }; + } + + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + + private static String[] makeSymbolicNames() + { + return new String[]{ + null, null, null, null, null, null, null, null, null, null, null, "True", + "False", "Quantifier", "UnaryOperator", "BinaryOperator", "TernaryOperator", + "MultiArityOperator", "AtomPrefix", "UninterpretedIntPrefix", "Identifier", + "IdentifierLetter", "Integer", "Digit", "Comment", "Whitespace" + }; + } + + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + + static + { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) + { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) + { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) + { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() + { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() + { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() + { + return "Smt.g4"; + } + + @Override + public String[] getRuleNames() + { + return ruleNames; + } + + @Override + public String getSerializedATN() + { + return _serializedATN; + } + + @Override + public ATN getATN() + { + return _ATN; + } + + public SmtParser(TokenStream input) + { + super(input); + _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + public static class ModelContext extends ParserRuleContext + { + public List sortDeclaration() + { + return getRuleContexts(SortDeclarationContext.class); + } + + public SortDeclarationContext sortDeclaration(int i) + { + return getRuleContext(SortDeclarationContext.class, i); + } + + public List functionDefinition() + { + return getRuleContexts(FunctionDefinitionContext.class); + } + + public FunctionDefinitionContext functionDefinition(int i) + { + return getRuleContext(FunctionDefinitionContext.class, i); + } + + public ModelContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_model; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterModel(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitModel(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitModel(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final ModelContext model() throws RecognitionException + { + ModelContext _localctx = new ModelContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_model); + int _la; + try + { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(52); + match(T__0); + setState(53); + match(T__1); + setState(57); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 0, _ctx); + while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER) + { + if (_alt == 1) + { + { + { + setState(54); + sortDeclaration(); + } + } + } + setState(59); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 0, _ctx); + } + setState(63); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == T__0) + { + { + { + setState(60); + functionDefinition(); + } + } + setState(65); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(66); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class SortDeclarationContext extends ParserRuleContext + { + public SortNameContext sortName() + { + return getRuleContext(SortNameContext.class, 0); + } + + public ArityContext arity() + { + return getRuleContext(ArityContext.class, 0); + } + + public SortDeclarationContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_sortDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterSortDeclaration(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitSortDeclaration(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitSortDeclaration(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final SortDeclarationContext sortDeclaration() throws RecognitionException + { + SortDeclarationContext _localctx = new SortDeclarationContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_sortDeclaration); + try + { + enterOuterAlt(_localctx, 1); + { + setState(68); + match(T__0); + setState(69); + match(T__3); + setState(70); + sortName(); + setState(71); + arity(); + setState(72); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class FunctionDefinitionContext extends ParserRuleContext + { + public FunctionNameContext functionName() + { + return getRuleContext(FunctionNameContext.class, 0); + } + + public SortContext sort() + { + return getRuleContext(SortContext.class, 0); + } + + public ExpressionContext expression() + { + return getRuleContext(ExpressionContext.class, 0); + } + + public List variableDeclaration() + { + return getRuleContexts(VariableDeclarationContext.class); + } + + public VariableDeclarationContext variableDeclaration(int i) + { + return getRuleContext(VariableDeclarationContext.class, i); + } + + public FunctionDefinitionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_functionDefinition; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterFunctionDefinition(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitFunctionDefinition(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitFunctionDefinition(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final FunctionDefinitionContext functionDefinition() throws RecognitionException + { + FunctionDefinitionContext _localctx = new FunctionDefinitionContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_functionDefinition); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(74); + match(T__0); + setState(75); + match(T__4); + setState(76); + functionName(); + setState(77); + match(T__0); + setState(81); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == T__0) + { + { + { + setState(78); + variableDeclaration(); + } + } + setState(83); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(84); + match(T__2); + setState(85); + sort(); + setState(86); + expression(); + setState(87); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class VariableDeclarationContext extends ParserRuleContext + { + public VariableNameContext variableName() + { + return getRuleContext(VariableNameContext.class, 0); + } + + public SortContext sort() + { + return getRuleContext(SortContext.class, 0); + } + + public VariableDeclarationContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_variableDeclaration; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterVariableDeclaration(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitVariableDeclaration(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitVariableDeclaration(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final VariableDeclarationContext variableDeclaration() throws RecognitionException + { + VariableDeclarationContext _localctx = new VariableDeclarationContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_variableDeclaration); + try + { + enterOuterAlt(_localctx, 1); + { + setState(89); + match(T__0); + setState(90); + variableName(); + setState(91); + sort(); + setState(92); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class SortContext extends ParserRuleContext + { + public SortNameContext sortName() + { + return getRuleContext(SortNameContext.class, 0); + } + + public TupleSortContext tupleSort() + { + return getRuleContext(TupleSortContext.class, 0); + } + + public SetSortContext setSort() + { + return getRuleContext(SetSortContext.class, 0); + } + + public SortContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_sort; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterSort(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitSort(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitSort(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final SortContext sort() throws RecognitionException + { + SortContext _localctx = new SortContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_sort); + try + { + setState(103); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 3, _ctx)) + { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(94); + sortName(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(95); + match(T__0); + setState(96); + tupleSort(); + setState(97); + match(T__2); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(99); + match(T__0); + setState(100); + setSort(); + setState(101); + match(T__2); + } + break; + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class SetSortContext extends ParserRuleContext + { + public SortContext sort() + { + return getRuleContext(SortContext.class, 0); + } + + public SetSortContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_setSort; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterSetSort(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitSetSort(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitSetSort(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final SetSortContext setSort() throws RecognitionException + { + SetSortContext _localctx = new SetSortContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_setSort); + try + { + enterOuterAlt(_localctx, 1); + { + setState(105); + match(T__5); + setState(106); + sort(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class TupleSortContext extends ParserRuleContext + { + public List sort() + { + return getRuleContexts(SortContext.class); + } + + public SortContext sort(int i) + { + return getRuleContext(SortContext.class, i); + } + + public TupleSortContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_tupleSort; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterTupleSort(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitTupleSort(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitTupleSort(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final TupleSortContext tupleSort() throws RecognitionException + { + TupleSortContext _localctx = new TupleSortContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_tupleSort); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(108); + match(T__6); + setState(110); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(109); + sort(); + } + } + setState(112); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == T__0 || _la == Identifier); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class SortNameContext extends ParserRuleContext + { + public TerminalNode Identifier() + { + return getToken(SmtParser.Identifier, 0); + } + + public SortNameContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_sortName; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterSortName(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitSortName(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitSortName(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final SortNameContext sortName() throws RecognitionException + { + SortNameContext _localctx = new SortNameContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_sortName); + try + { + enterOuterAlt(_localctx, 1); + { + setState(114); + match(Identifier); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class ArityContext extends ParserRuleContext + { + public TerminalNode Integer() + { + return getToken(SmtParser.Integer, 0); + } + + public ArityContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_arity; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterArity(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitArity(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitArity(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final ArityContext arity() throws RecognitionException + { + ArityContext _localctx = new ArityContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_arity); + try + { + enterOuterAlt(_localctx, 1); + { + setState(116); + match(Integer); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class FunctionNameContext extends ParserRuleContext + { + public TerminalNode Identifier() + { + return getToken(SmtParser.Identifier, 0); + } + + public FunctionNameContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_functionName; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterFunctionName(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitFunctionName(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitFunctionName(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final FunctionNameContext functionName() throws RecognitionException + { + FunctionNameContext _localctx = new FunctionNameContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_functionName); + try + { + enterOuterAlt(_localctx, 1); + { + setState(118); + match(Identifier); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class VariableNameContext extends ParserRuleContext + { + public TerminalNode Identifier() + { + return getToken(SmtParser.Identifier, 0); + } + + public VariableNameContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_variableName; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterVariableName(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitVariableName(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitVariableName(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final VariableNameContext variableName() throws RecognitionException + { + VariableNameContext _localctx = new VariableNameContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_variableName); + try + { + enterOuterAlt(_localctx, 1); + { + setState(120); + match(Identifier); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class ExpressionContext extends ParserRuleContext + { + public ConstantContext constant() + { + return getRuleContext(ConstantContext.class, 0); + } + + public VariableContext variable() + { + return getRuleContext(VariableContext.class, 0); + } + + public UnaryExpressionContext unaryExpression() + { + return getRuleContext(UnaryExpressionContext.class, 0); + } + + public BinaryExpressionContext binaryExpression() + { + return getRuleContext(BinaryExpressionContext.class, 0); + } + + public TernaryExpressionContext ternaryExpression() + { + return getRuleContext(TernaryExpressionContext.class, 0); + } + + public MultiArityExpressionContext multiArityExpression() + { + return getRuleContext(MultiArityExpressionContext.class, 0); + } + + public QuantifiedExpressionContext quantifiedExpression() + { + return getRuleContext(QuantifiedExpressionContext.class, 0); + } + + public FunctionCallExpressionContext functionCallExpression() + { + return getRuleContext(FunctionCallExpressionContext.class, 0); + } + + public ExpressionContext expression() + { + return getRuleContext(ExpressionContext.class, 0); + } + + public ExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_expression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final ExpressionContext expression() throws RecognitionException + { + ExpressionContext _localctx = new ExpressionContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_expression); + try + { + setState(134); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 5, _ctx)) + { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(122); + constant(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(123); + variable(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(124); + unaryExpression(); + } + break; + case 4: + enterOuterAlt(_localctx, 4); + { + setState(125); + binaryExpression(); + } + break; + case 5: + enterOuterAlt(_localctx, 5); + { + setState(126); + ternaryExpression(); + } + break; + case 6: + enterOuterAlt(_localctx, 6); + { + setState(127); + multiArityExpression(); + } + break; + case 7: + enterOuterAlt(_localctx, 7); + { + setState(128); + quantifiedExpression(); + } + break; + case 8: + enterOuterAlt(_localctx, 8); + { + setState(129); + functionCallExpression(); + } + break; + case 9: + enterOuterAlt(_localctx, 9); + { + setState(130); + match(T__0); + setState(131); + expression(); + setState(132); + match(T__2); + } + break; + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class UnaryExpressionContext extends ParserRuleContext + { + public TerminalNode UnaryOperator() + { + return getToken(SmtParser.UnaryOperator, 0); + } + + public ExpressionContext expression() + { + return getRuleContext(ExpressionContext.class, 0); + } + + public UnaryExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_unaryExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterUnaryExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitUnaryExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitUnaryExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final UnaryExpressionContext unaryExpression() throws RecognitionException + { + UnaryExpressionContext _localctx = new UnaryExpressionContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_unaryExpression); + try + { + enterOuterAlt(_localctx, 1); + { + setState(136); + match(UnaryOperator); + setState(137); + expression(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class BinaryExpressionContext extends ParserRuleContext + { + public TerminalNode BinaryOperator() + { + return getToken(SmtParser.BinaryOperator, 0); + } + + public List expression() + { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) + { + return getRuleContext(ExpressionContext.class, i); + } + + public BinaryExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_binaryExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterBinaryExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitBinaryExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitBinaryExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final BinaryExpressionContext binaryExpression() throws RecognitionException + { + BinaryExpressionContext _localctx = new BinaryExpressionContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_binaryExpression); + try + { + enterOuterAlt(_localctx, 1); + { + setState(139); + match(BinaryOperator); + setState(140); + expression(); + setState(141); + expression(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class TernaryExpressionContext extends ParserRuleContext + { + public TerminalNode TernaryOperator() + { + return getToken(SmtParser.TernaryOperator, 0); + } + + public List expression() + { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) + { + return getRuleContext(ExpressionContext.class, i); + } + + public TernaryExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_ternaryExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterTernaryExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitTernaryExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitTernaryExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final TernaryExpressionContext ternaryExpression() throws RecognitionException + { + TernaryExpressionContext _localctx = new TernaryExpressionContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_ternaryExpression); + try + { + enterOuterAlt(_localctx, 1); + { + setState(143); + match(TernaryOperator); + setState(144); + expression(); + setState(145); + expression(); + setState(146); + expression(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class MultiArityExpressionContext extends ParserRuleContext + { + public TerminalNode MultiArityOperator() + { + return getToken(SmtParser.MultiArityOperator, 0); + } + + public List expression() + { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) + { + return getRuleContext(ExpressionContext.class, i); + } + + public MultiArityExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_multiArityExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterMultiArityExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitMultiArityExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitMultiArityExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final MultiArityExpressionContext multiArityExpression() throws RecognitionException + { + MultiArityExpressionContext _localctx = new MultiArityExpressionContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_multiArityExpression); + try + { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(148); + match(MultiArityOperator); + setState(150); + _errHandler.sync(this); + _alt = 1; + do + { + switch (_alt) + { + case 1: + { + { + setState(149); + expression(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(152); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 6, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class QuantifiedExpressionContext extends ParserRuleContext + { + public TerminalNode Quantifier() + { + return getToken(SmtParser.Quantifier, 0); + } + + public ExpressionContext expression() + { + return getRuleContext(ExpressionContext.class, 0); + } + + public List variableDeclaration() + { + return getRuleContexts(VariableDeclarationContext.class); + } + + public VariableDeclarationContext variableDeclaration(int i) + { + return getRuleContext(VariableDeclarationContext.class, i); + } + + public QuantifiedExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_quantifiedExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterQuantifiedExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitQuantifiedExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitQuantifiedExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final QuantifiedExpressionContext quantifiedExpression() throws RecognitionException + { + QuantifiedExpressionContext _localctx = new QuantifiedExpressionContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_quantifiedExpression); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(154); + match(Quantifier); + setState(155); + match(T__0); + setState(157); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(156); + variableDeclaration(); + } + } + setState(159); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == T__0); + setState(161); + match(T__2); + setState(162); + match(T__0); + setState(163); + expression(); + setState(164); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class FunctionCallExpressionContext extends ParserRuleContext + { + public TerminalNode Identifier() + { + return getToken(SmtParser.Identifier, 0); + } + + public List expression() + { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) + { + return getRuleContext(ExpressionContext.class, i); + } + + public FunctionCallExpressionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_functionCallExpression; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterFunctionCallExpression(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitFunctionCallExpression(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitFunctionCallExpression(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final FunctionCallExpressionContext functionCallExpression() throws RecognitionException + { + FunctionCallExpressionContext _localctx = new FunctionCallExpressionContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_functionCallExpression); + try + { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(166); + match(Identifier); + setState(168); + _errHandler.sync(this); + _alt = 1; + do + { + switch (_alt) + { + case 1: + { + { + setState(167); + expression(); + } + } + break; + default: + throw new NoViableAltException(this); + } + setState(170); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input, 8, _ctx); + } while (_alt != 2 && _alt != org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class VariableContext extends ParserRuleContext + { + public TerminalNode Identifier() + { + return getToken(SmtParser.Identifier, 0); + } + + public VariableContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_variable; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterVariable(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitVariable(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitVariable(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final VariableContext variable() throws RecognitionException + { + VariableContext _localctx = new VariableContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_variable); + try + { + enterOuterAlt(_localctx, 1); + { + setState(172); + match(Identifier); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class ConstantContext extends ParserRuleContext + { + public BoolConstantContext boolConstant() + { + return getRuleContext(BoolConstantContext.class, 0); + } + + public IntegerConstantContext integerConstant() + { + return getRuleContext(IntegerConstantContext.class, 0); + } + + public UninterpretedConstantContext uninterpretedConstant() + { + return getRuleContext(UninterpretedConstantContext.class, 0); + } + + public EmptySetContext emptySet() + { + return getRuleContext(EmptySetContext.class, 0); + } + + public ConstantContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_constant; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterConstant(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitConstant(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitConstant(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final ConstantContext constant() throws RecognitionException + { + ConstantContext _localctx = new ConstantContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_constant); + try + { + setState(178); + _errHandler.sync(this); + switch (_input.LA(1)) + { + case True: + case False: + enterOuterAlt(_localctx, 1); + { + setState(174); + boolConstant(); + } + break; + case T__7: + case Integer: + enterOuterAlt(_localctx, 2); + { + setState(175); + integerConstant(); + } + break; + case AtomPrefix: + case UninterpretedIntPrefix: + enterOuterAlt(_localctx, 3); + { + setState(176); + uninterpretedConstant(); + } + break; + case T__8: + enterOuterAlt(_localctx, 4); + { + setState(177); + emptySet(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class BoolConstantContext extends ParserRuleContext + { + public TerminalNode True() + { + return getToken(SmtParser.True, 0); + } + + public TerminalNode False() + { + return getToken(SmtParser.False, 0); + } + + public BoolConstantContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_boolConstant; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterBoolConstant(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitBoolConstant(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitBoolConstant(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final BoolConstantContext boolConstant() throws RecognitionException + { + BoolConstantContext _localctx = new BoolConstantContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_boolConstant); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(180); + _la = _input.LA(1); + if (!(_la == True || _la == False)) + { + _errHandler.recoverInline(this); + } + else + { + if (_input.LA(1) == Token.EOF) + { + matchedEOF = true; + } + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class IntegerConstantContext extends ParserRuleContext + { + public TerminalNode Integer() + { + return getToken(SmtParser.Integer, 0); + } + + public IntegerConstantContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_integerConstant; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterIntegerConstant(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitIntegerConstant(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitIntegerConstant(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final IntegerConstantContext integerConstant() throws RecognitionException + { + IntegerConstantContext _localctx = new IntegerConstantContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_integerConstant); + try + { + setState(185); + _errHandler.sync(this); + switch (_input.LA(1)) + { + case T__7: + enterOuterAlt(_localctx, 1); + { + setState(182); + match(T__7); + setState(183); + match(Integer); + } + break; + case Integer: + enterOuterAlt(_localctx, 2); + { + setState(184); + match(Integer); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class UninterpretedConstantContext extends ParserRuleContext + { + public TerminalNode Integer() + { + return getToken(SmtParser.Integer, 0); + } + + public TerminalNode AtomPrefix() + { + return getToken(SmtParser.AtomPrefix, 0); + } + + public TerminalNode UninterpretedIntPrefix() + { + return getToken(SmtParser.UninterpretedIntPrefix, 0); + } + + public UninterpretedConstantContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_uninterpretedConstant; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterUninterpretedConstant(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitUninterpretedConstant(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitUninterpretedConstant(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final UninterpretedConstantContext uninterpretedConstant() throws RecognitionException + { + UninterpretedConstantContext _localctx = new UninterpretedConstantContext(_ctx, getState()); + enterRule(_localctx, 44, RULE_uninterpretedConstant); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(187); + _la = _input.LA(1); + if (!(_la == AtomPrefix || _la == UninterpretedIntPrefix)) + { + _errHandler.recoverInline(this); + } + else + { + if (_input.LA(1) == Token.EOF) + { + matchedEOF = true; + } + _errHandler.reportMatch(this); + consume(); + } + setState(188); + match(Integer); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class EmptySetContext extends ParserRuleContext + { + public SortContext sort() + { + return getRuleContext(SortContext.class, 0); + } + + public EmptySetContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_emptySet; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterEmptySet(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitEmptySet(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitEmptySet(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final EmptySetContext emptySet() throws RecognitionException + { + EmptySetContext _localctx = new EmptySetContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_emptySet); + try + { + enterOuterAlt(_localctx, 1); + { + setState(190); + match(T__8); + setState(191); + match(T__9); + setState(192); + match(T__0); + setState(193); + match(T__5); + setState(194); + sort(); + setState(195); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class GetValueContext extends ParserRuleContext + { + public List expression() + { + return getRuleContexts(ExpressionContext.class); + } + + public ExpressionContext expression(int i) + { + return getRuleContext(ExpressionContext.class, i); + } + + public GetValueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_getValue; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterGetValue(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitGetValue(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitGetValue(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final GetValueContext getValue() throws RecognitionException + { + GetValueContext _localctx = new GetValueContext(_ctx, getState()); + enterRule(_localctx, 48, RULE_getValue); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(197); + match(T__0); + setState(203); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(198); + match(T__0); + setState(199); + expression(); + setState(200); + expression(); + setState(201); + match(T__2); + } + } + setState(205); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == T__0); + setState(207); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class GetUnsatCoreContext extends ParserRuleContext + { + public List Identifier() + { + return getTokens(SmtParser.Identifier); + } + + public TerminalNode Identifier(int i) + { + return getToken(SmtParser.Identifier, i); + } + + public GetUnsatCoreContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + @Override + public int getRuleIndex() + { + return RULE_getUnsatCore; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).enterGetUnsatCore(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof SmtListener) + { + ((SmtListener) listener).exitGetUnsatCore(this); + } + } + + @Override + public T accept(ParseTreeVisitor visitor) + { + if (visitor instanceof SmtVisitor) + { + return ((SmtVisitor) visitor).visitGetUnsatCore(this); + } + else + { + return visitor.visitChildren(this); + } + } + } + + public final GetUnsatCoreContext getUnsatCore() throws RecognitionException + { + GetUnsatCoreContext _localctx = new GetUnsatCoreContext(_ctx, getState()); + enterRule(_localctx, 50, RULE_getUnsatCore); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(209); + match(T__0); + setState(213); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == Identifier) + { + { + { + setState(210); + match(Identifier); + } + } + setState(215); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(216); + match(T__2); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\33\u00dd\4\2\t\2" + + "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13" + + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22" + + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31" + + "\4\32\t\32\4\33\t\33\3\2\3\2\3\2\7\2:\n\2\f\2\16\2=\13\2\3\2\7\2@\n\2" + + "\f\2\16\2C\13\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\7" + + "\4R\n\4\f\4\16\4U\13\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6" + + "\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6j\n\6\3\7\3\7\3\7\3\b\3\b\6\bq\n\b\r\b" + + "\16\br\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3" + + "\r\3\r\3\r\3\r\3\r\5\r\u0089\n\r\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3" + + "\20\3\20\3\20\3\20\3\20\3\21\3\21\6\21\u0099\n\21\r\21\16\21\u009a\3\22" + + "\3\22\3\22\6\22\u00a0\n\22\r\22\16\22\u00a1\3\22\3\22\3\22\3\22\3\22\3" + + "\23\3\23\6\23\u00ab\n\23\r\23\16\23\u00ac\3\24\3\24\3\25\3\25\3\25\3\25" + + "\5\25\u00b5\n\25\3\26\3\26\3\27\3\27\3\27\5\27\u00bc\n\27\3\30\3\30\3" + + "\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\6" + + "\32\u00ce\n\32\r\32\16\32\u00cf\3\32\3\32\3\33\3\33\7\33\u00d6\n\33\f" + + "\33\16\33\u00d9\13\33\3\33\3\33\3\33\2\2\34\2\4\6\b\n\f\16\20\22\24\26" + + "\30\32\34\36 \"$&(*,.\60\62\64\2\4\3\2\r\16\3\2\24\25\2\u00d9\2\66\3\2" + + "\2\2\4F\3\2\2\2\6L\3\2\2\2\b[\3\2\2\2\ni\3\2\2\2\fk\3\2\2\2\16n\3\2\2" + + "\2\20t\3\2\2\2\22v\3\2\2\2\24x\3\2\2\2\26z\3\2\2\2\30\u0088\3\2\2\2\32" + + "\u008a\3\2\2\2\34\u008d\3\2\2\2\36\u0091\3\2\2\2 \u0096\3\2\2\2\"\u009c" + + "\3\2\2\2$\u00a8\3\2\2\2&\u00ae\3\2\2\2(\u00b4\3\2\2\2*\u00b6\3\2\2\2," + + "\u00bb\3\2\2\2.\u00bd\3\2\2\2\60\u00c0\3\2\2\2\62\u00c7\3\2\2\2\64\u00d3" + + "\3\2\2\2\66\67\7\3\2\2\67;\7\4\2\28:\5\4\3\298\3\2\2\2:=\3\2\2\2;9\3\2" + + "\2\2;<\3\2\2\2@\5\6\4\2?>\3\2\2\2@C\3\2\2\2A?\3\2" + + "\2\2AB\3\2\2\2BD\3\2\2\2CA\3\2\2\2DE\7\5\2\2E\3\3\2\2\2FG\7\3\2\2GH\7" + + "\6\2\2HI\5\20\t\2IJ\5\22\n\2JK\7\5\2\2K\5\3\2\2\2LM\7\3\2\2MN\7\7\2\2" + + "NO\5\24\13\2OS\7\3\2\2PR\5\b\5\2QP\3\2\2\2RU\3\2\2\2SQ\3\2\2\2ST\3\2\2" + + "\2TV\3\2\2\2US\3\2\2\2VW\7\5\2\2WX\5\n\6\2XY\5\30\r\2YZ\7\5\2\2Z\7\3\2" + + "\2\2[\\\7\3\2\2\\]\5\26\f\2]^\5\n\6\2^_\7\5\2\2_\t\3\2\2\2`j\5\20\t\2" + + "ab\7\3\2\2bc\5\16\b\2cd\7\5\2\2dj\3\2\2\2ef\7\3\2\2fg\5\f\7\2gh\7\5\2" + + "\2hj\3\2\2\2i`\3\2\2\2ia\3\2\2\2ie\3\2\2\2j\13\3\2\2\2kl\7\b\2\2lm\5\n" + + "\6\2m\r\3\2\2\2np\7\t\2\2oq\5\n\6\2po\3\2\2\2qr\3\2\2\2rp\3\2\2\2rs\3" + + "\2\2\2s\17\3\2\2\2tu\7\26\2\2u\21\3\2\2\2vw\7\30\2\2w\23\3\2\2\2xy\7\26" + + "\2\2y\25\3\2\2\2z{\7\26\2\2{\27\3\2\2\2|\u0089\5(\25\2}\u0089\5&\24\2" + + "~\u0089\5\32\16\2\177\u0089\5\34\17\2\u0080\u0089\5\36\20\2\u0081\u0089" + + "\5 \21\2\u0082\u0089\5\"\22\2\u0083\u0089\5$\23\2\u0084\u0085\7\3\2\2" + + "\u0085\u0086\5\30\r\2\u0086\u0087\7\5\2\2\u0087\u0089\3\2\2\2\u0088|\3" + + "\2\2\2\u0088}\3\2\2\2\u0088~\3\2\2\2\u0088\177\3\2\2\2\u0088\u0080\3\2" + + "\2\2\u0088\u0081\3\2\2\2\u0088\u0082\3\2\2\2\u0088\u0083\3\2\2\2\u0088" + + "\u0084\3\2\2\2\u0089\31\3\2\2\2\u008a\u008b\7\20\2\2\u008b\u008c\5\30" + + "\r\2\u008c\33\3\2\2\2\u008d\u008e\7\21\2\2\u008e\u008f\5\30\r\2\u008f" + + "\u0090\5\30\r\2\u0090\35\3\2\2\2\u0091\u0092\7\22\2\2\u0092\u0093\5\30" + + "\r\2\u0093\u0094\5\30\r\2\u0094\u0095\5\30\r\2\u0095\37\3\2\2\2\u0096" + + "\u0098\7\23\2\2\u0097\u0099\5\30\r\2\u0098\u0097\3\2\2\2\u0099\u009a\3" + + "\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b!\3\2\2\2\u009c\u009d" + + "\7\17\2\2\u009d\u009f\7\3\2\2\u009e\u00a0\5\b\5\2\u009f\u009e\3\2\2\2" + + "\u00a0\u00a1\3\2\2\2\u00a1\u009f\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\u00a3" + + "\3\2\2\2\u00a3\u00a4\7\5\2\2\u00a4\u00a5\7\3\2\2\u00a5\u00a6\5\30\r\2" + + "\u00a6\u00a7\7\5\2\2\u00a7#\3\2\2\2\u00a8\u00aa\7\26\2\2\u00a9\u00ab\5" + + "\30\r\2\u00aa\u00a9\3\2\2\2\u00ab\u00ac\3\2\2\2\u00ac\u00aa\3\2\2\2\u00ac" + + "\u00ad\3\2\2\2\u00ad%\3\2\2\2\u00ae\u00af\7\26\2\2\u00af\'\3\2\2\2\u00b0" + + "\u00b5\5*\26\2\u00b1\u00b5\5,\27\2\u00b2\u00b5\5.\30\2\u00b3\u00b5\5\60" + + "\31\2\u00b4\u00b0\3\2\2\2\u00b4\u00b1\3\2\2\2\u00b4\u00b2\3\2\2\2\u00b4" + + "\u00b3\3\2\2\2\u00b5)\3\2\2\2\u00b6\u00b7\t\2\2\2\u00b7+\3\2\2\2\u00b8" + + "\u00b9\7\n\2\2\u00b9\u00bc\7\30\2\2\u00ba\u00bc\7\30\2\2\u00bb\u00b8\3" + + "\2\2\2\u00bb\u00ba\3\2\2\2\u00bc-\3\2\2\2\u00bd\u00be\t\3\2\2\u00be\u00bf" + + "\7\30\2\2\u00bf/\3\2\2\2\u00c0\u00c1\7\13\2\2\u00c1\u00c2\7\f\2\2\u00c2" + + "\u00c3\7\3\2\2\u00c3\u00c4\7\b\2\2\u00c4\u00c5\5\n\6\2\u00c5\u00c6\7\5" + + "\2\2\u00c6\61\3\2\2\2\u00c7\u00cd\7\3\2\2\u00c8\u00c9\7\3\2\2\u00c9\u00ca" + + "\5\30\r\2\u00ca\u00cb\5\30\r\2\u00cb\u00cc\7\5\2\2\u00cc\u00ce\3\2\2\2" + + "\u00cd\u00c8\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\u00cd\3\2\2\2\u00cf\u00d0" + + "\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\7\5\2\2\u00d2\63\3\2\2\2\u00d3" + + "\u00d7\7\3\2\2\u00d4\u00d6\7\26\2\2\u00d5\u00d4\3\2\2\2\u00d6\u00d9\3" + + "\2\2\2\u00d7\u00d5\3\2\2\2\u00d7\u00d8\3\2\2\2\u00d8\u00da\3\2\2\2\u00d9" + + "\u00d7\3\2\2\2\u00da\u00db\7\5\2\2\u00db\65\3\2\2\2\17;ASir\u0088\u009a" + + "\u00a1\u00ac\u00b4\u00bb\u00cf\u00d7"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + + static + { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) + { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtVisitor.java new file mode 100644 index 000000000..80ec955d8 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/SmtVisitor.java @@ -0,0 +1,222 @@ +// Generated from Smt.g4 by ANTLR 4.7.2 +package edu.uiowa.smt.parser.antlr; + +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link SmtParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface SmtVisitor extends ParseTreeVisitor +{ + /** + * Visit a parse tree produced by {@link SmtParser#model}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitModel(SmtParser.ModelContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#sortDeclaration}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitSortDeclaration(SmtParser.SortDeclarationContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#functionDefinition}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunctionDefinition(SmtParser.FunctionDefinitionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#variableDeclaration}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariableDeclaration(SmtParser.VariableDeclarationContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#sort}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitSort(SmtParser.SortContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#setSort}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitSetSort(SmtParser.SetSortContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#tupleSort}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitTupleSort(SmtParser.TupleSortContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#sortName}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitSortName(SmtParser.SortNameContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#arity}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitArity(SmtParser.ArityContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#functionName}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunctionName(SmtParser.FunctionNameContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#variableName}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariableName(SmtParser.VariableNameContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#expression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitExpression(SmtParser.ExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#unaryExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitUnaryExpression(SmtParser.UnaryExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#binaryExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitBinaryExpression(SmtParser.BinaryExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#ternaryExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitTernaryExpression(SmtParser.TernaryExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#multiArityExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitMultiArityExpression(SmtParser.MultiArityExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#quantifiedExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitQuantifiedExpression(SmtParser.QuantifiedExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#functionCallExpression}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunctionCallExpression(SmtParser.FunctionCallExpressionContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#variable}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariable(SmtParser.VariableContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#constant}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitConstant(SmtParser.ConstantContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#boolConstant}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitBoolConstant(SmtParser.BoolConstantContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#integerConstant}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitIntegerConstant(SmtParser.IntegerConstantContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#uninterpretedConstant}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitUninterpretedConstant(SmtParser.UninterpretedConstantContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#emptySet}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitEmptySet(SmtParser.EmptySetContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#getValue}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetValue(SmtParser.GetValueContext ctx); + + /** + * Visit a parse tree produced by {@link SmtParser#getUnsatCore}. + * + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetUnsatCore(SmtParser.GetUnsatCoreContext ctx); +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr-4.7.2-complete.jar b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr-4.7.2-complete.jar new file mode 100644 index 000000000..9794f19b2 Binary files /dev/null and b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr-4.7.2-complete.jar differ diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr.bat b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr.bat new file mode 100644 index 000000000..4f976e36b --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlr.bat @@ -0,0 +1 @@ +java -jar antlr-4.7.2-complete.jar Smt.g4 -visitor -package edu.uiowa.smt.parser.antlr \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlrForGui.bat b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlrForGui.bat new file mode 100644 index 000000000..df48608d3 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/antlrForGui.bat @@ -0,0 +1 @@ +java -jar antlr-4.7.2-complete.jar Smt.g4 -visitor \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/compile.bat b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/compile.bat new file mode 100644 index 000000000..7b91e4b5d --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/compile.bat @@ -0,0 +1 @@ +javac *.java -cp antlr-4.7.2-complete.jar \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/grun.bat b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/grun.bat new file mode 100644 index 000000000..42844124f --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/grun.bat @@ -0,0 +1 @@ +java -cp ".;antlr-4.7.2-complete.jar" org.antlr.v4.gui.TestRig Smt model test.txt -gui diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/test.txt b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/test.txt new file mode 100644 index 000000000..151e08d0a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/parser/antlr/test.txt @@ -0,0 +1,20 @@ +(model +; cardinality of Atom is 3 +(declare-sort Atom 0) +; rep: @uc_Atom_0 +; rep: @uc_Atom_1 +; rep: @uc_Atom_2 +(declare-sort UnaryIntTup 0) +(declare-sort BinaryIntTup 0) +(declare-sort TernaryIntTup 0) +(define-fun value_of_unaryIntTup ((BOUND_VARIABLE_940 UnaryIntTup)) (Tuple Int) (mkTuple 0)) +(define-fun value_of_binaryIntTup ((BOUND_VARIABLE_949 BinaryIntTup)) (Tuple Int Int) (mkTuple 0 0)) +(define-fun value_of_ternaryIntTup ((BOUND_VARIABLE_958 TernaryIntTup)) (Tuple Int Int Int) (mkTuple 0 0 0)) +(define-fun atomNone () (Set (Tuple Atom)) (as emptyset (Set (Tuple Atom)))) +(define-fun atomUniv () (Set (Tuple Atom)) (union (union (singleton (mkTuple @uc_Atom_0)) (singleton (mkTuple @uc_Atom_1))) (singleton (mkTuple @uc_Atom_2)))) +(define-fun atomIden () (Set (Tuple Atom Atom)) (union (union (singleton (mkTuple @uc_Atom_0 @uc_Atom_0)) (singleton (mkTuple @uc_Atom_1 @uc_Atom_1))) (singleton (mkTuple @uc_Atom_2 @uc_Atom_2)))) +(define-fun this_A () (Set (Tuple Atom)) (union (union (singleton (mkTuple @uc_Atom_0)) (singleton (mkTuple @uc_Atom_1))) (singleton (mkTuple @uc_Atom_2)))) +(define-fun this_B () (Set (Tuple Atom)) (singleton (mkTuple @uc_Atom_1))) +(define-fun this_C () (Set (Tuple Atom)) (singleton (mkTuple @uc_Atom_2))) +(define-fun this_D () (Set (Tuple Atom)) (singleton (mkTuple @uc_Atom_0))) +) \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrettyPrinter.java b/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrettyPrinter.java new file mode 100644 index 000000000..d5c9fe12f --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrettyPrinter.java @@ -0,0 +1,152 @@ +package edu.uiowa.smt.printers; + +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.Map; + +public class SmtLibPrettyPrinter extends SmtLibPrinter +{ + private int tabsCount = 0; + + private void printTabs() + { + for (int i = 0; i < tabsCount; i++) + { + stringBuilder.append(" "); + } + } + + public SmtLibPrettyPrinter(SmtSettings smtSettings) + { + super(smtSettings); + } + + public SmtLibPrettyPrinter() + { + super(); + } + + @Override + public void visit(SmtUnaryExpr unaryExpression) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("(" + unaryExpression.getOp() + " "); + tabsCount++; + this.visit(unaryExpression.getExpr()); + stringBuilder.append(")"); + tabsCount -= 2; + + } + + @Override + public void visit(SmtBinaryExpr expr) + { + if (expr.getOp() != SmtBinaryExpr.Op.TUPSEL) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("(" + expr.getOp() + " "); + tabsCount++; + this.visit(expr.getA()); + stringBuilder.append(" "); + this.visit(expr.getB()); + stringBuilder.append(")"); + tabsCount -= 2; + } + else + { + stringBuilder.append("((_ " + expr.getOp() + " "); + stringBuilder.append(((IntConstant) expr.getA()).getValue()); + stringBuilder.append(") "); + this.visit(expr.getB()); + stringBuilder.append(")"); + } + } + + @Override + public void visit(SmtMultiArityExpr multiArityExpression) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("(" + multiArityExpression.getOp() + " "); + tabsCount++; + if (multiArityExpression.getExprs().size() == 1) + { + this.visit(multiArityExpression.getExprs().get(0)); + } + else if (multiArityExpression.getExprs().size() > 1) + { + for (int i = 0; i < multiArityExpression.getExprs().size() - 1; ++i) + { + this.visit(multiArityExpression.getExprs().get(i)); + stringBuilder.append(" "); + } + this.visit(multiArityExpression.getExprs().get(multiArityExpression.getExprs().size() - 1)); + } + else + { + throw new RuntimeException(""); + } + stringBuilder.append(")"); + tabsCount -= 2; + } + + @Override + public void visit(SmtQtExpr smtQtExpr) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("(" + smtQtExpr.getOp() + " ("); + for (SmtVariable boundVariable : smtQtExpr.getVariables()) + { + this.visit(boundVariable); + } + stringBuilder.append(") "); + tabsCount++; + this.visit(smtQtExpr.getExpr()); + stringBuilder.append(")"); + tabsCount -= 2; + } + + @Override + public void visit(SmtLetExpr let) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("(let ("); + for (Map.Entry letVar : let.getLetVariables().entrySet()) + { + tabsCount++; + stringBuilder.append("\n"); + printTabs(); + stringBuilder.append("("); + stringBuilder.append(TranslatorUtils.sanitizeWithBars(letVar.getKey())).append(" "); + this.visit(letVar.getValue()); + stringBuilder.append(")"); + tabsCount--; + } + stringBuilder.append(") "); + tabsCount++; + this.visit(let.getSmtExpr()); + stringBuilder.append(")"); + tabsCount -= 2; + } + + @Override + public void visit(SmtExpr smtExpr) + { + super.visit(smtExpr); + if (!smtExpr.getComment().isEmpty()) + { + stringBuilder.append("; " + smtExpr.getComment() + "\n"); + printTabs(); + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrinter.java b/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrinter.java new file mode 100644 index 000000000..d6f79b7b2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/printers/SmtLibPrinter.java @@ -0,0 +1,409 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.printers; + +import edu.uiowa.smt.TranslatorUtils; +import edu.uiowa.smt.smtAst.*; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class SmtLibPrinter extends AbstractSmtAstVisitor +{ + public final static String CHECK_SAT = "(check-sat)"; + public final static String GET_MODEL = "(get-model)"; + public final static String GET_UNSAT_CORE = "(get-unsat-core)"; + public final static String BLOCK_MODEL = "(block-model)"; + public final static String PUSH = "(push 1)"; + public final static String POP = "(pop 1)"; + protected SmtSettings smtSettings; + protected StringBuilder stringBuilder = new StringBuilder(); + + public SmtLibPrinter(SmtSettings smtSettings) + { + this.smtSettings = smtSettings; + } + + public SmtLibPrinter() + { + this.smtSettings = SmtSettings.Default; + } + + + public String getSmtLib() + { + return stringBuilder.toString(); + } + + + protected void initializeProgram() + { + visit(smtSettings); + } + + public void visit(SmtScript script) + { + if (script.getParent() == null) + { + initializeProgram(); + } + + for (Sort sort : script.getSorts()) + { + if (sort instanceof UninterpretedSort) + { + stringBuilder.append("(declare-sort "); + stringBuilder.append(sort.getName()); + stringBuilder.append(" 0)\n"); + } + } + for (FunctionDeclaration declaration : script.getFunctions()) + { + if (declaration instanceof FunctionDefinition) + { + this.visit((FunctionDefinition) declaration); + } + else + { + this.visit(declaration); + } + } + + for (Assertion assertion : script.getAssertions()) + { + this.visit(assertion); + } + } + + @Override + public void visit(SmtBinaryExpr expr) + { + if (expr.getOp() != SmtBinaryExpr.Op.TUPSEL) + { + stringBuilder.append("(" + expr.getOp() + " "); + this.visit(expr.getA()); + stringBuilder.append(" "); + this.visit(expr.getB()); + stringBuilder.append(")"); + } + else + { + stringBuilder.append("((_ " + expr.getOp() + " "); + stringBuilder.append(((IntConstant) expr.getA()).getValue()); + stringBuilder.append(") "); + this.visit(expr.getB()); + stringBuilder.append(")"); + } + } + + @Override + public void visit(IntSort intSort) + { + stringBuilder.append(intSort.getName()); + } + + @Override + public void visit(SmtQtExpr smtQtExpr) + { + stringBuilder.append("(" + smtQtExpr.getOp() + " ("); + for (SmtVariable boundVariable : smtQtExpr.getVariables()) + { + this.visit(boundVariable); + } + stringBuilder.append(") "); + this.visit(smtQtExpr.getExpr()); + stringBuilder.append(")"); + } + + @Override + public void visit(RealSort realSort) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void visit(SetSort setSort) + { + stringBuilder.append("(Set "); + this.visit(setSort.elementSort); + stringBuilder.append(")"); + } + + @Override + public void visit(StringSort stringSort) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void visit(TupleSort tupleSort) + { + stringBuilder.append("(Tuple "); + for (int i = 0; i < tupleSort.elementSorts.size() - 1; ++i) + { + this.visit(tupleSort.elementSorts.get(i)); + stringBuilder.append(" "); + } + this.visit(tupleSort.elementSorts.get(tupleSort.elementSorts.size() - 1)); + stringBuilder.append(")"); + } + + @Override + public void visit(SmtUnaryExpr unaryExpression) + { + stringBuilder.append("(" + unaryExpression.getOp() + " "); + this.visit(unaryExpression.getExpr()); + stringBuilder.append(")"); + } + + @Override + public void visit(UninterpretedSort uninterpretedSort) + { + stringBuilder.append(uninterpretedSort.getName()); + } + + @Override + public void visit(IntConstant intConstant) + { + int value = Integer.parseInt(intConstant.getValue()); + if (value >= 0) + { + stringBuilder.append(intConstant.getValue()); + } + else + { + stringBuilder.append("(- " + -value + ")"); + } + } + + @Override + public void visit(Variable variable) + { + stringBuilder.append(TranslatorUtils.sanitizeWithBars(variable.getDeclaration())); + } + + @Override + public void visit(FunctionDeclaration functionDeclaration) + { + stringBuilder.append("(declare-fun "); + stringBuilder.append(TranslatorUtils.sanitizeWithBars(functionDeclaration) + " ("); + + List inputSorts = functionDeclaration.getInputSorts(); + for (int i = 0; i < inputSorts.size(); i++) + { + this.visit(inputSorts.get(i)); + } + stringBuilder.append(") "); + this.visit(functionDeclaration.getSort()); + stringBuilder.append(")\n"); + } + + @Override + public void visit(FunctionDefinition definition) + { + stringBuilder.append("(define-fun ").append(TranslatorUtils.sanitizeWithBars(definition)).append(" ("); + for (SmtVariable bdVar : definition.inputVariables) + { + this.visit(bdVar); + } + stringBuilder.append(") "); + this.visit(definition.getSort()); + stringBuilder.append(" ").append("\n"); + this.visit(definition.smtExpr); + stringBuilder.append(")"); + stringBuilder.append("\n"); + } + + @Override + public void visit(BoolConstant aThis) + { + stringBuilder.append(aThis.getValue()); + } + + @Override + public void visit(Assertion assertion) + { + stringBuilder.append("\n"); + if (!assertion.getComment().isEmpty()) + { + // print comment + stringBuilder.append("; " + assertion.getComment() + "\n"); + } + + stringBuilder.append("(assert "); + if (smtSettings.produceUnsatCore && !assertion.getSymbolicName().isEmpty()) + { + stringBuilder.append("(! "); + } + this.visit(assertion.getSmtExpr()); + if (smtSettings.produceUnsatCore && !assertion.getSymbolicName().isEmpty()) + { + stringBuilder.append("\n :named |" + + assertion.getSymbolicName().replace("\\", "/") + + "|))\n"); + } + else + { + stringBuilder.append(")\n"); + } + } + + @Override + public void visit(SmtMultiArityExpr multiArityExpression) + { + stringBuilder.append("(" + multiArityExpression.getOp() + " "); + if (multiArityExpression.getExprs().size() == 1) + { + this.visit(multiArityExpression.getExprs().get(0)); + } + else if (multiArityExpression.getExprs().size() > 1) + { + for (int i = 0; i < multiArityExpression.getExprs().size() - 1; ++i) + { + this.visit(multiArityExpression.getExprs().get(i)); + stringBuilder.append(" "); + } + this.visit(multiArityExpression.getExprs().get(multiArityExpression.getExprs().size() - 1)); + } + else + { + throw new RuntimeException(""); + } + stringBuilder.append(")"); + } + + @Override + public void visit(SmtCallExpr smtCallExpr) + { + if (smtCallExpr.getArguments().size() > 0) + { + stringBuilder.append("("); + stringBuilder.append(TranslatorUtils.sanitizeWithBars(smtCallExpr.getFunction())); + stringBuilder.append(" "); + for (int i = 0; i < smtCallExpr.getArguments().size() - 1; ++i) + { + this.visit(smtCallExpr.getArguments().get(i)); + stringBuilder.append(" "); + } + this.visit(smtCallExpr.getArguments().get(smtCallExpr.getArguments().size() - 1)); + stringBuilder.append(")"); + } + else + { + stringBuilder.append(TranslatorUtils.sanitizeWithBars(smtCallExpr.getFunction())); + } + } + + @Override + public void visit(SmtVariable variable) + { + stringBuilder.append("(" + TranslatorUtils.sanitizeWithBars(variable) + " "); + this.visit(variable.getSort()); + stringBuilder.append(")"); + } + + @Override + public void visit(BoolSort aThis) + { + stringBuilder.append(aThis.getName()); + } + + @Override + public void visit(SmtLetExpr let) + { + stringBuilder.append("(let ("); + for (Map.Entry letVar : let.getLetVariables().entrySet()) + { + stringBuilder.append("("); + stringBuilder.append(TranslatorUtils.sanitizeWithBars(letVar.getKey())).append(" "); + this.visit(letVar.getValue()); + stringBuilder.append(")"); + } + stringBuilder.append(") "); + this.visit(let.getSmtExpr()); + stringBuilder.append(")"); + } + + @Override + public void visit(SmtIteExpr ite) + { + stringBuilder.append("(ite "); + this.visit(ite.getCondExpr()); + stringBuilder.append(" "); + this.visit(ite.getThenExpr()); + stringBuilder.append(" "); + this.visit(ite.getElseExpr()); + stringBuilder.append(")"); + + } + + @Override + public void visit(UninterpretedConstant uninterpretedConstant) + { + stringBuilder.append(uninterpretedConstant.getName()); + } + + @Override + public void visit(SmtSettings smtSettings) + { + for (String logic : smtSettings.getLogic()) + { + stringBuilder.append("(set-logic " + logic + ")\n"); + } + Map options = smtSettings.getSolverOptions(); + for (Map.Entry entry : options.entrySet()) + { + stringBuilder.append("(set-option "); + stringBuilder.append(":" + entry.getKey() + " "); + stringBuilder.append(entry.getValue() + ")\n"); + } + } + + public String printGetValue(SmtExpr smtExpr) + { + stringBuilder.append("(get-value ("); + visit(smtExpr); + stringBuilder.append("))"); + return stringBuilder.toString(); + } + + @Override + public void visit(SmtValues smtValues) + { + stringBuilder.append("("); + for (ExpressionValue value : smtValues.getValues()) + { + visit(value); + } + stringBuilder.append(")"); + } + + @Override + public void visit(ExpressionValue expressionValue) + { + stringBuilder.append("("); + visit(expressionValue.getSmtExpr()); + stringBuilder.append(" "); + visit(expressionValue.getValue()); + stringBuilder.append(")"); + } + + @Override + public void visit(SmtUnsatCore smtUnsatCore) + { + stringBuilder.append("(\n"); + for (String formula : smtUnsatCore.getCore()) + { + stringBuilder.append(formula + "\n"); + } + stringBuilder.append(")"); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/AbstractSmtAstVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/AbstractSmtAstVisitor.java new file mode 100644 index 000000000..1312f9e32 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/AbstractSmtAstVisitor.java @@ -0,0 +1,366 @@ +package edu.uiowa.smt.smtAst; + +import java.util.Map; + +abstract public class AbstractSmtAstVisitor implements SmtAstVisitor +{ + @Override + public void visit(SmtAst smtAst) + { + if (smtAst instanceof Assertion) + { + this.visit((Assertion) smtAst); + } + else if (smtAst instanceof Declaration) + { + this.visit((Declaration) smtAst); + } + else if (smtAst instanceof ExpressionValue) + { + this.visit((ExpressionValue) smtAst); + } + else if (smtAst instanceof SmtExpr) + { + this.visit((SmtExpr) smtAst); + } + else if (smtAst instanceof SmtScript) + { + this.visit((SmtScript) smtAst); + } + else if (smtAst instanceof SmtModel) + { + this.visit((SmtModel) smtAst); + } + else if (smtAst instanceof SmtSettings) + { + this.visit((SmtSettings) smtAst); + } + else if (smtAst instanceof SmtUnsatCore) + { + this.visit((SmtUnsatCore) smtAst); + } + else if (smtAst instanceof SmtValues) + { + this.visit((SmtValues) smtAst); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public void visit(Declaration declaration) + { + if (declaration instanceof FunctionDefinition) + { + this.visit((FunctionDefinition) declaration); + } + else if (declaration instanceof FunctionDeclaration) + { + this.visit((FunctionDeclaration) declaration); + } + else if (declaration instanceof SmtVariable) + { + this.visit((SmtVariable) declaration); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public void visit(SmtExpr smtExpr) + { + if (smtExpr instanceof Variable) + { + this.visit((Variable) smtExpr); + } + else if (smtExpr instanceof SmtUnaryExpr) + { + this.visit((SmtUnaryExpr) smtExpr); + } + else if (smtExpr instanceof SmtBinaryExpr) + { + this.visit((SmtBinaryExpr) smtExpr); + } + else if (smtExpr instanceof SmtMultiArityExpr) + { + this.visit((SmtMultiArityExpr) smtExpr); + } + else if (smtExpr instanceof SmtQtExpr) + { + this.visit((SmtQtExpr) smtExpr); + } + else if (smtExpr instanceof Sort) + { + this.visit((Sort) smtExpr); + } + else if (smtExpr instanceof IntConstant) + { + this.visit((IntConstant) smtExpr); + } + else if (smtExpr instanceof SmtCallExpr) + { + this.visit((SmtCallExpr) smtExpr); + } + else if (smtExpr instanceof BoolConstant) + { + this.visit((BoolConstant) smtExpr); + } + else if (smtExpr instanceof SmtLetExpr) + { + this.visit((SmtLetExpr) smtExpr); + } + else if (smtExpr instanceof SmtIteExpr) + { + this.visit((SmtIteExpr) smtExpr); + } + else if (smtExpr instanceof UninterpretedConstant) + { + this.visit((UninterpretedConstant) smtExpr); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public void visit(Sort sort) + { + if (sort instanceof UninterpretedSort) + { + this.visit((UninterpretedSort) sort); + } + else if (sort instanceof SetSort) + { + this.visit((SetSort) sort); + } + else if (sort instanceof TupleSort) + { + this.visit((TupleSort) sort); + } + else if (sort instanceof IntSort) + { + this.visit((IntSort) sort); + } + else if (sort instanceof RealSort) + { + this.visit((RealSort) sort); + } + else if (sort instanceof StringSort) + { + this.visit((StringSort) sort); + } + else if (sort instanceof BoolSort) + { + this.visit((BoolSort) sort); + } + else + { + throw new UnsupportedOperationException(); + } + } + + @Override + public void visit(SmtModel model) + { + } + + @Override + public void visit(SmtScript script) + { + for (Sort sort : script.getSorts()) + { + visit(sort); + } + for (Declaration function : script.getFunctions()) + { + visit(function); + } + for (Assertion assertion : script.getAssertions()) + { + visit(assertion); + } + } + + @Override + public void visit(SmtBinaryExpr expr) + { + visit(expr.getA()); + visit(expr.getB()); + } + + @Override + public void visit(IntSort intSort) + { + } + + @Override + public void visit(SmtQtExpr quantifiedExpression) + { + for (SmtVariable boundVariable : quantifiedExpression.getVariables()) + { + this.visit(boundVariable); + } + this.visit(quantifiedExpression.getExpr()); + } + + @Override + public void visit(RealSort realSort) + { + + } + + @Override + public void visit(SetSort setSort) + { + visit(setSort.elementSort); + } + + @Override + public void visit(StringSort stringSort) + { + } + + @Override + public void visit(TupleSort tupleSort) + { + for (Sort sort : tupleSort.elementSorts) + { + visit(sort); + } + } + + @Override + public void visit(SmtUnaryExpr unaryExpression) + { + visit(unaryExpression.getExpr()); + } + + @Override + public void visit(UninterpretedSort uninterpretedSort) + { + } + + @Override + public void visit(IntConstant intConstant) + { + } + + @Override + public void visit(Variable variable) + { + } + + @Override + public void visit(FunctionDeclaration functionDeclaration) + { + for (Sort sort : functionDeclaration.getInputSorts()) + { + visit(sort); + } + visit(functionDeclaration.getSort()); + } + + @Override + public void visit(FunctionDefinition functionDefinition) + { + for (SmtVariable variable : functionDefinition.getInputVariables()) + { + visit(variable); + } + visit(functionDefinition.getBody()); + visit(functionDefinition.getSort()); + } + + @Override + public void visit(BoolConstant booleanConstant) + { + } + + @Override + public void visit(Assertion assertion) + { + visit(assertion.getSmtExpr()); + } + + @Override + public void visit(SmtMultiArityExpr expression) + { + for (SmtExpr expr : expression.getExprs()) + { + visit(expr); + } + } + + @Override + public void visit(SmtCallExpr callExpression) + { + for (SmtExpr expr : callExpression.getArguments()) + { + visit(expr); + } + } + + @Override + public void visit(SmtVariable smtVariable) + { + visit(smtVariable.getSort()); + } + + @Override + public void visit(BoolSort boolSort) + { + } + + @Override + public void visit(SmtLetExpr letExpression) + { + for (Map.Entry entry : letExpression.getLetVariables().entrySet()) + { + visit(entry.getKey()); + visit(entry.getValue()); + } + visit(letExpression.getSmtExpr()); + } + + @Override + public void visit(SmtIteExpr iteExpression) + { + visit(iteExpression.getCondExpr()); + visit(iteExpression.getThenExpr()); + visit(iteExpression.getElseExpr()); + } + + @Override + public void visit(UninterpretedConstant uninterpretedConstant) + { + visit(uninterpretedConstant.getSort()); + } + + @Override + public void visit(SmtSettings smtSettings) + { + } + + @Override + public void visit(SmtValues smtValues) + { + + } + + @Override + public void visit(ExpressionValue expressionValue) + { + + } + + @Override + public void visit(SmtUnsatCore smtUnsatCore) + { + + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Assertion.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Assertion.java new file mode 100644 index 000000000..1e682dd9a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Assertion.java @@ -0,0 +1,46 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class Assertion extends SmtAst +{ + private final SmtExpr smtExpr; + + private final String comment; + + private final String symbolicName; + + public Assertion(String symbolicName, String comment, SmtExpr smtExpr) + { + this.symbolicName = symbolicName; + this.comment = comment; + this.smtExpr = smtExpr; + } + + public String getComment() + { + return this.comment; + } + + public SmtExpr getSmtExpr() + { + return this.smtExpr; + } + + public String getSymbolicName() + { + return symbolicName; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolConstant.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolConstant.java new file mode 100644 index 000000000..5ca4341a2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolConstant.java @@ -0,0 +1,103 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class BoolConstant extends Constant +{ + private final boolean value; + + public static final BoolConstant True = new BoolConstant(true); + public static final BoolConstant False = new BoolConstant(false); + + private BoolConstant(boolean value) + { + this.value = value; + } + + public String getValue() + { + return String.valueOf(this.value); + } + + public boolean getBooleanValue() + { + return value; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return AbstractTranslator.boolSort; + } + + @Override + public SmtExpr evaluate(Map functions) + { + return this; + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof BoolConstant)) + { + return false; + } + BoolConstant booleanObject = (BoolConstant) object; + return value == booleanObject.value; + } + + @Override + public List getFreeVariables() + { + return new ArrayList<>(); + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + return this; + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + return this; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolSort.java new file mode 100644 index 000000000..450994915 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/BoolSort.java @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package edu.uiowa.smt.smtAst; + +/** + * @author Paul Meng, Mudathir Mahgoub + */ +public class BoolSort extends Sort +{ + + private static BoolSort instance = new BoolSort(); + + private BoolSort() + { + super("Bool", 0); + } + + public static BoolSort getInstance() + { + return instance; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof BoolSort)) + { + return false; + } + return true; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Constant.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Constant.java new file mode 100644 index 000000000..a9c5022e0 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Constant.java @@ -0,0 +1,5 @@ +package edu.uiowa.smt.smtAst; + +abstract public class Constant extends SmtExpr +{ +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ConstantDefinition.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ConstantDefinition.java new file mode 100644 index 000000000..b038d63c1 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ConstantDefinition.java @@ -0,0 +1,23 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class ConstantDefinition extends FunctionDefinition +{ + public ConstantDefinition(String name, Sort outputSort, SmtExpr smtExpr, boolean isOriginal) + { + super(name, outputSort, smtExpr, isOriginal); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Declaration.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Declaration.java new file mode 100644 index 000000000..7b7fd21ec --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Declaration.java @@ -0,0 +1,47 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +//ToDo: refactor Declaration into only Function and Variable and make them expressions +abstract public class Declaration extends SmtAst +{ + private final String name; + private final Sort sort; + private final boolean isOriginal; + + protected Variable variable; + + protected Declaration(String name, Sort sort, boolean isOriginal) + { + this.name = name; + this.sort = sort; + this.variable = new Variable(this); + this.isOriginal = isOriginal; + } + + public String getName() + { + return this.name; + } + + public Sort getSort() + { + return this.sort; + } + + public Variable getVariable() + { + return this.variable; + } + + public boolean isOriginal() + { + return isOriginal; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ExpressionValue.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ExpressionValue.java new file mode 100644 index 000000000..3ce28b823 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/ExpressionValue.java @@ -0,0 +1,29 @@ +package edu.uiowa.smt.smtAst; + +public class ExpressionValue extends SmtAst +{ + private final SmtExpr smtExpr; + private final SmtExpr value; + + public ExpressionValue(SmtExpr smtExpr, SmtExpr value) + { + this.smtExpr = smtExpr; + this.value = value; + } + + public SmtExpr getSmtExpr() + { + return smtExpr; + } + + public SmtExpr getValue() + { + return value; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDeclaration.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDeclaration.java new file mode 100644 index 000000000..6117a54a8 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDeclaration.java @@ -0,0 +1,103 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FunctionDeclaration extends Declaration +{ + private final List inputSorts; + + public FunctionDeclaration(String name, List inputSort, Sort outputSort, boolean isOriginal) + { + super(name, outputSort, isOriginal); + + this.inputSorts = inputSort; + + if (this.inputSorts.isEmpty()) + { + variable = new Variable(this); + } + else + { + variable = null; + } + } + + public FunctionDeclaration(String name, Sort inputSort, Sort outputSort, boolean isOriginal) + { + super(name, outputSort, isOriginal); + this.inputSorts = Arrays.asList(inputSort); + + if (this.inputSorts.isEmpty()) + { + variable = new Variable(this); + } + else + { + variable = null; + } + } + + public FunctionDeclaration(String name, Sort outputSort, boolean isOriginal) + { + super(name, outputSort, isOriginal); + this.inputSorts = new ArrayList<>(); + this.variable = new Variable(this); + } + + public FunctionDeclaration(String name, boolean isOriginal, Sort outputSort, Sort... inputSorts) + { + super(name, outputSort, isOriginal); + this.inputSorts = Arrays.asList(inputSorts); + + if (this.inputSorts.isEmpty()) + { + variable = new Variable(this); + } + else + { + variable = null; + } + } + + public List getInputSorts() + { + return this.inputSorts; + } + + @Override + public Variable getVariable() + { + if (this.variable != null) + { + return this.variable; + } + // this is a function call + throw new UnsupportedOperationException(); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public Sort getSort(int index) + { + if (index >= this.inputSorts.size()) + { + throw new RuntimeException("Argument index out of range"); + } + + return inputSorts.get(index); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDefinition.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDefinition.java new file mode 100644 index 000000000..835df6fac --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/FunctionDefinition.java @@ -0,0 +1,72 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.printers.SmtLibPrinter; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class FunctionDefinition extends FunctionDeclaration +{ + public SmtExpr smtExpr; + public final List inputVariables; + + public FunctionDefinition(String name, List inputVariables, Sort outputSort, SmtExpr smtExpr, boolean isOriginal) + { + super(name, inputVariables.stream().map(v -> v.getSort()).collect(Collectors.toList()), outputSort, isOriginal); + this.inputVariables = inputVariables; + this.smtExpr = smtExpr; + } + + public FunctionDefinition(String name, SmtVariable inputVariable, Sort outputSort, SmtExpr smtExpr, boolean isOriginal) + { + super(name, inputVariable.getSort(), outputSort, isOriginal); + this.inputVariables = Collections.singletonList(inputVariable); + this.smtExpr = smtExpr; + } + + public FunctionDefinition(String name, Sort outputSort, SmtExpr smtExpr, boolean isOriginal, SmtVariable... inputVariables) + { + super(name, Arrays.stream(inputVariables).map(v -> v.getSort()).collect(Collectors.toList()), outputSort, isOriginal); + this.inputVariables = Arrays.asList(inputVariables); + this.smtExpr = smtExpr; + } + + public List getInputVariables() + { + return this.inputVariables; + } + + public SmtExpr getBody() + { + return this.smtExpr; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public String toString() + { + SmtLibPrinter printer = new SmtLibPrinter(); + printer.visit(this); + return printer.getSmtLib(); + } + + public void setBody(SmtExpr smtExpr) + { + this.smtExpr = smtExpr; + } +} \ No newline at end of file diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntConstant.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntConstant.java new file mode 100644 index 000000000..86b185c16 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntConstant.java @@ -0,0 +1,122 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class IntConstant extends Constant +{ + private final BigInteger value; + + private IntConstant(int value) + { + this.value = new BigInteger(String.valueOf(value)); + } + + public static IntConstant getInstance(int value) + { + return new IntConstant(value); + } + + public static SmtExpr getSingletonTuple(int value) + { + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, + new IntConstant(value)); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tuple); + return singleton; + } + + public static SmtExpr getSingletonTuple(IntConstant intConstant) + { + SmtExpr tuple = new SmtMultiArityExpr(SmtMultiArityExpr.Op.MKTUPLE, + intConstant); + SmtExpr singleton = SmtUnaryExpr.Op.SINGLETON.make(tuple); + return singleton; + } + + public IntConstant(String value) + { + this.value = new BigInteger(value); + } + + public String getValue() + { + return this.value.toString(); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return AbstractTranslator.intSort; + } + + @Override + public SmtExpr evaluate(Map functions) + { + return this; + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof IntConstant)) + { + return false; + } + IntConstant intConstant = (IntConstant) object; + return value.equals(intConstant.value); + } + + @Override + public List getFreeVariables() + { + return new ArrayList<>(); + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + return this; + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + return this; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntSort.java new file mode 100644 index 000000000..c3a092f72 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/IntSort.java @@ -0,0 +1,54 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class IntSort extends Sort +{ + private static IntSort instance = new IntSort(); + + private IntSort() + { + super("Int", 0); + } + + public static IntSort getInstance() + { + return instance; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof IntSort)) + { + return false; + } + return true; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/RealSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/RealSort.java new file mode 100644 index 000000000..45f9849ae --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/RealSort.java @@ -0,0 +1,47 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class RealSort extends Sort +{ + public RealSort() + { + super("Real", 0); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof RealSort)) + { + return false; + } + return true; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SetSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SetSort.java new file mode 100644 index 000000000..2203767e0 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SetSort.java @@ -0,0 +1,53 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class SetSort extends Sort +{ + public Sort elementSort; + + public SetSort(Sort elementSort) + { + super("Set", 0); + this.elementSort = elementSort; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + + if (!(object instanceof SetSort)) + { + return false; + } + + SetSort sort = (SetSort) object; + return sort.elementSort.equals(this.elementSort); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || elementSort.containsExpr(expr)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAst.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAst.java new file mode 100644 index 000000000..54114e893 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAst.java @@ -0,0 +1,24 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.printers.SmtLibPrinter; + +public abstract class SmtAst +{ + public abstract void accept(SmtAstVisitor visitor); + + @Override + public String toString() + { + SmtLibPrinter printer = new SmtLibPrinter(); + printer.visit(this); + return printer.getSmtLib(); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAstVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAstVisitor.java new file mode 100644 index 000000000..36687f6ba --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtAstVisitor.java @@ -0,0 +1,76 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public interface SmtAstVisitor +{ + void visit(SmtAst smtAst); + + void visit(Declaration declaration); + + void visit(SmtModel model); + + void visit(SmtScript script); + + void visit(SmtBinaryExpr expr); + + void visit(Sort sort); + + void visit(IntSort intSort); + + void visit(SmtQtExpr quantifiedExpression); + + void visit(RealSort realSort); + + void visit(SetSort setSort); + + void visit(StringSort stringSort); + + void visit(TupleSort tupleSort); + + void visit(SmtExpr smtExpr); + + void visit(SmtUnaryExpr unaryExpression); + + void visit(UninterpretedSort uninterpretedSort); + + void visit(IntConstant intConstant); + + void visit(Variable variable); + + void visit(FunctionDeclaration functionDeclaration); + + void visit(FunctionDefinition functionDefinition); + + void visit(BoolConstant booleanConstant); + + void visit(Assertion assertion); + + void visit(SmtMultiArityExpr expression); + + void visit(SmtCallExpr smtCallExpr); + + void visit(SmtVariable smtVariable); + + void visit(BoolSort boolSort); + + void visit(SmtLetExpr letExpression); + + void visit(SmtIteExpr iteExpression); + + void visit(UninterpretedConstant uninterpretedConstant); + + void visit(SmtSettings smtSettings); + + void visit(SmtValues smtValues); + + void visit(ExpressionValue expressionValue); + + void visit(SmtUnsatCore smtUnsatCore); +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtBinaryExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtBinaryExpr.java new file mode 100644 index 000000000..a19947329 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtBinaryExpr.java @@ -0,0 +1,474 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SmtBinaryExpr extends SmtExpr +{ + private final Op op; + private SmtExpr A; + private SmtExpr B; + + private SmtBinaryExpr(Op op, SmtExpr A, SmtExpr B) + { + this.op = op; + if (A == null) + { + throw new RuntimeException("Left expression is null"); + } + this.A = A; + if (B == null) + { + throw new RuntimeException("Right expression is null"); + } + this.B = B; + + checkTypes(); + } + + @Override + protected void checkTypes() + { + switch (op) + { + case IMPLIES: + { + if (A.getSort() != AbstractTranslator.boolSort) + { + throw new RuntimeException(String.format("Left expression sort '%1$s' is not boolean", A.getSort())); + } + if (B.getSort() != AbstractTranslator.boolSort) + { + throw new RuntimeException(String.format("Right expression sort '%1$s' is not boolean", B.getSort())); + } + } + break; + case PLUS: + case MINUS: + case MULTIPLY: + case DIVIDE: + case MOD: + case GTE: + case LTE: + case GT: + case LT: + { + if (A.getSort() != AbstractTranslator.intSort) + { + throw new RuntimeException(String.format("Left expression sort '%1$s' is not integer or set of integers", A.getSort())); + } + if (B.getSort() != AbstractTranslator.intSort) + { + throw new RuntimeException(String.format("Right expression sort '%1$s' is not integer or set of integers", B.getSort())); + } + } + break; + + case EQ: + case UNION: + case INTERSECTION: + case SETMINUS: + case SUBSET: + { + if (!A.getSort().equals(B.getSort())) + { + throw new RuntimeException(String.format("The sort of left expression sort '%1$s' is different than the sort of right expression '%2$s'", A.getSort(), B.getSort())); + } + } + break; + + case MEMBER: + { + if (B instanceof IntConstant) + { + B = IntConstant.getSingletonTuple((IntConstant) B); + } + + if (!(B.getSort() instanceof SetSort)) + { + throw new RuntimeException(String.format("The sort of right expression '%1$s' is not a set", B.getSort())); + } + + SetSort setSort = (SetSort) B.getSort(); + + if (!(A.getSort().equals(setSort.elementSort))) + { + throw new RuntimeException(String.format("The sort of left expression '%1$s' doesn't match the element sort of the right expression '%2$s'", A.getSort(), setSort.elementSort)); + } + } + break; + + case JOIN: + { + if (!(A.getSort() instanceof SetSort && + ((SetSort) A.getSort()).elementSort instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort of left expression '%1$s' is not a set of tuples", A.getSort())); + } + if (!(B.getSort() instanceof SetSort && + ((SetSort) B.getSort()).elementSort instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort of right expression '%1$s' is not a set of tuples", B.getSort())); + } + + TupleSort leftSort = (TupleSort) ((SetSort) A.getSort()).elementSort; + TupleSort rightSort = (TupleSort) ((SetSort) B.getSort()).elementSort; + + if (!(leftSort.elementSorts.get(leftSort.elementSorts.size() - 1).equals(rightSort.elementSorts.get(0)))) + { + throw new RuntimeException(String.format("The left and right sorts ('%1$s' and '%2$s') can't be joined", leftSort, rightSort)); + } + } + break; + case PRODUCT: + { + if (!(A.getSort() instanceof SetSort && + ((SetSort) A.getSort()).elementSort instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort of left expression '%1$s' is not a set of tuples", A.getSort())); + } + if (!(B.getSort() instanceof SetSort && + ((SetSort) B.getSort()).elementSort instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort of right expression '%1$s' is not a set of tuples", B.getSort())); + } + } + break; + case TUPSEL: + { + if (!(A instanceof IntConstant)) + { + throw new RuntimeException(String.format("The left expression '%1$s' is not a constant integer", A)); + } + if (!(B.getSort() instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort of right expression '%1$s' is not tuple", B.getSort())); + } + + int index = Integer.parseInt(((IntConstant) A).getValue()); + TupleSort sort = (TupleSort) B.getSort(); + if (index >= sort.elementSorts.size() || index < 0) + { + throw new RuntimeException(String.format("The index '%1$d' out of range", index)); + } + } + break; + default: + throw new UnsupportedOperationException(); + } + } + + public SmtExpr getA() + { + return this.A; + } + + public SmtExpr getB() + { + return this.B; + } + + public Op getOp() + { + return this.op; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public enum Op + { + IMPLIES("=>"), + PLUS("+"), + MINUS("-"), + MULTIPLY("*"), + DIVIDE("/"), + MOD("mod"), + EQ("="), + GTE(">="), + LTE("<="), + GT(">"), + LT("<"), + UNION("union"), + INTERSECTION("intersection"), + SETMINUS("setminus"), + MEMBER("member"), + SUBSET("subset"), + JOIN("join"), + PRODUCT("product"), + TUPSEL("tupSel"); + + private final String opStr; + + public SmtBinaryExpr make(SmtExpr left, SmtExpr right) + { + return new SmtBinaryExpr(this, left, right); + } + + Op(String op) + { + this.opStr = op; + } + + public static Op getOp(String operator) + { + switch (operator) + { + case "=>": + return IMPLIES; + case "+": + return PLUS; + case "-": + return MINUS; + case "*": + return MULTIPLY; + case "/": + return DIVIDE; + case "mod": + return MOD; + case "=": + return EQ; + case ">=": + return GTE; + case "<=": + return LTE; + case ">": + return GT; + case "<": + return LT; + case "union": + return UNION; + case "intersection": + return INTERSECTION; + case "setminus": + return SETMINUS; + case "member": + return MEMBER; + case "subset": + return SUBSET; + case "join": + return JOIN; + case "product": + return PRODUCT; + case "tupSel": + return TUPSEL; + default: + throw new UnsupportedOperationException("Operator " + operator + " is not defined"); + } + } + + @Override + public String toString() + { + return this.opStr; + } + } + + @Override + public Sort getSort() + { + switch (op) + { + case IMPLIES: + return AbstractTranslator.boolSort; + case PLUS: + return A.getSort() instanceof IntSort ? AbstractTranslator.intSort : AbstractTranslator.setOfUninterpretedIntTuple; + case MINUS: + return A.getSort() instanceof IntSort ? AbstractTranslator.intSort : AbstractTranslator.setOfUninterpretedIntTuple; + case MULTIPLY: + return A.getSort() instanceof IntSort ? AbstractTranslator.intSort : AbstractTranslator.setOfUninterpretedIntTuple; + case DIVIDE: + return A.getSort() instanceof IntSort ? AbstractTranslator.intSort : AbstractTranslator.setOfUninterpretedIntTuple; + case MOD: + return A.getSort() instanceof IntSort ? AbstractTranslator.intSort : AbstractTranslator.setOfUninterpretedIntTuple; + case EQ: + return AbstractTranslator.boolSort; + case GTE: + return AbstractTranslator.boolSort; + case LTE: + return AbstractTranslator.boolSort; + case GT: + return AbstractTranslator.boolSort; + case LT: + return AbstractTranslator.boolSort; + case UNION: + return A.getSort(); + case INTERSECTION: + return A.getSort(); + case SETMINUS: + return A.getSort(); + case MEMBER: + return AbstractTranslator.boolSort; + case SUBSET: + return AbstractTranslator.boolSort; + case JOIN: + { + // type checking is handled during construction + + TupleSort leftSort = (TupleSort) ((SetSort) A.getSort()).elementSort; + TupleSort rightSort = (TupleSort) ((SetSort) B.getSort()).elementSort; + + // the join sorts should match + assert (leftSort.elementSorts.get(leftSort.elementSorts.size() - 1) == + rightSort.elementSorts.get(0)); + + List newSorts = new ArrayList<>(); + for (int i = 0; i < leftSort.elementSorts.size() - 1; i++) + { + newSorts.add(leftSort.elementSorts.get(i)); + } + + for (int i = 1; i < rightSort.elementSorts.size(); i++) + { + newSorts.add(rightSort.elementSorts.get(i)); + } + + Sort sort = new SetSort(new TupleSort(newSorts)); + + return sort; + } + case PRODUCT: + { + // type checking is handled during construction + + TupleSort leftSort = (TupleSort) ((SetSort) A.getSort()).elementSort; + TupleSort rightSort = (TupleSort) ((SetSort) B.getSort()).elementSort; + + List newSorts = new ArrayList<>(); + newSorts.addAll(leftSort.elementSorts); + newSorts.addAll(rightSort.elementSorts); + + Sort sort = new SetSort(new TupleSort(newSorts)); + return sort; + } + case TUPSEL: + { + int index = Integer.parseInt(((IntConstant) A).getValue()); + TupleSort sort = (TupleSort) B.getSort(); + return sort.elementSorts.get(index); + } + default: + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtExpr evaluate(Map functions) + { + switch (op) + { + case EQ: + { + if (A instanceof Variable && B instanceof UninterpretedConstant) + { + return evaluateEquality(functions, A, B); + } + if (B instanceof Variable && A instanceof UninterpretedConstant) + { + return evaluateEquality(functions, B, A); + } + } + break; + case UNION: + { + SmtExpr left = A.evaluate(functions); + SmtExpr right = B.evaluate(functions); + return Op.UNION.make(left, right); + } + } + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtBinaryExpr)) + { + return false; + } + SmtBinaryExpr binaryObject = (SmtBinaryExpr) object; + return op == binaryObject.op && + A.equals(binaryObject.A) && + B.equals(binaryObject.B); + } + + @Override + public List getFreeVariables() + { + List freeVariables = A.getFreeVariables(); + freeVariables.addAll(B.getFreeVariables()); + return freeVariables; + } + + private SmtExpr evaluateEquality(Map functions, SmtExpr left, SmtExpr right) + { + String variableName = ((Variable) left).getName(); + if (!functions.containsKey(variableName)) + { + throw new RuntimeException("Function " + variableName + " is undefined"); + } + SmtExpr leftValue = functions.get(variableName).getBody(); + boolean isEqual = leftValue.equals(right); + if (isEqual) + { + return BoolConstant.True; + } + else + { + return BoolConstant.False; + } + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + if (A.equals(newVariable) || B.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + + SmtExpr A = this.A.substitute(oldVariable, newVariable); + SmtExpr B = this.B.substitute(oldVariable, newVariable); + return op.make(A, B); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + SmtExpr A = this.A.replace(oldSmtExpr, newSmtExpr); + SmtExpr B = this.B.replace(oldSmtExpr, newSmtExpr); + return op.make(A, B); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || A.containsExpr(expr) || B.containsExpr(expr)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtCallExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtCallExpr.java new file mode 100644 index 000000000..f9599ff65 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtCallExpr.java @@ -0,0 +1,184 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.*; + +public class SmtCallExpr extends SmtExpr +{ + private final FunctionDeclaration function; + private final List arguments; + + public SmtCallExpr(FunctionDeclaration function, SmtExpr... arguments) + { + this.function = function; + this.arguments = Arrays.asList(arguments); + checkTypes(); + } + + public SmtCallExpr(FunctionDeclaration function, List arguments) + { + this.function = function; + this.arguments = arguments; + checkTypes(); + } + + @Override + protected void checkTypes() + { + if (function.getInputSorts().size() != arguments.size()) + { + throw new RuntimeException(String.format("Function '%1$s' expects %2$d arguments but %3$d arguments were passed", function.getName(), function.getInputSorts().size(), arguments.size())); + } + + for (int i = 0; i < arguments.size(); i++) + { + Sort actualSort = arguments.get(i).getSort(); + Sort expectedSort = function.getInputSorts().get(i); + if (!actualSort.equals(expectedSort)) + { + throw new RuntimeException(String.format("Function '%1$s' expects argument %2$d to have sort '%3$s', but it has sort '%4$s'", function.getName(), i, expectedSort, actualSort)); + } + } + } + + public String getFunctionName() + { + return this.function.getName(); + } + + public List getArguments() + { + return this.arguments; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return function.getSort(); + } + + @Override + public SmtExpr evaluate(Map functions) + { + FunctionDefinition definition = functions.get(this.function.getName()); + // improve the performance of this line + Map newScope = new HashMap<>(functions); + for (int i = 0; i < arguments.size(); i++) + { + SmtExpr argument = arguments.get(i); + if (argument instanceof UninterpretedConstant) + { + UninterpretedConstant uninterpretedConstant = (UninterpretedConstant) argument; + String argumentName = definition.inputVariables.get(i).getName(); + // ToDo: refactor this + // for now generate a new constant with the passed parameter; + ConstantDefinition constant = new ConstantDefinition(argumentName, uninterpretedConstant.getSort(), uninterpretedConstant, true); + newScope.put(constant.getName(), constant); + } + else + { + throw new UnsupportedOperationException(); + } + } + return definition.getBody().evaluate(newScope); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtCallExpr)) + { + return false; + } + SmtCallExpr functionCall = (SmtCallExpr) object; + return function.equals(functionCall.function) && + arguments.equals(functionCall.arguments); + } + + @Override + public List getFreeVariables() + { + List freeVariables = new ArrayList<>(); + for (SmtExpr smtExpr : arguments) + { + freeVariables.addAll(smtExpr.getFreeVariables()); + } + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + if (this.function.getVariable().equals(newVariable)) + { + throw new UnsupportedOperationException(); + } + + List newSmtExprs = new ArrayList<>(); + for (SmtExpr smtExpr : arguments) + { + if (smtExpr.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + newSmtExprs.add(smtExpr.substitute(oldVariable, newVariable)); + } + return new SmtCallExpr(function, newSmtExprs); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + List newSmtExprs = new ArrayList<>(); + for (SmtExpr smtExpr : arguments) + { + newSmtExprs.add(smtExpr.replace(oldSmtExpr, newSmtExpr)); + } + return new SmtCallExpr(function, newSmtExprs); + } + + public FunctionDeclaration getFunction() + { + return function; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + + for (SmtExpr smtExpr: this.arguments) + { + if(smtExpr.containsExpr(expr)) + { + return true; + } + } + + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtExpr.java new file mode 100644 index 000000000..dc18c0554 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtExpr.java @@ -0,0 +1,116 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.printers.SmtLibPrinter; + +import java.util.List; +import java.util.Map; + +public abstract class SmtExpr extends SmtAst +{ + private String comment = ""; + + public abstract Sort getSort(); + + public String getComment() + { + return this.comment; + } + + public void setComment(String comment) + { + this.comment = comment; + } + + @Override + public String toString() + { + SmtLibPrinter printer = new SmtLibPrinter(); + printer.visit(this); + return printer.getSmtLib(); + } + + protected void checkTypes() + { + } + + public abstract SmtExpr evaluate(Map functions); + + @Override + public abstract boolean equals(Object object); + + public abstract List getFreeVariables(); + + public abstract SmtExpr substitute(Variable oldVariable, Variable newVariable); + + public abstract SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr); + + public abstract boolean containsExpr(SmtExpr expr); + + public SmtBinaryExpr implies(SmtExpr expr) + { + return SmtBinaryExpr.Op.IMPLIES.make(this, expr); + } + + public SmtBinaryExpr member(SmtExpr set) + { + return SmtBinaryExpr.Op.MEMBER.make(this, set); + } + + public SmtBinaryExpr subset(SmtExpr set) + { + return SmtBinaryExpr.Op.SUBSET.make(this, set); + } + + public SmtBinaryExpr product(SmtExpr set) + { + return SmtBinaryExpr.Op.PRODUCT.make(this, set); + } + + public SmtBinaryExpr join(SmtExpr set) + { + return SmtBinaryExpr.Op.JOIN.make(this, set); + } + + public SmtBinaryExpr plus(SmtExpr expr) + { + return SmtBinaryExpr.Op.PLUS.make(this, expr); + } + + public SmtBinaryExpr minus(SmtExpr expr) + { + return SmtBinaryExpr.Op.MINUS.make(this, expr); + } + + public SmtBinaryExpr multiply(SmtExpr expr) + { + return SmtBinaryExpr.Op.MULTIPLY.make(this, expr); + } + + public SmtBinaryExpr divide(SmtExpr expr) + { + return SmtBinaryExpr.Op.DIVIDE.make(this, expr); + } + + public SmtBinaryExpr mod(SmtExpr expr) + { + return SmtBinaryExpr.Op.MOD.make(this, expr); + } + + public SmtUnaryExpr singleton() + { + return SmtUnaryExpr.Op.SINGLETON.make(this); + } + + public SmtUnaryExpr not() + { + return SmtUnaryExpr.Op.NOT.make(this); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtIteExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtIteExpr.java new file mode 100644 index 000000000..045f055e1 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtIteExpr.java @@ -0,0 +1,167 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.List; +import java.util.Map; + +/** + * @author Mudathir Mohamed, Paul Meng + */ +public class SmtIteExpr extends SmtExpr +{ + private final SmtExpr condExpr; + private final SmtExpr thenExpr; + private final SmtExpr elseExpr; + + public SmtIteExpr(SmtExpr condExpr, SmtExpr thenExpr, SmtExpr elseExpr) + { + if (condExpr == null) + { + throw new RuntimeException("Condition expression of the ite is null"); + } + if (thenExpr == null) + { + throw new RuntimeException("Then expression of the ite is null"); + } + if (elseExpr == null) + { + throw new RuntimeException("Else expression of the ite is null"); + } + this.condExpr = condExpr; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; + checkTypes(); + } + + @Override + protected void checkTypes() + { + if (condExpr.getSort() != AbstractTranslator.boolSort) + { + throw new RuntimeException(String.format("The sort '%1$s' of the condition expression is not boolean", condExpr.getSort())); + } + + if (!thenExpr.getSort().equals(elseExpr.getSort())) + { + throw new RuntimeException(String.format("The sort '%1$s' of then expression is different than the sort '%1$s' of else expression", thenExpr.getSort(), elseExpr.getSort())); + } + } + + + public SmtExpr getCondExpr() + { + return this.condExpr; + } + + public SmtExpr getThenExpr() + { + return this.thenExpr; + } + + public SmtExpr getElseExpr() + { + return this.elseExpr; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return this.thenExpr.getSort(); + } + + @Override + public SmtExpr evaluate(Map functions) + { + SmtExpr evaluatedCondition = condExpr.evaluate(functions); + if (!(evaluatedCondition instanceof BoolConstant)) + { + throw new RuntimeException("Expected a boolean constant but got " + evaluatedCondition); + } + boolean isTrue = Boolean.parseBoolean(((BoolConstant) evaluatedCondition).getValue()); + if (isTrue) + { + return thenExpr.evaluate(functions); + } + else + { + return elseExpr.evaluate(functions); + } + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtIteExpr)) + { + return false; + } + SmtIteExpr iteObject = (SmtIteExpr) object; + return condExpr.equals(iteObject.condExpr) && + thenExpr.equals(iteObject.thenExpr) && + elseExpr.equals(iteObject.elseExpr); + } + + @Override + public List getFreeVariables() + { + List freeVariables = condExpr.getFreeVariables(); + freeVariables.addAll(thenExpr.getFreeVariables()); + freeVariables.addAll(elseExpr.getFreeVariables()); + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + if (condExpr.equals(newVariable) || thenExpr.equals(newVariable) || elseExpr.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + SmtExpr newCondition = condExpr.substitute(oldVariable, newVariable); + SmtExpr newThen = elseExpr.substitute(oldVariable, newVariable); + SmtExpr newElse = elseExpr.substitute(oldVariable, newVariable); + return new SmtIteExpr(newCondition, newThen, newElse); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + SmtExpr newCondition = condExpr.replace(oldSmtExpr, newSmtExpr); + SmtExpr newThen = elseExpr.replace(oldSmtExpr, newSmtExpr); + SmtExpr newElse = elseExpr.replace(oldSmtExpr, newSmtExpr); + return new SmtIteExpr(newCondition, newThen, newElse); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || + this.condExpr.containsExpr(expr) || + this.thenExpr.containsExpr(expr) || + this.elseExpr.containsExpr(expr)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtLetExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtLetExpr.java new file mode 100644 index 000000000..b7ea2a9c0 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtLetExpr.java @@ -0,0 +1,152 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SmtLetExpr extends SmtExpr +{ + private final SmtExpr expr; + private final Map letVariables; + + public SmtLetExpr(Map letVars, SmtExpr expr) + { + this.letVariables = new HashMap<>(); + this.expr = expr; + for (Map.Entry var : letVars.entrySet()) + { + this.letVariables.put(var.getKey(), var.getValue()); + } + checkTypes(); + } + + @Override + protected void checkTypes() + { + // make sure the types of the declared variables match their corresponding expressions + + for (Map.Entry entry : letVariables.entrySet()) + { + if (!entry.getKey().getSort().equals(entry.getValue().getSort())) + { + throw new RuntimeException(String.format("The variable '%1$s' has sort '%2$s' which is the different than '%3$s', the sort of its expression", entry.getKey().getName(), entry.getKey().getSort(), entry.getValue().getSort())); + } + } + + // check there is no typing error within the body + expr.checkTypes(); + } + + public Map getLetVariables() + { + return this.letVariables; + } + + public SmtExpr getSmtExpr() + { + return this.expr; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return expr.getSort(); + } + + @Override + public SmtExpr evaluate(Map functions) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + // syntax equality without alpha equivalence + if (object == this) + { + return true; + } + if (!(object instanceof SmtLetExpr)) + { + return false; + } + SmtLetExpr letObject = (SmtLetExpr) object; + return letVariables.equals(letObject.letVariables) && expr.equals(letObject.expr); + } + + @Override + public List getFreeVariables() + { + List freeVariables = expr.getFreeVariables(); + for (Map.Entry entry : letVariables.entrySet()) + { + freeVariables.remove(entry.getKey().getVariable()); + } + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + throw new UnsupportedOperationException(); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + List variables = letVariables.keySet() + .stream() + .map(v -> v.getVariable()) + .collect(Collectors.toList()); + // oldSmtExpr is not free + if(variables.contains(oldSmtExpr)) + { + // oldSmtExpr is not free + return this; + } + else + { + if(variables.contains(newSmtExpr)) + { + // the newSmtExpr should be free + throw new UnsupportedOperationException(String.format("Expr '%1$s' is not free in '%2$s', " + + "therefore it can not be replaced with '%3$s'.", newSmtExpr, this, oldSmtExpr)); + } + + Map newMap = new HashMap<>(); + for (Map.Entry entry: letVariables.entrySet()) + { + newMap.put(entry.getKey(), entry.getValue().replace(oldSmtExpr, newSmtExpr)); + } + SmtExpr newExpr = this.expr.replace(oldSmtExpr, newSmtExpr); + return new SmtLetExpr(newMap, newExpr); + } + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || this.expr.containsExpr(expr)) + { + return true; + } + + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtModel.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtModel.java new file mode 100644 index 000000000..1859d32f8 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtModel.java @@ -0,0 +1,124 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.*; + +public class SmtModel extends SmtAst +{ + protected final List sorts = new ArrayList<>(); + protected List functions = new ArrayList<>(); + + public SmtModel() + { + } + + public SmtModel(SmtModel model) + { + this.sorts.addAll(model.sorts); + this.functions.addAll(model.functions); + } + + + public void addSort(Sort sort) + { + if (sort != null) + { + this.sorts.add(sort); + } + } + + public void removeSort(Sort sort) + { + if (sort != null) + { + this.sorts.removeAll(Collections.singleton(sort)); + } + } + + + public void addFunction(FunctionDeclaration function) + { + if (function != null) + { + this.functions.add(function); + } + } + + public void addFunctions(List functions) + { + for (FunctionDeclaration function : functions) + { + addFunction(function); + } + } + + public void removeFunction(FunctionDeclaration function) + { + if (function != null) + { + this.functions.removeAll(Collections.singleton(function)); + } + } + + public void removeFunctions(List functions) + { + this.functions.removeAll(functions); + } + + public List getSorts() + { + return this.sorts; + } + + public List getFunctions() + { + return this.functions; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + throw new UnsupportedOperationException(); + } + + public FunctionDefinition evaluateUninterpretedInt(FunctionDefinition function) + { + Map functions = new HashMap<>(); + + if (function.inputVariables.size() > 0) + { + throw new UnsupportedOperationException(); + } + // make sure this is a cvc4 model + for (FunctionDeclaration declaration : this.functions) + { + if (!(declaration instanceof FunctionDefinition)) + { + throw new RuntimeException("The function " + declaration + " is not defined"); + } + functions.put(declaration.getName(), (FunctionDefinition) declaration); + } + SmtExpr body = function.smtExpr.evaluate(functions); + + return new FunctionDefinition(function.getName(), function.inputVariables, + function.getSort(), body, function.isOriginal()); + } + + protected void reset() + { + this.sorts.clear(); + this.functions.clear(); + } + + public void setFunctions(List functions) + { + this.functions = functions; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtMultiArityExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtMultiArityExpr.java new file mode 100644 index 000000000..bac981dc4 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtMultiArityExpr.java @@ -0,0 +1,316 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.*; +import java.util.stream.Collectors; + +public class SmtMultiArityExpr extends SmtExpr +{ + private final Op op; + private final List exprs; + + private SmtMultiArityExpr(Op op, List exprs) + { + this.op = op; + this.exprs = exprs; + + if (this.exprs.stream().anyMatch(Objects::isNull)) + { + throw new RuntimeException("One of the expression is null"); + } + checkTypes(); + } + + public void checkTypes() + { + switch (op) + { + case MKTUPLE: + { + if (exprs.size() == 0) + { + throw new RuntimeException("mkTuple operation requires at least one expression"); + } + break; + } + case INSERT: + { + if (exprs.size() <= 1) + { + throw new RuntimeException("Insert operation requires at least two expressions"); + } + // the last expression should have a set sort + SmtExpr setSmtExpr = exprs.get(exprs.size() - 1); + if (!(setSmtExpr.getSort() instanceof SetSort)) + { + throw new RuntimeException(String.format("The expression '%1$s' has sort '%2S' which is not set", setSmtExpr, setSmtExpr.getSort())); + } + SetSort setSort = (SetSort) setSmtExpr.getSort(); + + // all remaining expressions should have the same sort of the elements of the set + for (int i = 0; i < exprs.size() - 1; i++) + { + SmtExpr smtExpr = exprs.get(i); + if (!(smtExpr.getSort().equals(setSort.elementSort))) + { + throw new RuntimeException(String.format("The sort '%1$s' of expression '%2$s' doesn't match the elements sort '%3$s'", exprs.get(i).getSort(), smtExpr, setSort.elementSort)); + } + } + } + break; + case DISTINCT: + { + if (exprs.size() <= 1) + { + throw new RuntimeException("distinct operation requires at least two expressions"); + } + + List sorts = this.exprs.stream() + .map(SmtExpr::getSort).collect(Collectors.toList()); + Sort firstSort = sorts.get(0); + for (int i = 1; i < sorts.size(); i++) + { + if (!sorts.get(i).equals(firstSort)) + { + throw new RuntimeException(String.format("Expressions of distinct operation do not have the same type:\n%s", sorts)); + } + } + } + break; + case OR: + { + checkBoolType(Op.OR); + } + break; + case AND: + { + checkBoolType(Op.AND); + } + break; + default: + throw new UnsupportedOperationException(); + } + } + + private void checkBoolType(Op op) + { + if (exprs.size() == 0) + { + throw new RuntimeException(op + " operation requires at least one expression"); + } + + // all expressions should have boolean sort + for (SmtExpr smtExpr : exprs) + { + if (!(smtExpr.getSort().equals(AbstractTranslator.boolSort))) + { + throw new RuntimeException(String.format("The sort '%1$s' of expression '%2$s' is not boolean", smtExpr.getSort(), smtExpr)); + } + } + } + + public SmtMultiArityExpr(Op op, SmtExpr... exprs) + { + this(op, Arrays.asList(exprs)); + } + + public Op getOp() + { + return this.op; + } + + public List getExprs() + { + return this.exprs; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public SmtExpr get(int index) + { + assert (0 <= index && index < exprs.size()); + return this.exprs.get(index); + } + + public enum Op + { + MKTUPLE("mkTuple"), + INSERT("insert"), + DISTINCT("distinct"), + OR("or"), + AND("and"); + + private final String opStr; + + Op(String op) + { + this.opStr = op; + } + + public SmtMultiArityExpr make(List exprs) + { + return new SmtMultiArityExpr(this, exprs); + } + + public SmtMultiArityExpr make(SmtExpr... exprs) + { + return new SmtMultiArityExpr(this, exprs); + } + + public static Op getOp(String operator) + { + switch (operator) + { + case "mkTuple": + return MKTUPLE; + case "insert": + return INSERT; + case "distinct": + return DISTINCT; + case "or": + return OR; + case "and": + return AND; + default: + throw new UnsupportedOperationException("Operator " + operator + " is not defined"); + } + } + + + @Override + public String toString() + { + return this.opStr; + } + } + + @Override + public Sort getSort() + { + switch (op) + { + case MKTUPLE: + { + + List sorts = new ArrayList<>(); + for (SmtExpr expr : exprs) + { + sorts.add(expr.getSort()); + } + return new TupleSort(sorts); + } + case INSERT: + { + // return the sort of the last element + return exprs.get(exprs.size() - 1).getSort(); + } + case DISTINCT: + case OR: + case AND: + return AbstractTranslator.boolSort; + default: + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtExpr evaluate(Map functions) + { + List smtExprs = new ArrayList<>(); + for (SmtExpr smtExpr : this.exprs) + { + smtExprs.add(smtExpr.evaluate(functions)); + } + return new SmtMultiArityExpr(this.op, smtExprs); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtMultiArityExpr)) + { + return false; + } + SmtMultiArityExpr multiArity = (SmtMultiArityExpr) object; + return op == multiArity.op && + exprs.equals(multiArity.exprs); + } + + @Override + public List getFreeVariables() + { + List freeVariables = new ArrayList<>(); + for (SmtExpr smtExpr : exprs) + { + freeVariables.addAll(smtExpr.getFreeVariables()); + } + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + List newSmtExprs = new ArrayList<>(); + for (SmtExpr smtExpr : exprs) + { + if (smtExpr.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + newSmtExprs.add(smtExpr.substitute(oldVariable, newVariable)); + } + return new SmtMultiArityExpr(op, newSmtExprs); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + + List newSmtExprs = new ArrayList<>(); + for (SmtExpr smtExpr : exprs) + { + newSmtExprs.add(smtExpr.replace(oldSmtExpr, newSmtExpr)); + } + return new SmtMultiArityExpr(op, newSmtExprs); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + + for (SmtExpr smtExpr: this.exprs) + { + if(smtExpr.containsExpr(expr)) + { + return true; + } + } + + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtQtExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtQtExpr.java new file mode 100644 index 000000000..58f5e0f73 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtQtExpr.java @@ -0,0 +1,224 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.TranslatorUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SmtQtExpr extends SmtExpr +{ + private final SmtExpr expr; + private final List variables; + private final Op op; + + private SmtQtExpr(Op op, List variables, SmtExpr expr) + { + this.variables = new ArrayList<>(); + this.expr = expr; + this.op = op; + for (SmtVariable bdVar : variables) + { + this.variables.add(bdVar); + } + checkTypes(); + } + + @Override + protected void checkTypes() + { + if (expr.getSort() != AbstractTranslator.boolSort) + { + throw new RuntimeException(String.format("The sort '%1$s' of the quantified expression is not boolean", expr.getSort())); + } + if (variables.size() == 0) + { + throw new RuntimeException(String.format("Expected at least one variable for the quantified expression '%1$s'.", this.toString())); + } + } + + private SmtQtExpr(Op op, SmtExpr expr, SmtVariable... variables) + { + this.variables = Arrays.asList(variables); + this.expr = expr; + this.op = op; + } + + public List getVariables() + { + return this.variables; + } + + public SmtExpr getExpr() + { + return this.expr; + } + + public Op getOp() + { + return this.op; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public enum Op + { + FORALL("forall"), + EXISTS("exists"); + + private final String opStr; + + Op(String op) + { + this.opStr = op; + } + + public static Op getOp(String operator) + { + switch (operator) + { + case "forall": + return FORALL; + case "exists": + return EXISTS; + default: + throw new UnsupportedOperationException("Operator " + operator + " is not defined"); + } + } + + public SmtQtExpr make(SmtExpr expr, SmtVariable... variables) + { + return new SmtQtExpr(this, expr, variables); + } + + public SmtQtExpr make(SmtExpr expr, List variables) + { + return new SmtQtExpr(this, variables, expr); + } + + @Override + public String toString() + { + return this.opStr; + } + } + + @Override + public Sort getSort() + { + switch (op) + { + case EXISTS: + case FORALL: + return AbstractTranslator.boolSort; + default: + throw new UnsupportedOperationException("Unsupported operator" + op.toString()); + } + } + + @Override + public SmtExpr evaluate(Map functions) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtQtExpr)) + { + return false; + } + SmtQtExpr quantifiedObject = (SmtQtExpr) object; + if (!variables.equals(quantifiedObject.variables)) + { + return false; + } + return op == quantifiedObject.op && + expr.equals(quantifiedObject.expr); + } + + @Override + public List getFreeVariables() + { + List freeVariables = expr.getFreeVariables(); + freeVariables.removeAll(variables.stream().map(v -> v.getVariable()).collect(Collectors.toList())); + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + SmtExpr body = expr; + List variables = new ArrayList<>(this.variables); + // check if the new variable is declared + for (Declaration declaration : this.variables) + { + if (declaration.getVariable().equals(newVariable)) + { + // choose a new name for the declared variable + SmtVariable newDeclaration = new SmtVariable(TranslatorUtils.getFreshName(declaration.getSort()), declaration.getSort(), false); + if (declaration instanceof SmtVariable) + { + SmtExpr constraint = ((SmtVariable) declaration).getConstraint(); + SmtExpr newConstraint = constraint.substitute(oldVariable, newVariable); + newDeclaration.setConstraint(newConstraint); + } + else + { + throw new UnsupportedOperationException(); + } + body = expr.substitute(declaration.getVariable(), newDeclaration.getVariable()); + variables.remove(declaration); + variables.add(newDeclaration); + } + } + if (expr.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + + SmtExpr newSmtExpr = body.substitute(oldVariable, newVariable); + return new SmtQtExpr(op, variables, newSmtExpr); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + SmtExpr smtExpr = expr.replace(oldSmtExpr, newSmtExpr); + return new SmtQtExpr(op, variables, smtExpr); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || this.expr.containsExpr(expr)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtScript.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtScript.java new file mode 100644 index 000000000..eb93662bd --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtScript.java @@ -0,0 +1,194 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.printers.SmtLibPrettyPrinter; + +import java.math.BigInteger; +import java.util.*; + +public class SmtScript extends SmtModel +{ + private List assertions = new ArrayList<>(); + private SmtScript parent; + //ToDo: refactor classes abstract translator and SmtScript + private Map integerConstants = new HashMap<>(); + // script between push pop commands + private List children = new ArrayList<>(); + + public SmtScript() + { + parent = null; + } + + public SmtScript(SmtScript smtScript) + { + super(smtScript); + this.assertions.addAll(smtScript.assertions); + this.parent = smtScript.parent; + this.integerConstants.putAll(smtScript.integerConstants); + } + + public Map getIntegerConstants() + { + return integerConstants; + } + + public void putIntegerConstant(BigInteger value, FunctionDeclaration declaration) + { + integerConstants.put(value, declaration); + addFunction(declaration); + } + + public SmtScript createChild() + { + SmtScript child = new SmtScript(); + child.parent = this; + this.children.add(child); + return child; + } + + public void addAssertion(Assertion assertion) + { + if (assertion != null) + { + this.assertions.add(assertion); + } + } + + public void removeAssertion(Assertion assertion) + { + if (assertion != null) + { + this.assertions.removeAll(Collections.singleton(assertion)); + } + } + + public List getAssertions() + { + return this.assertions; + } + + public void setAssertions(List assertions) + { + this.assertions = assertions; + } + + public void reset() + { + super.reset(); + this.assertions.clear(); + for (SmtScript child : children) + { + child.reset(); + } + } + + public void removeAssertions(List assertions) + { + this.assertions.removeAll(assertions); + } + + public SmtScript getParent() + { + return parent; + } + + public SmtScript getChild(int index) + { + return children.get(index); + } + + public void addAssertions(List assertions) + { + this.assertions.addAll(assertions); + } + + public void addChild(SmtScript child) + { + child.parent = this; + children.add(child); + } + + public List getChildren() + { + return children; + } + + public boolean isUninterpretedIntUsed() + { + List excludedFunctions = AbstractTranslator.getUninterpretedIntFunctions(this); + for (FunctionDeclaration function : this.getFunctions()) + { + if (excludedFunctions.contains(function)) + { + // skip default functions for uninterpreted integers + continue; + } + + UninterpretedIntVisitor visitor = new UninterpretedIntVisitor(); + visitor.visit(function); + if (visitor.isUninterpretedIntUsed()) + { + return true; + } + + } + + List excludedAssertions = AbstractTranslator.getUninterpretedIntAssertions(this); + + for (Assertion assertion : this.getAssertions()) + { + if (excludedAssertions.contains(assertion)) + { + // skip default assertions for uninterpreted integers + continue; + } + + UninterpretedIntVisitor visitor = new UninterpretedIntVisitor(); + visitor.visit(assertion); + if (visitor.isUninterpretedIntUsed()) + { + return true; + } + } + + // check children + for (SmtScript child : this.getChildren()) + { + if (child.isUninterpretedIntUsed()) + { + return true; + } + } + + return false; + } + + @Override + public String toString() + { + SmtLibPrettyPrinter prettyPrinter = new SmtLibPrettyPrinter(); + prettyPrinter.visit(this); + return prettyPrinter.getSmtLib(); + } + + public String print(SmtSettings settings) + { + SmtLibPrettyPrinter prettyPrinter = new SmtLibPrettyPrinter(settings); + prettyPrinter.visit(this); + return prettyPrinter.getSmtLib(); + } + + public void clearChildren() + { + this.children.clear(); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtSettings.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtSettings.java new file mode 100644 index 000000000..b9b9596d2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtSettings.java @@ -0,0 +1,73 @@ +package edu.uiowa.smt.smtAst; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SmtSettings extends SmtAst +{ + private List logic = new ArrayList<>(); + private Map solverOptions = new HashMap<>(); + public boolean produceUnsatCore; + public boolean finiteModelFinding; + + public static final SmtSettings Default = new SmtSettings(); + + public static final String TLIMIT = "tlimit"; + public static final String PRODUCE_UNSAT_CORES = "produce-unsat-cores"; + public static final String FINITE_MODEL_FIND = "finite-model-find"; + + protected SmtSettings() + { + addLogic("ALL"); + putSolverOption("produce-models", "true"); + putSolverOption("incremental", "true"); + putSolverOption("sets-ext", "true"); + putSolverOption("block-models", "literals"); + putSolverOption(FINITE_MODEL_FIND, Boolean.toString(true)); + putSolverOption("cegqi-all", "false"); + finiteModelFinding = true; + produceUnsatCore = false; + } + + public static SmtSettings getInstance() + { + return new SmtSettings(Default); + } + + public SmtSettings(SmtSettings settings) + { + logic = new ArrayList<>(settings.logic); + solverOptions = new HashMap<>(settings.solverOptions); + produceUnsatCore = settings.produceUnsatCore; + finiteModelFinding = settings.finiteModelFinding; + } + + public void addLogic(String logic) + { + this.logic.add(logic); + } + + public List getLogic() + { + return logic; + } + + public Map getSolverOptions() + { + return solverOptions; + } + + public void putSolverOption(String key, String value) + { + solverOptions.put(key, value); + } + + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnaryExpr.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnaryExpr.java new file mode 100644 index 000000000..362d8f91d --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnaryExpr.java @@ -0,0 +1,272 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SmtUnaryExpr extends SmtExpr +{ + private final Op op; + private final SmtExpr expr; + + private SmtUnaryExpr(Op op, SmtExpr expr) + { + this.op = op; + if (expr == null) + { + throw new RuntimeException("Expression is null"); + } + this.expr = expr; + checkTypes(); + } + + @Override + protected void checkTypes() + { + switch (op) + { + case NOT: + { + if (expr.getSort() != AbstractTranslator.boolSort) + { + throw new RuntimeException(String.format("Expression sort '%1$s' is not boolean", expr.getSort())); + } + } + break; + case COMPLEMENT: + { + if (!(expr.getSort() instanceof SetSort)) + { + throw new RuntimeException(String.format("The sort '%1$s' of expression '%2$s' is not a set", expr.getSort(), expr)); + } + } + break; + case TRANSPOSE: + case TCLOSURE: + { + // make sure expr is a set of tuples + if (!(expr.getSort() instanceof SetSort && + ((SetSort) expr.getSort()).elementSort instanceof TupleSort)) + { + throw new RuntimeException(String.format("The sort '%1$s' of expression '%2$s' is not a set of tuples", expr.getSort(), expr)); + } + // make sure expr is a binary relation + TupleSort tupleSort = (TupleSort) ((SetSort) expr.getSort()).elementSort; + if (tupleSort.elementSorts.size() != 2) + { + throw new RuntimeException(String.format("The sort '%1$s' of expression '%2$s' is not a binary relation", expr.getSort(), expr)); + } + } + break; + case EMPTYSET: + case UNIVSET: + { + if (!(expr instanceof SetSort)) + { + throw new RuntimeException(String.format("Expected a set sort. Found '%1$s'", expr)); + } + } + break; + case CHOOSE: + { + if (!(expr.getSort() instanceof SetSort)) + { + throw new RuntimeException(String.format("Expected a set sort in '%1$s', found '%2$s' ", + this.toString(), expr.getSort())); + } + } + case SINGLETON: + break; + default: + throw new UnsupportedOperationException(); + } + } + + public Op getOp() + { + return this.op; + } + + public SmtExpr getExpr() + { + return this.expr; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + switch (op) + { + case NOT: + return AbstractTranslator.boolSort; + case COMPLEMENT: + return expr.getSort(); + case TRANSPOSE: + { + // type checking is handled during construction + TupleSort oldSort = (TupleSort) ((SetSort) expr.getSort()).elementSort; + List reverse = new ArrayList<>(); + for (int i = oldSort.elementSorts.size() - 1; i >= 0; i--) + { + reverse.add(oldSort.elementSorts.get(i)); + } + SetSort sort = new SetSort(new TupleSort(reverse)); + return sort; + } + case TCLOSURE: + return expr.getSort(); + case SINGLETON: + return new SetSort(expr.getSort()); + case CHOOSE: + return ((SetSort) expr.getSort()).elementSort; + case EMPTYSET: + return expr.getSort(); + case UNIVSET: + return expr.getSort(); + default: + throw new UnsupportedOperationException(); + } + } + + @Override + public SmtExpr evaluate(Map functions) + { + if (op == Op.EMPTYSET) + { + if (expr.equals(AbstractTranslator.setOfUninterpretedIntTuple)) + { + return new SmtUnaryExpr(op, AbstractTranslator.setOfIntSortTuple); + } + else + { + return this; + } + } + SmtExpr smtExpr = this.expr.evaluate(functions); + return new SmtUnaryExpr(this.op, smtExpr); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof SmtUnaryExpr)) + { + return false; + } + SmtUnaryExpr unaryObject = (SmtUnaryExpr) object; + return op == unaryObject.op && + expr.equals(unaryObject.expr); + } + + @Override + public List getFreeVariables() + { + return expr.getFreeVariables(); + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + if (expr.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + + SmtExpr newSmtExpr = expr.substitute(oldVariable, newVariable); + return new SmtUnaryExpr(op, newSmtExpr); + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + SmtExpr smtExpr = expr.replace(oldSmtExpr, newSmtExpr); + return new SmtUnaryExpr(op, smtExpr); + } + + public enum Op + { + NOT("not"), + COMPLEMENT("complement"), + TRANSPOSE("transpose"), + TCLOSURE("tclosure"), + SINGLETON("singleton"), + CHOOSE("choose"), + UNIVSET("as univset"), + EMPTYSET("as emptyset"); + + private final String opStr; + + Op(String str) + { + this.opStr = str; + } + + public static Op getOp(String operator) + { + switch (operator) + { + case "not": + return NOT; + case "complement": + return COMPLEMENT; + case "transpose": + return TRANSPOSE; + case "tclosure": + return TCLOSURE; + case "singleton": + return SINGLETON; + case "as univset": + return UNIVSET; + case "as emptyset": + return EMPTYSET; + default: + throw new UnsupportedOperationException("Operator " + operator + " is not defined"); + } + } + + public SmtUnaryExpr make(SmtExpr expr) + { + return new SmtUnaryExpr(this, expr); + } + + @Override + public String toString() + { + return this.opStr; + } + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this) || this.expr.containsExpr(expr)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnsatCore.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnsatCore.java new file mode 100644 index 000000000..d9632a8ec --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtUnsatCore.java @@ -0,0 +1,24 @@ +package edu.uiowa.smt.smtAst; + +import java.util.List; + +public class SmtUnsatCore extends SmtAst +{ + private final List core; + + public SmtUnsatCore(List core) + { + this.core = core; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public List getCore() + { + return core; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtValues.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtValues.java new file mode 100644 index 000000000..3e901f58a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtValues.java @@ -0,0 +1,34 @@ +package edu.uiowa.smt.smtAst; + +import java.util.List; + +public class SmtValues extends SmtAst +{ + private final List values; + + public SmtValues(List values) + { + this.values = values; + } + + public List getValues() + { + return values; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + public SmtExpr getExpression(int index) + { + return values.get(index).getSmtExpr(); + } + + public SmtExpr getValue(int index) + { + return values.get(index).getValue(); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtVariable.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtVariable.java new file mode 100644 index 000000000..67f3ed499 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/SmtVariable.java @@ -0,0 +1,35 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class SmtVariable extends Declaration +{ + private SmtExpr constraint; + + public SmtVariable(String name, Sort sort, boolean isOriginal) + { + super(name, sort, isOriginal); + } + + public void setConstraint(SmtExpr constraint) + { + this.constraint = constraint; + } + + public SmtExpr getConstraint() + { + return constraint; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Sort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Sort.java new file mode 100644 index 000000000..e5f7f92d8 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Sort.java @@ -0,0 +1,92 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.printers.SmtLibPrinter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class Sort extends SmtExpr +{ + private final String name; + private final int arity; + + public Sort(String name, int arity) + { + this.name = name; + this.arity = arity; + } + + public String getName() + { + return this.name; + } + + @Override + public String toString() + { + SmtLibPrinter printer = new SmtLibPrinter(); + printer.visit(this); + return printer.getSmtLib(); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return this; + } + + @Override + public SmtExpr evaluate(Map functions) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + throw new UnsupportedOperationException(); + } + + @Override + public List getFreeVariables() + { + return new ArrayList<>(); + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + return this; + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + return this; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + throw new UnsupportedOperationException(); + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/StringSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/StringSort.java new file mode 100644 index 000000000..1aaf32c7a --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/StringSort.java @@ -0,0 +1,48 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class StringSort extends Sort +{ + public StringSort() + { + super("String", 0); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof StringSort)) + { + return false; + } + + return true; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/TupleSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/TupleSort.java new file mode 100644 index 000000000..e190781ea --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/TupleSort.java @@ -0,0 +1,88 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.Arrays; +import java.util.List; + +public class TupleSort extends Sort +{ + public List elementSorts; + + public TupleSort(List elementSorts) + { + super("Tuple", 0); + this.elementSorts = elementSorts; + } + + public TupleSort(Sort... elementSorts) + { + this(Arrays.asList(elementSorts)); + } + + @Override + public String toString() + { + String result = "(Tuple "; + + for (int i = 0; i < this.elementSorts.size(); ++i) + { + result += this.elementSorts.get(i).toString(); + + if (i < this.elementSorts.size() - 1) + { + result += " "; + } + } + result += ")"; + return result; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + + if (!(object instanceof TupleSort)) + { + return false; + } + + TupleSort sort = (TupleSort) object; + return sort.elementSorts.equals(this.elementSorts); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + + for (SmtExpr smtExpr: elementSorts) + { + if(smtExpr.containsExpr(expr)) + { + return true; + } + } + + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedConstant.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedConstant.java new file mode 100644 index 000000000..3b4e11c30 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedConstant.java @@ -0,0 +1,108 @@ +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class UninterpretedConstant extends Constant +{ + + private String name; + private UninterpretedSort sort; + + public UninterpretedConstant(String name, UninterpretedSort sort) + { + this.name = name; + this.sort = sort; + } + + public String getName() + { + return name; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return sort; + } + + @Override + public SmtExpr evaluate(Map functions) + { + if (this.getSort().equals(AbstractTranslator.atomSort)) + { + return this; + } + if (this.getSort().equals(AbstractTranslator.uninterpretedInt)) + { + if (!functions.containsKey(AbstractTranslator.uninterpretedIntValueName)) + { + throw new RuntimeException("The function " + AbstractTranslator.uninterpretedInt + " is undefined in this model"); + } + // convert the uninterpreted int to int + FunctionDefinition uninterpretedIntValue = functions.get(AbstractTranslator.uninterpretedIntValueName); + // uninterpretedIntValue: UninterpretedInt -> Int + assert (uninterpretedIntValue.inputVariables.size() == 1); + SmtCallExpr functionCall = new SmtCallExpr(uninterpretedIntValue, this); + return functionCall.evaluate(functions); + } + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof UninterpretedConstant)) + { + return false; + } + UninterpretedConstant constant = (UninterpretedConstant) object; + return name.equals(constant.name) && + sort.equals(constant.sort); + } + + @Override + public List getFreeVariables() + { + return Collections.emptyList(); + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + return this; + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + return this; + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedIntVisitor.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedIntVisitor.java new file mode 100644 index 000000000..baa3c9dd2 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedIntVisitor.java @@ -0,0 +1,28 @@ +package edu.uiowa.smt.smtAst; + +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.smtAst.AbstractSmtAstVisitor; +import edu.uiowa.smt.smtAst.UninterpretedSort; + +public class UninterpretedIntVisitor extends AbstractSmtAstVisitor +{ + private boolean uninterpretedIntUsed = false; + + public UninterpretedIntVisitor() + { + } + + public boolean isUninterpretedIntUsed() + { + return uninterpretedIntUsed; + } + + @Override + public void visit(UninterpretedSort uninterpretedSort) + { + if (uninterpretedSort.equals(AbstractTranslator.uninterpretedInt)) + { + this.uninterpretedIntUsed = true; + } + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedSort.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedSort.java new file mode 100644 index 000000000..ea83af751 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/UninterpretedSort.java @@ -0,0 +1,50 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +public class UninterpretedSort extends Sort +{ + public UninterpretedSort(String sortName) + { + super(sortName, 0); + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + + if (!(object instanceof UninterpretedSort)) + { + return false; + } + + UninterpretedSort sort = (UninterpretedSort) object; + return sort.getName().equals(this.getName()); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Variable.java b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Variable.java new file mode 100644 index 000000000..375122608 --- /dev/null +++ b/SMT-Extension/src/main/java/edu/uiowa/smt/smtAst/Variable.java @@ -0,0 +1,113 @@ +/* + * This file is part of alloy2smt. + * Copyright (C) 2018-2019 The University of Iowa + * + * @author Mudathir Mohamed, Paul Meng + * + */ + +package edu.uiowa.smt.smtAst; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class Variable extends SmtExpr +{ + private final Declaration declaration; + + Variable(Declaration declaration) + { + this.declaration = declaration; + } + + public String getName() + { + return this.declaration.getName(); + } + + public Declaration getDeclaration() + { + return this.declaration; + } + + @Override + public void accept(SmtAstVisitor visitor) + { + visitor.visit(this); + } + + @Override + public Sort getSort() + { + return declaration.getSort(); + } + + @Override + public SmtExpr evaluate(Map functions) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean equals(Object object) + { + if (object == this) + { + return true; + } + if (!(object instanceof Variable)) + { + return false; + } + Variable constantObject = (Variable) object; + return declaration.equals(constantObject.declaration); + } + + @Override + public List getFreeVariables() + { + List freeVariables = new ArrayList<>(); + freeVariables.add(this); + return freeVariables; + } + + @Override + public SmtExpr substitute(Variable oldVariable, Variable newVariable) + { + if (this.equals(newVariable)) + { + throw new RuntimeException(String.format("Variable '%1$s' is not free in expression '%2$s'", newVariable, this)); + } + if (this.equals(oldVariable)) + { + return newVariable; + } + return this; + } + + @Override + public SmtExpr replace(SmtExpr oldSmtExpr, SmtExpr newSmtExpr) + { + if (oldSmtExpr.equals(this)) + { + return newSmtExpr; + } + return this; + } + + public boolean isOriginal() + { + return declaration.isOriginal(); + } + + @Override + public boolean containsExpr(SmtExpr expr) + { + if(expr.equals(this)) + { + return true; + } + return false; + } +} diff --git a/cnf/central.xml b/cnf/central.xml index e60bb8c11..cb550054d 100644 --- a/cnf/central.xml +++ b/cnf/central.xml @@ -1,4 +1,5 @@ - 4.0.0 @@ -60,6 +61,59 @@ slf4j-simple 1.7.5 - + + + + commons-cli + commons-cli + 1.4 + + + + org.antlr + antlr4-runtime + 4.9.2 + + + + javax.activation + activation + 1.1.1 + + + + + javax.xml.bind + jaxb-api + 2.3.1 + + + + com.sun.xml.bind + jaxb-impl + 2.3.1 + + + + + org.glassfish.jaxb + jaxb-core + 2.3.0.1 + + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.8 + + + + org.junit.jupiter + junit-jupiter-api + 5.6.2 + test + + diff --git a/org.alloytools.alloy.application/bnd.bnd b/org.alloytools.alloy.application/bnd.bnd index 298a54ca5..48ab7f995 100644 --- a/org.alloytools.alloy.application/bnd.bnd +++ b/org.alloytools.alloy.application/bnd.bnd @@ -5,7 +5,13 @@ lib/apple-osx-ui.jar;version=file,\ org.alloytools.pardinus;version=latest,\ org.alloytools.alloy.core;version=latest,\ - + SMT-Extension;version=latest,\ + org.antlr.antlr4-runtime,\ + com.fasterxml.jackson.core.jackson-annotations,\ + com.fasterxml.jackson.core.jackson-databind,\ + jaxb-api,\ + com.fasterxml.jackson.core.jackson-core + -testpath: \ osgi.enroute.junit.wrapper, \ osgi.enroute.hamcrest.wrapper, \ @@ -20,3 +26,4 @@ Private-Package: \ edu.mit.csail.sdg.alloy4graph,\ edu.mit.csail.sdg.alloy4viz,\ edu.mit.csail.sdg.alloy4whole,\ + edu.mit.csail.sdg.alloy4whole.instances diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4EnumerationTask.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4EnumerationTask.java new file mode 100644 index 000000000..8e26ae53e --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4EnumerationTask.java @@ -0,0 +1,116 @@ +package edu.mit.csail.sdg.alloy4whole; + +import static edu.mit.csail.sdg.alloy4.A4Preferences.ImplicitThis; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; +import java.util.Map; + +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.WorkerEngine; +import edu.mit.csail.sdg.alloy4whole.instances.AlloySolution; +import edu.mit.csail.sdg.ast.Command; +import edu.uiowa.alloy2smt.Utils; +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.smt.printers.SmtLibPrinter; +import edu.uiowa.smt.smtAst.SmtModel; + + +public class Cvc4EnumerationTask implements WorkerEngine.WorkerTask { + + private final String xmlFileName; + private Translation translation; + private AlloySolution alloySolution; + private Map alloyFiles; + private int commandIndex; + private String originalFileName; + + Cvc4EnumerationTask(String xmlFileName) throws Exception { + this.xmlFileName = xmlFileName; + } + + @Override + public void run(WorkerEngine.WorkerCallback workerCallback) throws Exception { + try { + if (!xmlFileName.equals(Cvc4Task.lastXmlFile)) { + workerCallback.callback(new Object[] { + "pop", "You can only enumerate the solutions of the last executed command." + }); + return; + } + + // read the solution from the xml file + alloySolution = AlloySolution.readFromXml(xmlFileName); + alloyFiles = alloySolution.getAlloyFiles(); + if (alloySolution.instances.size() == 0) { + throw new Exception("No instance found in the file " + xmlFileName); + } + // read the command from the only instance in the file + String command = alloySolution.instances.get(0).command; + originalFileName = alloySolution.instances.get(0).fileName; + + translation = translateToSMT(); + + // find the index of the matching command + List commands = translation.getCommands(); + for (commandIndex = 0; commandIndex < commands.size(); commandIndex++) { + if (command.equals(commands.get(commandIndex).toString())) { + break; + } + } + + // (block-model) + Cvc4Task.cvc4Process.sendCommand(SmtLibPrinter.BLOCK_MODEL); + // (check-sat) + String result = Cvc4Task.cvc4Process.sendCommand(SmtLibPrinter.CHECK_SAT); + if (result != null) { + switch (result) { + case "sat" : + // get a new model and save it + prepareInstance(commandIndex); + // tell alloySolution user interface that the last instance has changed + workerCallback.callback(new Object[] { + "declare", xmlFileName + }); + break; + case "unsat" : + workerCallback.callback(new Object[] { + "pop", "There are no more satisfying instances.\n\n" + "Note: due to symmetry breaking and other optimizations,\n" + "some equivalent solutions may have been omitted." + }); + break; + default : + workerCallback.callback(new Object[] { + "pop", "CVC4 solver returned unknown." + }); + } + } + } catch (Exception exception) { + StringWriter stringWriter = new StringWriter(); + exception.printStackTrace(new PrintWriter(stringWriter)); + throw new Exception(stringWriter.toString()); + } + } + + private Translation translateToSMT() throws IOException { + int resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + Cvc4Task.setAlloySettings(); + Translation translation = Utils.translate(alloyFiles, originalFileName, resolutionMode, Cvc4Task.alloySettings); + return translation; + } + + private void prepareInstance(int commandIndex) throws Exception { + String smtModel = Cvc4Task.cvc4Process.sendCommand(SmtLibPrinter.GET_MODEL); + Command command = translation.getCommands().get(commandIndex); + + SmtModel model = Cvc4Task.parseModel(smtModel); + + File xmlFile = new File(xmlFileName); + + String xmlFilePath = xmlFile.getAbsolutePath(); + + Cvc4Task.writeModelToAlloyXmlFile(translation, model, xmlFilePath, originalFileName, command, alloySolution.getAlloyFiles()); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Process.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Process.java new file mode 100644 index 000000000..8aed8bab6 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Process.java @@ -0,0 +1,149 @@ +package edu.mit.csail.sdg.alloy4whole; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Formatter; +import java.util.List; +import java.util.Scanner; + +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.WorkerEngine; + + +public class Cvc4Process { + + public static final String OS = System.getProperty("os.name"); + public static final String SEP = File.separator; + public static final String BIN_PATH = System.getProperty("user.dir") + SEP; + + private Process process; + private Scanner scanner; + private OutputStream outputStream; + private StringBuilder smtCode; + + private Cvc4Process(Process process) { + this.process = process; + this.scanner = new Scanner(process.getInputStream()); + this.outputStream = process.getOutputStream(); + this.smtCode = new StringBuilder(); + } + + public static Cvc4Process start(WorkerEngine.WorkerCallback workerCallback) throws Exception { + ProcessBuilder processBuilder = getProcessBuilder(); + + workerCallback.callback(new Object[] { + "", "Executing command: " + String.join(" ", processBuilder.command()) + "\n\n" + }); + Process process = processBuilder.start(); + + return new Cvc4Process(process); + } + + private String runCVC4() throws Exception { + ProcessBuilder processBuilder = getProcessBuilder(); + + String tempDirectory = System.getProperty("java.io.tmpdir"); + // save the smt file + File smtFile = File.createTempFile("tmp", ".smt2", new File(tempDirectory)); + Formatter formatter = new Formatter(smtFile); + formatter.format("%s", smtCode.toString()); + formatter.close(); + processBuilder.command().add(smtFile.getAbsolutePath()); + + // start the process + Process process = processBuilder.start(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append("/n"); + } + process.destroyForcibly(); + return stringBuilder.toString(); + } + + private static ProcessBuilder getProcessBuilder() throws Exception { + String cvc4; + + if (Util.onWindows()) { + cvc4 = BIN_PATH + "cvc4_win64.exe"; + } else if (Util.onMac()) { + cvc4 = BIN_PATH + "cvc4_mac"; + } else if (OS.startsWith("Linux")) { + cvc4 = BIN_PATH + "cvc4_linux"; + } else { + throw new Exception("No CVC4 binary available for the OS: " + OS); + } + + File cvc4Binary = new File(cvc4); + + if (!cvc4Binary.exists()) { + throw new Exception("CVC4 binary does not exist at: " + cvc4); + } + if (!cvc4Binary.canExecute()) { + throw new Exception("CVC4 binary cannot be executed at: " + cvc4); + } + + ProcessBuilder processBuilder = new ProcessBuilder(); + List command = new ArrayList<>(); + + command.add(cvc4); + + // tell cvc4 the input language is smt2 + command.add("--lang"); + command.add("smtlib2.6"); + // command.add("--print-success"); + + processBuilder.command(command); + + processBuilder.redirectErrorStream(true); + return processBuilder; + } + + public String sendCommand(String command) throws IOException { + outputStream.write((command + "\n").getBytes()); + smtCode.append(command + "\n"); + try { + outputStream.flush(); + } catch (java.io.IOException ioException) { + if (ioException.getMessage().toLowerCase().contains("pipe")) { + System.out.println(smtCode.toString()); + try { + String error = runCVC4(); + throw new IOException(error); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + throw ioException; + } + return receiveOutput(); + } + + private String receiveOutput() throws IOException { + String line = ""; + outputStream.write(("(echo success)\n").getBytes()); + outputStream.flush(); + + StringBuilder output = new StringBuilder(); + + while (scanner.hasNextLine()) { + line = scanner.nextLine(); + + if (line.equals("success")) { + return output.toString().trim(); + } + output.append(line).append("\n"); + } + return line; + } + + public void destroy() { + process.destroyForcibly(); + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Task.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Task.java new file mode 100644 index 000000000..282f520eb --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Cvc4Task.java @@ -0,0 +1,794 @@ +package edu.mit.csail.sdg.alloy4whole; + +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4FiniteModelFind; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4IncludeCommandScope; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4IntegerSingletonsOnly; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4ProduceUnsatCores; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4Timeout; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Formatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.WorkerEngine; +import edu.mit.csail.sdg.alloy4whole.instances.AlloyFile; +import edu.mit.csail.sdg.alloy4whole.instances.AlloySolution; +import edu.mit.csail.sdg.alloy4whole.instances.Atom; +import edu.mit.csail.sdg.alloy4whole.instances.Field; +import edu.mit.csail.sdg.alloy4whole.instances.Instance; +import edu.mit.csail.sdg.alloy4whole.instances.Signature; +import edu.mit.csail.sdg.alloy4whole.instances.Tuple; +import edu.mit.csail.sdg.alloy4whole.instances.Type; +import edu.mit.csail.sdg.alloy4whole.instances.Types; +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.ast.Sig; +import edu.uiowa.alloy2smt.Utils; +import edu.uiowa.alloy2smt.mapping.Mapper; +import edu.uiowa.alloy2smt.mapping.MappingField; +import edu.uiowa.alloy2smt.mapping.MappingSignature; +import edu.uiowa.alloy2smt.mapping.MappingType; +import edu.uiowa.alloy2smt.translators.Translation; +import edu.uiowa.alloy2smt.utils.AlloySettings; +import edu.uiowa.alloy2smt.utils.AlloyUnsatCore; +import edu.uiowa.smt.AbstractTranslator; +import edu.uiowa.smt.parser.SmtModelVisitor; +import edu.uiowa.smt.parser.antlr.SmtLexer; +import edu.uiowa.smt.parser.antlr.SmtParser; +import edu.uiowa.smt.printers.SmtLibPrinter; +import edu.uiowa.smt.smtAst.FunctionDeclaration; +import edu.uiowa.smt.smtAst.FunctionDefinition; +import edu.uiowa.smt.smtAst.IntConstant; +import edu.uiowa.smt.smtAst.SmtBinaryExpr; +import edu.uiowa.smt.smtAst.SmtExpr; +import edu.uiowa.smt.smtAst.SmtModel; +import edu.uiowa.smt.smtAst.SmtMultiArityExpr; +import edu.uiowa.smt.smtAst.SmtSettings; +import edu.uiowa.smt.smtAst.SmtUnaryExpr; +import edu.uiowa.smt.smtAst.SmtUnsatCore; +import edu.uiowa.smt.smtAst.UninterpretedConstant; + +public class Cvc4Task implements WorkerEngine.WorkerTask { + + public static final String tempDirectory = System.getProperty("java.io.tmpdir"); + + private final Map alloyFiles; + private final String originalFileName; + private final int resolutionMode; + private final int targetCommandIndex; + // store the results of "Execute All" command + private final List commandResults = new ArrayList<>(); + + // only one process for alloy editor + public static Cvc4Process cvc4Process; + private WorkerEngine.WorkerCallback workerCallback; + private Translation translation; + public static AlloySettings alloySettings = AlloySettings.getInstance(); + public static String lastXmlFile; + + Cvc4Task(Map alloyFiles, String originalFileName, int resolutionMode, int targetCommandIndex) { + this.alloyFiles = alloyFiles; + this.originalFileName = originalFileName; + this.resolutionMode = resolutionMode; + this.targetCommandIndex = targetCommandIndex; + } + + @Override + public void run(WorkerEngine.WorkerCallback workerCallback) throws Exception { + try { + this.workerCallback = workerCallback; + + final long startTranslate = System.currentTimeMillis(); + + translation = translateToSMT(); + + final long endTranslate = System.currentTimeMillis(); + + // callbackBold("Translation time: " + (endTranslate - startTranslate) + " ms\n"); + + String smtScript = translation.getOptimizedSmtScript().print(translation.getAlloySettings()); + + if (smtScript != null) { + cvc4Process = Cvc4Process.start(workerCallback); + + cvc4Process.sendCommand(smtScript); + + CommandResult commandResult; + + // execute all commands if targetCommandIndex < 0 + if (targetCommandIndex < 0) { + // surround each command except the last one with (push) and (pop) + for (int index = 0; index < translation.getCommands().size() - 1; index++) { + // (push) + cvc4Process.sendCommand(SmtLibPrinter.PUSH); + commandResult = solveCommand(index); + // (pop) + cvc4Process.sendCommand(SmtLibPrinter.POP); + this.commandResults.add(commandResult); + } + + // solve the last command without push and pop to view multiple models if sat + commandResult = solveCommand(translation.getCommands().size() - 1); + this.commandResults.add(commandResult); + + // display a summary of the results + displaySummary(workerCallback); + } else// execute only the target command + { + // solve the target command without push and pop to view multiple models if sat + commandResult = solveCommand(targetCommandIndex); + } + + if (commandResult != null && commandResult.xmlFileName != null) { + lastXmlFile = commandResult.xmlFileName; + } + + //ToDo: review when to destroy the process + //cvc4Process.destroy(); + } else { + callbackPlain("No translation found from alloy model to SMT"); + } + } catch (Exception exception) { + StringWriter stringWriter = new StringWriter(); + exception.printStackTrace(new PrintWriter(stringWriter)); + throw new Exception(stringWriter.toString()); + } + } + + + void displaySummary(WorkerEngine.WorkerCallback workerCallback) { + if (this.commandResults.size() > 1) { + callbackBold(commandResults.size() + " commands were executed. The results are:\n"); + for (CommandResult commandResult : this.commandResults) { + callbackPlain("#" + (commandResult.index + 1) + ": "); + + switch (commandResult.result) { + case "sat" : + callbackLink(commandResult.command.check ? "Counterexample found. " : "Instance found. ", "XML: " + commandResult.xmlFileName); + + callbackPlain(commandResult.command.label + " "); + + callbackPlain(commandResult.command.check ? "is invalid" : "is consistent"); + + break; + case "unsat" : + + callbackPlain(commandResult.command.label + " "); + + callbackPlain(commandResult.command.check ? "is valid" : " is unsatisfiable"); + + break; + default : + callbackPlain(commandResult.command.label + " is unknown"); + } + callbackPlain("\n"); + } + } + } + + private CommandResult solveCommand(int index) throws Exception { + String commandTranslation = translation.getOptimizedSmtScript(index).toString(); + + Command command = translation.getCommands().get(index); + + callbackBold("Executing " + command + "\n"); + + if (!Cvc4IncludeCommandScope.get()) { + ErrorWarning warning = new ErrorWarning(command.pos, "The scope is ignored by cvc4"); + callbackWarning(warning); + } + + final long startSolve = System.currentTimeMillis(); + + // (check-sat) + // callbackPlain( commandTranslation + SmtLibPrinter.CHECK_SAT); + String result = cvc4Process.sendCommand(commandTranslation + SmtLibPrinter.CHECK_SAT); + + final long endSolve = System.currentTimeMillis(); + long duration = (endSolve - startSolve); + // callbackBold("Solving time: " + duration + " ms\n"); + + callbackPlain("Satisfiability: " + result + "\n"); + + CommandResult commandResult = new CommandResult(); + commandResult.index = index; + commandResult.command = command; + commandResult.result = result; + + if (result != null) { + switch (result) { + case "sat" : + commandResult.xmlFileName = prepareInstance(index, duration); + break; + case "unsat" : + if (Cvc4ProduceUnsatCores.get()) { + commandResult.unsatCore = prepareUnsatCore(index, duration); + } + break; + default : + // callbackPlain("The satResult is unknown\n"); + } + } else { + callbackPlain("No satResult returned from cvc4\n"); + commandResult.result = ""; + } + + return commandResult; + } + + private Set prepareUnsatCore(int commandIndex, long duration) throws Exception { + String smtCore = cvc4Process.sendCommand(SmtLibPrinter.GET_UNSAT_CORE); + + callbackPlain("CVC4 found an "); + Object[] modelMessage = new Object[] { + "link", "unsat core", "MSG: " + smtCore + }; + workerCallback.callback(modelMessage); + callbackPlain("\n"); + + SmtUnsatCore smtUnsatCore = parseUnsatCore(smtCore); + AlloyUnsatCore alloyUnsatCore = AlloyUnsatCore.fromSmtUnsatCore(smtUnsatCore); + Set positions = alloyUnsatCore.getPositions(); + + String coreMessage = getCoreMessage(positions); + + Object[] message = new Object[] { + "link", "Core", coreMessage + }; + workerCallback.callback(message); + callbackPlain(" contains " + positions.size() + " top-level formulas. " + duration + "ms.\n"); + + // Command command = translation.getCommands().get(commandIndex); + // String satResult = "unsat"; + // int minimizedBefore = 0; + // int minimizedAfter = positions.size(); + // Object[] message = new Object []{satResult, command.check, command.expects, duration, null, coreMessage, minimizedBefore, minimizedAfter, duration}; + // workerCallback.callback(message); + + return positions; + } + + private String getCoreMessage(Set positions) { + Pair,Set> core = new Pair<>(positions, Collections.emptySet()); + + String coreMessage; + OutputStream fs = null; + ObjectOutputStream os = null; + try { + // generate unsat core file + File coreFile = File.createTempFile("tmp", ".core", new File(tempDirectory)); + fs = new FileOutputStream(coreFile); + os = new ObjectOutputStream(fs); + os.writeObject(core); + os.writeObject(positions); + coreMessage = "CORE: " + coreFile.getAbsolutePath(); + } catch (Throwable ex) { + coreMessage = ""; + } finally { + Util.close(os); + Util.close(fs); + } + return coreMessage; + } + + private void callbackLink(String log, String link) { + workerCallback.callback(new Object[] { + "link", log, link + }); + } + + private void callbackPlain(String log) { + workerCallback.callback(new Object[] { + "", log + }); + workerCallback.callback(new Object[] { + "", "" + }); + } + + private void callbackBold(String log) { + workerCallback.callback(new Object[] { + "S2", "\n" + }); + workerCallback.callback(new Object[] { + "S2", log + }); + workerCallback.callback(new Object[] { + "S2", "\n" + }); + } + + private void callbackWarning(ErrorWarning warning) { + workerCallback.callback(new Object[] { + "warning", warning + }); + } + + + /** + * gets a model from cvc4 if the satResult is sat and saves it into a new xml + * file and return its path + * + * @param commandIndex the index of the sat command + * @param duration the solving duration in milli seconds + * @return a path to the xml file where the model is saved + * @throws Exception + */ + private String prepareInstance(int commandIndex, long duration) throws Exception { + String smtModel = cvc4Process.sendCommand(SmtLibPrinter.GET_MODEL); + + callbackPlain("CVC4 found a "); + Object[] modelMessage = new Object[] { + "link", "model", "MSG: " + smtModel + }; + workerCallback.callback(modelMessage); + callbackPlain("\n"); + + // callbackPlain(smtModel + "\n"); + + Command command = translation.getCommands().get(commandIndex); + + // smtModel= showInputDialog(smtModel); + + SmtModel model = parseModel(smtModel); + + File xmlFile = File.createTempFile("tmp", ".smt.xml", new File(tempDirectory)); + + String xmlFilePath = xmlFile.getAbsolutePath(); + + Instance instance = writeModelToAlloyXmlFile(translation, model, xmlFilePath, originalFileName, command, alloyFiles); + + // generate alloy code that restricts the model to be the instance found + String alloyCode = instance.generateAlloyCode(); + File alloyFile = File.createTempFile("tmp", ".als", new File(tempDirectory)); + Formatter formatter = new Formatter(alloyFile); + formatter.format("%s", alloyCode); + formatter.close(); + + String satResult = "sat"; + Object[] message = new Object[] { + satResult, command.check, command.expects, xmlFilePath, null, duration + }; + workerCallback.callback(message); + + return xmlFilePath; + } + + public static Instance writeModelToAlloyXmlFile(Translation translation, SmtModel model, String xmlFileName, String originalFileName, Command command, Map alloyFiles) throws Exception { + Mapper mapper = translation.getMapper(); + + Map functionsMap = new HashMap<>(); + + for (FunctionDeclaration function : model.getFunctions()) { + FunctionDefinition definition = (FunctionDefinition) function; + functionsMap.put(function.getName(), definition); + } + + List signatures = new ArrayList<>(); + + for (MappingSignature mappingSignature : mapper.signatures) { + Signature signature = getSignature(functionsMap, mappingSignature); + signatures.add(signature); + } + + + List fields = new ArrayList<>(); + + for (MappingField mappingField : mapper.fields) { + Field field = getField(functionsMap, mappingField); + fields.add(field); + } + + // addSpecialSignatures(translation, functionsMap, signatures ,fields); + + Instance instance = new Instance(); + instance.signatures = signatures; + instance.fields = fields; + instance.bitWidth = command.bitwidth >= 0 ? command.bitwidth : 4; + instance.maxSeq = command.maxseq >= 0 ? command.maxseq : 4; + instance.command = command.toString(); + + instance.fileName = originalFileName; + + AlloySolution alloySolution = new AlloySolution(); + alloySolution.instances = new ArrayList<>(); + alloySolution.instances.add(instance); + alloySolution.buildDate = java.time.Instant.now().toString(); + alloySolution.alloyFiles = new ArrayList<>(); + + for (Map.Entry entry : alloyFiles.entrySet()) { + alloySolution.alloyFiles.add(new AlloyFile(entry.getKey(), entry.getValue())); + } + + alloySolution.writeToXml(xmlFileName); + return instance; + } + + private static void addSpecialSignatures(Translation translation, Map functionsMap, List signatures, List fields) throws Exception { + Signature signature = new Signature(); + signature.label = "Operations"; + Sig.SubsetSig operations = new Sig.SubsetSig(signature.label, Arrays.asList(Sig.SIGINT)); + signature.id = translation.getSigId(operations); + signature.parentId = translation.getSigId(Sig.SIGINT); + signature.types.add(new Type(signature.parentId)); + + signature.builtIn = "no"; + signature.isAbstract = "no"; + signature.isOne = "no"; + signature.isLone = "no"; + signature.isSome = "no"; + signature.isPrivate = "no"; + signature.isMeta = "no"; + signature.isExact = "no"; + signature.isEnum = "no"; + signatures.add(signature); + addSpecialFields(functionsMap, fields, signature.id); + } + + private static void addSpecialFields(Map functionsMap, List fields, int parentId) throws Exception { + if (functionsMap.containsKey(AbstractTranslator.plus)) { + fields.add(getSpecialField(functionsMap, AbstractTranslator.plus, parentId)); + } + if (functionsMap.containsKey(AbstractTranslator.minus)) { + fields.add(getSpecialField(functionsMap, AbstractTranslator.minus, parentId)); + } + if (functionsMap.containsKey(AbstractTranslator.multiply)) { + fields.add(getSpecialField(functionsMap, AbstractTranslator.multiply, parentId)); + } + if (functionsMap.containsKey(AbstractTranslator.divide)) { + fields.add(getSpecialField(functionsMap, AbstractTranslator.divide, parentId)); + } + if (functionsMap.containsKey(AbstractTranslator.mod)) { + fields.add(getSpecialField(functionsMap, AbstractTranslator.mod, parentId)); + } + } + + private static Signature getSignature(Map functionsMap, MappingSignature mappingSignature) throws Exception { + Signature signature = new Signature(); + + // get signature info from the mapping + signature.label = mappingSignature.label; + signature.id = mappingSignature.id; + + if (mappingSignature.parents.size() == 1) { + signature.parentId = mappingSignature.parents.get(0); + } + + // add types for subset + if (mappingSignature.isSubset) { + for (Integer id : mappingSignature.parents) { + signature.types.add(new Type(id)); + } + } + + signature.builtIn = mappingSignature.builtIn ? "yes" : "no"; + signature.isAbstract = mappingSignature.isAbstract ? "yes" : "no"; + signature.isOne = mappingSignature.isOne ? "yes" : "no"; + signature.isLone = mappingSignature.isLone ? "yes" : "no"; + signature.isSome = mappingSignature.isSome ? "yes" : "no"; + signature.isPrivate = mappingSignature.isPrivate ? "yes" : "no"; + signature.isMeta = mappingSignature.isMeta ? "yes" : "no"; + signature.isExact = mappingSignature.isExact ? "yes" : "no"; + signature.isEnum = mappingSignature.isEnum ? "yes" : "no"; + + // the signature Int is treated differently + if (signature.label.equals("Int")) { + return signature; + } + + // get the corresponding function from the model + FunctionDefinition function = functionsMap.get(mappingSignature.functionName); + if (function == null) { + // throw new Exception("Can not find the function "+ mappingSignature.functionName + " for signature "+ signature.label + "in the model.") ; + + // due to some optimization, some signatures may be lost. So here we assume empty atoms. + signature.atoms = new ArrayList<>(); + } else { + signature.atoms = getAtoms(function.smtExpr, functionsMap); + } + return signature; + } + + private static Field getSpecialField(Map functionsMap, String fieldName, int parentId) throws Exception { + Field field = new Field(); + field.label = fieldName; + field.id = fieldName.hashCode(); + field.parentId = parentId; + + field.isPrivate = "no"; + field.isMeta = "no"; + + // get the corresponding function from the model + FunctionDefinition function = functionsMap.get(fieldName); + if (function == null) { + throw new Exception("Can not find the function " + fieldName + " for field " + field.label + "in the model."); + } + field.tuples = getTuples(function.smtExpr, functionsMap); + field.types = Collections.singletonList(new Types()); + //ToDo: refactor these magic numbers + field.types.get(0).types = Arrays.stream(new int[] { + parentId, parentId, parentId + }).mapToObj(Type::new).collect(Collectors.toList()); + + return field; + } + + + private static Field getField(Map functionsMap, MappingField mappingField) throws Exception { + Field field = new Field(); + + // get field info from the mapping + field.label = mappingField.label; + field.id = mappingField.id; + field.parentId = mappingField.parentId; + + field.isPrivate = mappingField.isPrivate ? "yes" : "no"; + field.isMeta = mappingField.isMeta ? "yes" : "no"; + + // get the corresponding function from the model + FunctionDefinition function = functionsMap.get(mappingField.functionName); + if (function == null) { + // throw new Exception("Can not find the function "+ mappingField.functionName + " for field "+ field.label + "in the model.") ; + + // due to some optimization, some signatures may be lost. So here we assume empty atoms. + field.tuples = new ArrayList<>(); + } else { + field.tuples = getTuples(function.smtExpr, functionsMap); + } + + field.types = getTypes(mappingField); + + return field; + } + + private static List getTypes(MappingField mappingField) { + List types = new ArrayList<>(); + for (List list : mappingField.types) { + Types alloyTypes = new Types(); + alloyTypes.types = list.stream().map(t -> new Type(t.id)).collect(Collectors.toList()); + types.add(alloyTypes); + } + return types; + } + + private static List getTuples(SmtExpr smtExpr, Map functionsMap) { + List tuples = new ArrayList<>(); + + if (smtExpr instanceof SmtUnaryExpr) { + SmtUnaryExpr unary = (SmtUnaryExpr) smtExpr; + switch (unary.getOp()) { + case EMPTYSET : + return new ArrayList<>(); + case SINGLETON : { + SmtExpr unarySmtExpr = unary.getExpr(); + if (unarySmtExpr instanceof SmtMultiArityExpr) { + SmtMultiArityExpr multiArity = (SmtMultiArityExpr) unarySmtExpr; + + if (multiArity.getOp() == SmtMultiArityExpr.Op.MKTUPLE) { + List atoms = getAtoms(multiArity, functionsMap); + Tuple tuple = new Tuple(); + tuple.atoms = atoms; + return Collections.singletonList(tuple); + } + + throw new UnsupportedOperationException(); + } + throw new UnsupportedOperationException(); + } + default : + throw new UnsupportedOperationException(); + } + } + + if (smtExpr instanceof SmtBinaryExpr) { + SmtBinaryExpr binary = (SmtBinaryExpr) smtExpr; + + switch (binary.getOp()) { + case UNION : { + tuples.addAll(getTuples(binary.getA(), functionsMap)); + tuples.addAll(getTuples(binary.getB(), functionsMap)); + return tuples; + } + default : + throw new UnsupportedOperationException(); + } + } + + throw new UnsupportedOperationException(); + } + + private static List getAtoms(SmtExpr smtExpr, Map functions) { + List atoms = new ArrayList<>(); + + if (smtExpr instanceof UninterpretedConstant) { + UninterpretedConstant uninterpretedConstant = (UninterpretedConstant) smtExpr; + if (uninterpretedConstant.getSort().equals(AbstractTranslator.atomSort)) { + atoms.add(new Atom(uninterpretedConstant.getName())); + } + if (uninterpretedConstant.getSort().equals(AbstractTranslator.uninterpretedInt)) { + IntConstant intConstant = (IntConstant) uninterpretedConstant.evaluate(functions); + atoms.add(new Atom(intConstant.getValue())); + } + return atoms; + } + + //ToDo: review removing this which is replaced with uninterpretedInt + if (smtExpr instanceof IntConstant) { + IntConstant intConstant = (IntConstant) smtExpr; + atoms.add(new Atom(intConstant.getValue())); + return atoms; + } + + if (smtExpr instanceof SmtUnaryExpr) { + SmtUnaryExpr unary = (SmtUnaryExpr) smtExpr; + switch (unary.getOp()) { + case EMPTYSET : + return new ArrayList<>(); + case SINGLETON : { + return getAtoms(unary.getExpr(), functions); + } + default : + throw new UnsupportedOperationException(); + } + } + + if (smtExpr instanceof SmtBinaryExpr) { + SmtBinaryExpr binary = (SmtBinaryExpr) smtExpr; + + switch (binary.getOp()) { + case UNION : { + atoms.addAll(getAtoms(binary.getA(), functions)); + atoms.addAll(getAtoms(binary.getB(), functions)); + return atoms; + } + default : + throw new UnsupportedOperationException(); + } + } + + if (smtExpr instanceof SmtMultiArityExpr) { + SmtMultiArityExpr multiArity = (SmtMultiArityExpr) smtExpr; + switch (multiArity.getOp()) { + case MKTUPLE : { + for (SmtExpr expr : multiArity.getExprs()) { + atoms.addAll(getAtoms(expr, functions)); + } + + return atoms; + } + + default : + throw new UnsupportedOperationException(); + } + } + + throw new UnsupportedOperationException(); + } + + private Translation translateToSMT() throws IOException { + setAlloySettings(); + + Translation translation = Utils.translate(alloyFiles, originalFileName, resolutionMode, alloySettings); + + // callbackBold("Translation output"); + // callbackPlain(translation.getSmtScript()); + + // output the smt file + generateSmtFile(translation, false); + generateSmtFile(translation, true); + + // output the mapping + File jsonFile = File.createTempFile("tmp", ".mapping.json", new File(tempDirectory)); + translation.getMapper().writeToJson(jsonFile.getPath()); + + callbackPlain("\nGenerated json mapping file: "); + Object[] jsonMessage = new Object[] { + "link", jsonFile.getAbsolutePath(), "CNF: " + jsonFile.getAbsolutePath() + }; + workerCallback.callback(jsonMessage); + callbackPlain("\n"); + return translation; + } + + private void generateSmtFile(Translation translation, boolean isOptimized) throws IOException { + File smtFile = File.createTempFile("tmp", ".smt2", new File(tempDirectory)); + String allCommands = translation.translateAllCommandsWithCheckSat(isOptimized); + Formatter formatter = new Formatter(smtFile); + formatter.format("%s", allCommands); + formatter.close(); + if (isOptimized) { + callbackPlain("\nGenerated optimized smt2 file: "); + } else { + callbackPlain("\nGenerated smt2 file: "); + } + Object[] smtMessage = new Object[] { + "link", smtFile.getAbsolutePath(), "CNF: " + smtFile.getAbsolutePath() + }; + workerCallback.callback(smtMessage); + } + + public static void setAlloySettings() { + // (set-option :tlimit 30000) + alloySettings.putSolverOption(SmtSettings.TLIMIT, Cvc4Timeout.get().toString()); + //(set-option :produce-unsat-cores false) + alloySettings.putSolverOption(SmtSettings.PRODUCE_UNSAT_CORES, Cvc4ProduceUnsatCores.get().toString()); + //(set-option :finite-model-find false) + alloySettings.putSolverOption(SmtSettings.FINITE_MODEL_FIND, Cvc4FiniteModelFind.get().toString()); + alloySettings.includeCommandScope = Cvc4IncludeCommandScope.get(); + alloySettings.produceUnsatCore = Cvc4ProduceUnsatCores.get(); + alloySettings.finiteModelFinding = Cvc4FiniteModelFind.get(); + alloySettings.integerSingletonsOnly = Cvc4IntegerSingletonsOnly.get(); + } + + //ToDo: replace this with a call edu.uiowa.smt.Result.parseModel + public static SmtModel parseModel(String model) { + CharStream charStream = CharStreams.fromString(model); + + SmtLexer lexer = new SmtLexer(charStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + SmtParser parser = new SmtParser(tokenStream); + + ParseTree tree = parser.model(); + SmtModelVisitor visitor = new SmtModelVisitor(); + + SmtModel smtModel = (SmtModel) visitor.visit(tree); + + return smtModel; + } + + //ToDo: replace this with a call edu.uiowa.smt.Result.parseUnsatCore + public static SmtUnsatCore parseUnsatCore(String smtCore) { + CharStream charStream = CharStreams.fromString(smtCore); + + SmtLexer lexer = new SmtLexer(charStream); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + SmtParser parser = new SmtParser(tokenStream); + + ParseTree tree = parser.getUnsatCore(); + SmtModelVisitor visitor = new SmtModelVisitor(); + + SmtUnsatCore smtUnsatCore = (SmtUnsatCore) visitor.visit(tree); + return smtUnsatCore; + } + + public static String showInputDialog(String text) { + JTextArea textArea = new JTextArea(text); + textArea.setSize(textArea.getPreferredSize().width, textArea.getPreferredSize().height); + JOptionPane.showConfirmDialog(null, new JScrollPane(textArea), "Debugging", JOptionPane.OK_OPTION); + return textArea.getText(); + } + + private class CommandResult { + + public int index; + public Command command; + public String result; + public String xmlFileName; + public Set unsatCore; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java index b35e7a0a1..b3d39ac5f 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java @@ -23,11 +23,16 @@ import static edu.mit.csail.sdg.alloy4.A4Preferences.AutoVisualize; import static edu.mit.csail.sdg.alloy4.A4Preferences.CoreGranularity; import static edu.mit.csail.sdg.alloy4.A4Preferences.CoreMinimization; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4FiniteModelFind; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4IncludeCommandScope; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4ProduceUnsatCores; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Cvc4Timeout; import static edu.mit.csail.sdg.alloy4.A4Preferences.DecomposePref; import static edu.mit.csail.sdg.alloy4.A4Preferences.FontName; import static edu.mit.csail.sdg.alloy4.A4Preferences.FontSize; import static edu.mit.csail.sdg.alloy4.A4Preferences.ImplicitThis; import static edu.mit.csail.sdg.alloy4.A4Preferences.InferPartialInstance; +import static edu.mit.csail.sdg.alloy4.A4Preferences.KODKOD; import static edu.mit.csail.sdg.alloy4.A4Preferences.LAF; import static edu.mit.csail.sdg.alloy4.A4Preferences.Model0; import static edu.mit.csail.sdg.alloy4.A4Preferences.Model1; @@ -35,6 +40,7 @@ import static edu.mit.csail.sdg.alloy4.A4Preferences.Model3; import static edu.mit.csail.sdg.alloy4.A4Preferences.NoOverflow; import static edu.mit.csail.sdg.alloy4.A4Preferences.RecordKodkod; +import static edu.mit.csail.sdg.alloy4.A4Preferences.RelationalSolver; import static edu.mit.csail.sdg.alloy4.A4Preferences.SkolemDepth; import static edu.mit.csail.sdg.alloy4.A4Preferences.Solver; import static edu.mit.csail.sdg.alloy4.A4Preferences.SubMemory; @@ -71,6 +77,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; +import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.reflect.Method; import java.net.URISyntaxException; import java.util.ArrayList; @@ -1184,7 +1192,7 @@ private Runner doRun(Integer commandIndex) { if (i >= commands.size()) i = commands.size() - 1; SimpleCallback1 cb = new SimpleCallback1(this, null, log, VerbosityPref.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); - SimpleTask1 task = new SimpleTask1(); + A4Options opt = new A4Options(); opt.tempDirectory = alloyHome(frame) + fs + "tmp"; opt.solverDirectory = alloyHome(frame) + fs + "binary"; @@ -1198,12 +1206,23 @@ private Runner doRun(Integer commandIndex) { opt.decompose_mode = DecomposePref.get().ordinal(); opt.originalFilename = Util.canon(text.get().getFilename()); opt.solver = Solver.get(); - task.bundleIndex = i; - task.bundleWarningNonFatal = WarningNonfatal.get(); - task.map = text.takeSnapshot(); - task.options = opt.dup(); - task.resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; - task.tempdir = maketemp(frame); + + WorkerEngine.WorkerTask task; + + Map alloyFiles = text.takeSnapshot(); + int resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + if (RelationalSolver.get().equals(KODKOD)) { + SimpleTask1 kodkodTask = new SimpleTask1(); + kodkodTask.bundleIndex = i; + kodkodTask.bundleWarningNonFatal = WarningNonfatal.get(); + kodkodTask.map = text.takeSnapshot(); + kodkodTask.options = opt.dup(); + kodkodTask.resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + kodkodTask.tempdir = maketemp(frame); + task = kodkodTask; + } else { + task = new Cvc4Task(alloyFiles, opt.originalFilename, resolutionMode, i); + } try { runmenu.setEnabled(false); runbutton.setVisible(false); @@ -1441,6 +1460,25 @@ private Runner doRefreshOption() { addToMenu(optmenu, AntiAlias); addToMenu(optmenu, A4Preferences.LAF); + optmenu.addSeparator(); + // CVC4 options + JMenu relationalSolverMenu = addToMenu(optmenu, RelationalSolver); + JMenu cvc4TimeoutMenu = addToMenu(optmenu, Cvc4Timeout); + List cvc4BooleanPreferences = addToMenu(optmenu, Cvc4IncludeCommandScope, Cvc4ProduceUnsatCores, Cvc4FiniteModelFind); + //, Cvc4IntegerSingletonsOnly + + if (RelationalSolver.get().equals(KODKOD)) { + cvc4TimeoutMenu.setEnabled(false); + for (JMenuItem item : cvc4BooleanPreferences) { + item.setEnabled(false); + } + } else { + cvc4TimeoutMenu.setEnabled(true); + for (JMenuItem item : cvc4BooleanPreferences) { + item.setEnabled(true); + } + } + optmenu.addSeparator(); addToMenu(optmenu, Solver); @@ -1789,9 +1827,29 @@ public String compute(Object input) { if (WorkerEngine.isBusy()) throw new RuntimeException("Alloy4 is currently executing a SAT solver command. Please wait until that command has finished."); SimpleCallback1 cb = new SimpleCallback1(SimpleGUI.this, viz, log, VerbosityPref.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); - SimpleTask2 task = new SimpleTask2(); - task.filename = arg[0]; - task.index = Integer.valueOf(arg[1]); + + WorkerEngine.WorkerTask task; + + if (RelationalSolver.get().equals(KODKOD)) { + SimpleTask2 task2 = new SimpleTask2(); + task2.filename = arg[0]; + task2.index = Integer.valueOf(arg[1]); + subrunningTask = task2.index < 1 ? 2 : 3; // [electrum] whether global iteration + task = task2; + } else { + try { + task = new Cvc4EnumerationTask(arg[1]); + subrunningTask = 2; + } catch (Exception exception) { + StringWriter stringWriter = new StringWriter(); + exception.printStackTrace(new PrintWriter(stringWriter)); + log.logBold(stringWriter.toString()); + log.logDivider(); + log.flush(); + return arg[1]; + } + } + try { if (AlloyCore.isDebug()) WorkerEngine.runLocally(task, cb); @@ -1806,7 +1864,6 @@ public String compute(Object input) { doStop(2); return arg[0]; } - subrunningTask = task.index < 1 ? 2 : 3; // [electrum] whether global iteration runmenu.setEnabled(false); runbutton.setVisible(false); showbutton.setEnabled(false); @@ -2384,12 +2441,15 @@ public Object do_action(Object sender, Event e, Object arg) { * Creates menu items from boolean preferences (prefs) and adds * them to a given parent menu (parent). */ - private void addToMenu(JMenu parent, BooleanPref... prefs) { + private List addToMenu(JMenu parent, BooleanPref... prefs) { + List menuItems = new ArrayList<>(); for (BooleanPref pref : prefs) { Action action = pref.getTitleAction(); Object name = action.getValue(Action.NAME); - menuItem(parent, name + ": " + (pref.get() ? "Yes" : "No"), action); + JMenuItem item = menuItem(parent, name + ": " + (pref.get() ? "Yes" : "No"), action); + menuItems.add(item); } + return menuItems; } /** diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java index 1531dc389..3960885f1 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java @@ -22,6 +22,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.io.Serializable; +import java.io.StringWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; @@ -50,6 +51,7 @@ import edu.mit.csail.sdg.alloy4.XMLNode; import edu.mit.csail.sdg.alloy4viz.StaticInstanceReader; import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.alloy4whole.instances.AlloySolution; import edu.mit.csail.sdg.ast.Command; import edu.mit.csail.sdg.ast.Module; import edu.mit.csail.sdg.ast.Sig; @@ -265,8 +267,32 @@ else if (warnings.size() > 1) results.add(filename); (new File(filename)).deleteOnExit(); gui.doSetLatest(filename); - span.setLength(len3); - span.log(" "); + + // generate model constraints + try { + AlloySolution alloySolution = AlloySolution.readFromXml(filename); + + span.log("\nGenerated xml instance file: "); + + span.logLink(filename, "CNF: " + filename); + + span.log("\n"); + + String constraints = alloySolution.instances.get(0).generateAlloyCode(); + span.log("Generated " + (chk ? "counterexample" : "instance")); + + span.logLink(" constraints", "MSG: " + constraints); + span.log("\n"); + + } catch (Exception e) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + OurDialog.showtext("Error", sw.toString()); + } + + //span.setLength(len3); + span.log("\n "); span.logLink(chk ? "Counterexample" : "Instance", "XML: " + filename); span.log(" found. "); span.logLink(chk ? "Assertion" : "Predicate", formula); diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloyFile.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloyFile.java new file mode 100644 index 000000000..283c3fbb9 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloyFile.java @@ -0,0 +1,28 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "source") +public class AlloyFile +{ + @XmlAttribute(name = "filename") + @JsonProperty("fileName") + public String fileName; + + @XmlAttribute(name = "content") + @JsonProperty("content") + public String content; + + public AlloyFile() + { + } + + public AlloyFile(String fileName, String content) + { + this.fileName = fileName; + this.content = content; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloySolution.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloySolution.java new file mode 100644 index 000000000..37297044d --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/AlloySolution.java @@ -0,0 +1,77 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "alloy") +public class AlloySolution +{ + @XmlElement(name = "instance") + @JsonProperty("instances") + public List instances; + + @XmlAttribute(name = "builddate") + @JsonProperty("buildDate") + public String buildDate; + + @XmlElement(name = "source") + @JsonProperty("alloyFiles") + public List alloyFiles; + + public Map getAlloyFiles() + { + Map files = new HashMap<>(); + if(alloyFiles != null) + { + for (AlloyFile file: alloyFiles) + { + files.put(file.fileName, file.content); + } + } + return files; + } + + public void writeToXml(String xmlFile) throws JAXBException + { + JAXBContext context = JAXBContext.newInstance(AlloySolution.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.marshal(this, new File(xmlFile)); + } + + public static AlloySolution readFromXml(String xmlFile) throws JAXBException + { + JAXBContext context = JAXBContext.newInstance(AlloySolution.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + AlloySolution alloySolution = (AlloySolution) unmarshaller.unmarshal(new File(xmlFile)); + return alloySolution; + } + + public void writeToJson(String jsonFile) throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(jsonFile), this); + } + + public static AlloySolution readFromJson(String jsonFile) throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(); + AlloySolution alloySolution = objectMapper.readValue(new File(jsonFile), AlloySolution.class); + return alloySolution; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Atom.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Atom.java new file mode 100644 index 000000000..0550cdbe9 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Atom.java @@ -0,0 +1,29 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "atom") +public class Atom +{ + @XmlAttribute(name = "label") + @JsonProperty("label") + public String label; + + public Atom() + { + } + + public Atom(String label) + { + this.label = label; + } + + @Override + public String toString() + { + return label; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Field.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Field.java new file mode 100644 index 000000000..07e5d7a8a --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Field.java @@ -0,0 +1,42 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import java.util.ArrayList; +import java.util.List; + +@XmlRootElement(name = "field") +public class Field +{ + @XmlAttribute(name = "label") + @JsonProperty("label") + public String label; + + @XmlAttribute(name = "ID") + @JsonProperty("id") + public int id; + + @XmlAttribute(name = "parentID") + @JsonProperty("parentId") + public int parentId; + + @XmlAttribute(name = "private") + @JsonProperty("isPrivate") + public String isPrivate; + + @XmlAttribute(name = "meta") + @JsonProperty("isMeta") + public String isMeta; + + @XmlElement(name = "tuple") + @JsonProperty("tuples") + public List tuples; + + @XmlElement(name = "types") + @JsonProperty("types") + public List types = new ArrayList<>(); +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Instance.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Instance.java new file mode 100644 index 000000000..3f2b22914 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Instance.java @@ -0,0 +1,151 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import edu.uiowa.alloy2smt.utils.AlloyUtils; + +@XmlRootElement( + name = "instance" ) +public class Instance { + + @XmlElement( + name = "sig" ) + @JsonProperty("signatures" ) + public List signatures; + + @XmlElement( + name = "field" ) + @JsonProperty("fields" ) + public List fields; + + @XmlAttribute( + name = "bitwidth" ) + @JsonProperty("bitWidth" ) + public int bitWidth = 4; + + @XmlAttribute( + name = "maxseq" ) + @JsonProperty("maxSeq" ) + public int maxSeq = 4; + + @XmlAttribute( + name = "mintrace" ) + @JsonProperty("minTrace" ) + public int minTrace = -1; + + @XmlAttribute( + name = "maxtrace" ) + @JsonProperty("maxTrace" ) + public int maxTrace = -1; + + @XmlAttribute( + name = "command" ) + @JsonProperty("command" ) + public String command; + + @XmlAttribute( + name = "filename" ) + @JsonProperty("fileName" ) + public String fileName; + + @XmlAttribute( + name = "tracelength" ) + @JsonProperty("traceLength" ) + public int traceLength = 1; + + @XmlAttribute( + name = "backloop" ) + @JsonProperty("backLoop" ) + public int backLoop = 0; + + public String generateAlloyCode() { + Set allAtoms = new HashSet<>(); + StringBuilder code = new StringBuilder(); + for (Signature signature : signatures) { + code.append(generateSignatureCode(signature, allAtoms)); + } + if (allAtoms.size() > 0) { + List atoms = new ArrayList<>(allAtoms); + code.append("one sig "); + code.append(atoms.get(0)); + for (int i = 1; i < atoms.size(); i++) { + code.append(", " + atoms.get(i)); + } + code.append(" in univ {}\n"); + } + + if (fields != null) { + for (Field field : fields) { + code.append(generateFieldCode(field)); + } + } + + return code.toString(); + } + + private String generateSignatureCode(Signature signature, Set allAtoms) { + if (signature.builtIn != null && signature.builtIn.equals("yes")) { + return ""; + } else { + if (signature.atoms != null && signature.atoms.size() > 0) { + // the signature is equal to the union of all atoms + StringBuilder code = new StringBuilder(); + String atom = AlloyUtils.sanitizeAtom(signature.atoms.get(0).label); + code.append("fact { " + signature.label.replace("this/", "") + " = " + atom); + allAtoms.add(atom); + for (int i = 1; i < signature.atoms.size(); i++) { + atom = AlloyUtils.sanitizeAtom(signature.atoms.get(i).label); + allAtoms.add(atom); + code.append(" + " + atom); + } + code.append(" }\n"); + if (signature.isPrivate == null || !signature.isPrivate.equals("yes")) { + return code.toString(); + } else { + return ""; + } + } + // no atoms means cardinality is zero + return "fact { #" + signature.label.replace("this/", "") + " = 0 }\n"; + } + } + + private String generateFieldCode(Field field) { + if (field.tuples != null && field.tuples.size() > 0) { + StringBuilder code = new StringBuilder(); + // the field is equal to the union of all tuples + + code.append("fact { " + field.label + " = " + generateTupleCode(field.tuples.get(0))); + for (int i = 1; i < field.tuples.size(); i++) { + code.append(" + " + generateTupleCode(field.tuples.get(i))); + } + code.append(" }\n"); + if (field.isPrivate == null || !field.isPrivate.equals("yes")) { + return code.toString(); + } else { + return ""; + } + } else { + // no atoms means cardinality is zero + return "fact { #" + field.label + " = 0 } \n"; + } + } + + private String generateTupleCode(Tuple tuple) { + StringBuilder code = new StringBuilder(); + code.append(AlloyUtils.sanitizeAtom(tuple.atoms.get(0).label)); + for (int i = 1; i < tuple.atoms.size(); i++) { + code.append(" -> " + AlloyUtils.sanitizeAtom(tuple.atoms.get(i).label)); + } + return code.toString(); + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Signature.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Signature.java new file mode 100644 index 000000000..0de709b6c --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Signature.java @@ -0,0 +1,73 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +@XmlRootElement(name = "sig") +public class Signature +{ + @XmlElement(name = "atom") + @JsonProperty("atoms") + public List atoms; + + @XmlElement(name = "type") + @JsonProperty("types") + public List types = new ArrayList<>(); + + @XmlAttribute(name = "label") + @JsonProperty("label") + public String label; + + @XmlAttribute(name = "ID") + @JsonProperty("id") + public int id; + + @XmlAttribute(name = "parentID") + @JsonProperty("parents") + public int parentId; + + @XmlAttribute(name = "builtin") + @JsonProperty("builtIn") + public String builtIn; // yes/no + + @XmlAttribute(name = "abstract") + public String isAbstract; // yes/no + + @XmlAttribute(name = "one") + @JsonProperty("isOne") + public String isOne; // yes/no + + @XmlAttribute(name = "lone") + @JsonProperty("isLone") + public String isLone; // yes/no + + @XmlAttribute(name = "some") + @JsonProperty("isSome") + public String isSome; // yes/no + + @XmlAttribute(name = "private") + public String isPrivate; // yes/no + + @XmlAttribute(name = "meta") + @JsonProperty("isMeta") + public String isMeta; // yes/no + + @XmlAttribute(name = "exact") + @JsonProperty("isExact") + public String isExact; // yes/no + + @XmlAttribute(name = "enum") + @JsonProperty("isEnum") + public String isEnum; // yes/no + + @Override + public String toString() + { + return label; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Tuple.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Tuple.java new file mode 100644 index 000000000..7f87239bf --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Tuple.java @@ -0,0 +1,15 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +@XmlRootElement(name = "tuple") +public class Tuple +{ + @XmlElement(name = "atom") + @JsonProperty("atoms") + public List atoms; +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Type.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Type.java new file mode 100644 index 000000000..c72d86d34 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Type.java @@ -0,0 +1,21 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "type") +public class Type +{ + @XmlAttribute(name = "ID") + @JsonProperty("id") + public int id; + + public Type() {} + + public Type(int id) + { + this.id = id; + } +} diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Types.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Types.java new file mode 100644 index 000000000..cc6088ef1 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/instances/Types.java @@ -0,0 +1,15 @@ +package edu.mit.csail.sdg.alloy4whole.instances; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +@XmlRootElement(name = "types") +public class Types +{ + @XmlElement(name = "type") + @JsonProperty("types") + public List types; +} diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java index 75365e8fc..c73df3311 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java @@ -712,28 +712,57 @@ public Object renderValueShort(Integer value) { /** * The fourth file in Alloy Analyzer's "open recent" list. */ - public static final StringPref Model3 = new StringPref("Model3"); + public static final StringPref Model3 = new StringPref("Model3"); /** Automatically infer partial instance from model */ - public static final BooleanPref InferPartialInstance = new BooleanPref("InferPartialInstance", "Infer partial instance"); + public static final BooleanPref InferPartialInstance = new BooleanPref("InferPartialInstance", "Infer partial instance"); - public static final DelayedChoicePref Solver = new DelayedChoicePref("SatSolver2", "Solver", SatSolver.values(), SatSolver.SAT4J) { + public static final String KODKOD = "Kodkod"; - @Override - protected String serialize(SatSolver value) { - return value.id(); - } - }; + public static final String CVC4 = "CVC4"; - public static final ChoicePref VerbosityPref = new ChoicePref("Verbosity", Verbosity.values(), Verbosity.DEFAULT) { + public static final StringChoicePref RelationalSolver = new StringChoicePref("Relational Solver", Arrays.asList(KODKOD, CVC4), KODKOD); - @Override - protected String serialize(Verbosity value) { - return value.id; - } - }; + public static final IntChoicePref Cvc4Timeout = new IntChoicePref("Cvc4Timeout", "CVC4 timeout", Arrays.asList(5000, 30000, 60000, 120000, 300000, 600000, 0), 30000) { + + @Override + public Object renderValueShort(Integer value) { + if (value != 0) { + double valueInMinutes = value / 1000.0; + return ((int) valueInMinutes) + " seconds"; + } else { + return "Infinity"; + } + } + }; + + public static final BooleanPref Cvc4IncludeCommandScope = new BooleanPref("Cvc4IncludeCommandScope", "CVC4 include scope", false); + + public static final BooleanPref Cvc4ProduceUnsatCores = new BooleanPref("Cvc4ProduceUnsatCores", "CVC4 produce unsat cores", false); + + public static final BooleanPref Cvc4FiniteModelFind = new BooleanPref("Cvc4FiniteModelFind", "Finite model find", true); + + public static final BooleanPref Cvc4IntegerSingletonsOnly = new BooleanPref("Cvc4IntegerSingletonsOnly", "CVC4 integer singletons only", false); + + + public static final DelayedChoicePref Solver = new DelayedChoicePref("SatSolver2", "Solver", SatSolver.values(), SatSolver.SAT4J) { + + @Override + protected String serialize(SatSolver value) { + return value.id(); + } + }; + + public static final ChoicePref VerbosityPref = new ChoicePref("Verbosity", Verbosity.values(), Verbosity.DEFAULT) { + + @Override + protected String serialize(Verbosity value) { + return value.id; + } + }; public enum Verbosity { + /** Level 0. */ DEFAULT("0", "low"), /** Level 1. */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java index 7fff7c4e0..9004bff9e 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java @@ -144,17 +144,21 @@ public final class CompModule extends Browsable implements Module { */ private final Set exactSigs; + public Set getExactSigs() { + return exactSigs; + } + /** * This stores a set of global values; given a unresolved name, we query this * map first before all else. */ - private final Map globals; + private final Map globals; /** This stores the meta signature "sig$" */ - private final PrimSig metaSig; + private final PrimSig metaSig; /** This stores the meta signature "field$" */ - private final PrimSig metaField; + private final PrimSig metaField; // ============================================================================================================================// @@ -162,15 +166,15 @@ public final class CompModule extends Browsable implements Module { * This field is used during a depth-first search of the dag-of-module(s) to * mark which modules have been visited. */ - private Object visitedBy = null; + private Object visitedBy = null; /** The world that this CompModule belongs to. */ - private final CompModule world; + private final CompModule world; /** * The simplest path pointing to this Module ("" if this is the main module) */ - public final String path; + public final String path; /** * Return the simplest path pointing to this Module ("" if this is the main diff --git a/org.alloytools.alloy.dist/binaries/cvc4_linux b/org.alloytools.alloy.dist/binaries/cvc4_linux new file mode 100755 index 000000000..b57a9e059 Binary files /dev/null and b/org.alloytools.alloy.dist/binaries/cvc4_linux differ diff --git a/org.alloytools.alloy.dist/binaries/cvc4_mac b/org.alloytools.alloy.dist/binaries/cvc4_mac new file mode 100755 index 000000000..d0d060d3b Binary files /dev/null and b/org.alloytools.alloy.dist/binaries/cvc4_mac differ diff --git a/org.alloytools.alloy.dist/binaries/cvc4_win64.exe b/org.alloytools.alloy.dist/binaries/cvc4_win64.exe new file mode 100755 index 000000000..36ebcadcd Binary files /dev/null and b/org.alloytools.alloy.dist/binaries/cvc4_win64.exe differ diff --git a/org.alloytools.alloy.dist/bnd.bnd b/org.alloytools.alloy.dist/bnd.bnd index 35289c047..08f05d81d 100644 --- a/org.alloytools.alloy.dist/bnd.bnd +++ b/org.alloytools.alloy.dist/bnd.bnd @@ -2,7 +2,7 @@ Main-Class: edu.mit.csail.sdg.alloy4whole.Alloy -buildpath: \ org.alloytools.alloy.application,\ - org.alloytools.alloy.core,\ + org.alloytools.alloy.core,\ org.alloytools.alloy.extra,\ org.alloytools.pardinus;version=latest,\ org.alloytools.kodkod.nativesat.x86-windows;version=latest,\ @@ -11,6 +11,11 @@ Main-Class: edu.mit.csail.sdg.alloy4whole.Alloy org.alloytools.kodkod.nativesat.x86-linux;version=latest,\ org.alloytools.kodkod.nativesat.x86-mac;version=latest,\ slf4j.api,\ + org.antlr.antlr4-runtime,\ + com.fasterxml.jackson.core.jackson-annotations,\ + com.fasterxml.jackson.core.jackson-databind,\ + com.fasterxml.jackson.core.jackson-core,\ + SMT-Extension;version=latest -sources: false @@ -27,4 +32,10 @@ Main-Class: edu.mit.csail.sdg.alloy4whole.Alloy @${repo;org.sat4j.core}, \ @${repo;org.sat4j.maxsat}, \ @${repo;org.sat4j.pb}, \ + @${repo;org.antlr.antlr4-runtime}, \ + @${repo;com.fasterxml.jackson.core.jackson-annotations},\ + @${repo;com.fasterxml.jackson.core.jackson-databind},\ + @${repo;com.fasterxml.jackson.core.jackson-core}, \ + @${repo;SMT-Extension}, \ LICENSES +