/**
* Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis,
* Rick Salay.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alessio Di Sandro - Implementation.
*/
package edu.toronto.cs.se.modelepedia.istar_mavo.operator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import edu.toronto.cs.se.mavo.MAVOElement;
import edu.toronto.cs.se.mavo.MAVOPackage;
import edu.toronto.cs.se.mmint.MMINTException;
import edu.toronto.cs.se.mmint.mavo.library.MAVOUtils;
import edu.toronto.cs.se.mmint.mid.GenericElement;
import edu.toronto.cs.se.mmint.mid.MID;
import edu.toronto.cs.se.mmint.mid.Model;
import edu.toronto.cs.se.mmint.mid.utils.FileUtils;
import edu.toronto.cs.se.mmint.mid.utils.MIDOperatorIOUtils;
import edu.toronto.cs.se.modelepedia.z3.Z3IncrementalSolver;
import edu.toronto.cs.se.modelepedia.z3.Z3IncrementalSolver.Z3IncrementalBehavior;
import edu.toronto.cs.se.modelepedia.z3.Z3Model;
import edu.toronto.cs.se.modelepedia.z3.Z3Model.Z3Result;
import edu.toronto.cs.se.modelepedia.z3.mavo.Z3MAVOUtils;
import edu.toronto.cs.se.modelepedia.z3.Z3Utils;
public class FASE14 extends RE13 {
// input-output properties
protected static final String PROPERTY_OUT_TIMERNF = "timeRNF";
// constants
private static final String RNF_OUTPUT_SUFFIX = "_rnf";
// state
protected Map<String, MAVOElement> mavoModelObjs;
private String smtEncodingRNF;
// output
protected long timeRNF;
@Override
protected void init() {
super.init();
// state
mavoModelObjs = new HashMap<>();
smtEncodingRNF = "";
// output
timeRNF = -1;
}
@Override
protected void writeProperties(Properties properties) {
super.writeProperties(properties);
properties.setProperty(PROPERTY_OUT_TIMERNF, String.valueOf(timeRNF));
}
private Z3Model checkMAVOAnnotation(MAVOElement mavoModelObj, EStructuralFeature mavoAnnotation, String smtMavoConstraint, Z3IncrementalSolver z3IncSolver, List<MAVOElement> mavoModelObjsToRemove) {
Z3Model z3ModelResult = z3IncSolver.checkSatAndGetModel(Z3Utils.assertion(Z3Utils.not(smtMavoConstraint)), Z3IncrementalBehavior.POP);
if (z3ModelResult.getZ3Result() == Z3Result.SAT) {
//TODO MMINT[RNF] optimize search for other annotations in output model using the map mavoModelObjs
return null;
}
else {
if (mavoAnnotation == MAVOPackage.eINSTANCE.getMAVOElement_May() && smtMavoConstraint.startsWith(Z3Utils.SMTLIB_NOT)) { // M model object deletion
EcoreUtil.delete(mavoModelObj, true);
}
else { // M-S-V removal
mavoModelObj.eSet(mavoAnnotation, false);
}
mavoModelObjsToRemove.add(mavoModelObj);
String smtMavoAssertion = Z3Utils.assertion(smtMavoConstraint);
smtEncodingRNF += smtMavoAssertion + "\n";
return z3IncSolver.checkSatAndGetModel(smtMavoAssertion, Z3IncrementalBehavior.NORMAL);
}
}
protected void doRNF(Z3IncrementalSolver z3IncSolver, Z3Model z3Model) {
long startTime = System.nanoTime();
Z3Model z3TempModel;
List<MAVOElement> mavoModelObjsToRemove = new ArrayList<MAVOElement>();
for (MAVOElement mavoModelObj : mavoModelObjs.values()) {
try {
if (mavoModelObj.isMay()) {
String smtMConstraint = Z3MAVOUtils.getSMTLIBMayModelObjectConstraint(mavoModelObj, false, false);
z3TempModel = checkMAVOAnnotation(mavoModelObj, MAVOPackage.eINSTANCE.getMAVOElement_May(), smtMConstraint, z3IncSolver, mavoModelObjsToRemove);
if (z3TempModel != null) {
z3Model = z3TempModel;
}
z3TempModel = checkMAVOAnnotation(mavoModelObj, MAVOPackage.eINSTANCE.getMAVOElement_May(), Z3Utils.not(smtMConstraint), z3IncSolver, mavoModelObjsToRemove);
if (z3TempModel != null) {
z3Model = z3TempModel;
}
}
if (mavoModelObj.isSet()) {
String smtSConstraint = Z3MAVOUtils.getSMTLIBSetModelObjectConstraint(mavoModelObj, false);
z3TempModel = checkMAVOAnnotation(mavoModelObj, MAVOPackage.eINSTANCE.getMAVOElement_Set(), smtSConstraint, z3IncSolver, mavoModelObjsToRemove);
if (z3TempModel != null) {
z3Model = z3TempModel;
}
}
if (mavoModelObj.isVar()) {
Set<String> mergeableFormulaVars = MAVOUtils.getMergeableFormulaVars(istar, mavoModelObj);
if (!mergeableFormulaVars.isEmpty()) {
String smtVConstraint = Z3MAVOUtils.getSMTLIBVarModelObjectConstraint(mavoModelObj, mergeableFormulaVars, false);
z3TempModel = checkMAVOAnnotation(mavoModelObj, MAVOPackage.eINSTANCE.getMAVOElement_Var(), smtVConstraint, z3IncSolver, mavoModelObjsToRemove);
if (z3TempModel != null) {
z3Model = z3TempModel;
}
}
}
}
catch (MMINTException e) {
MMINTException.print(IStatus.WARNING, "Error creating RNF constraint for model object " + mavoModelObj.getFormulaVariable() + ", skipping it", e);
continue;
}
}
mavoModelObjs.values().removeAll(mavoModelObjsToRemove);
timeRNF = System.nanoTime() - startTime;
}
protected void writeRNF(Model istarModel) {
try {
FileUtils.createTextFile(
FileUtils.replaceFileExtensionInUri(
FileUtils.addFileNameSuffixInUri(istarModel.getUri(), RNF_OUTPUT_SUFFIX),
Z3Utils.SMTLIB_FILE_EXTENSION
),
smtEncodingRNF,
true
);
}
catch (Exception e) {
MMINTException.print(IStatus.WARNING, "RNF file writing failed", e);
}
}
@Override
protected void collectAnalysisModelObjects(Model istarModel) throws MMINTException {
super.collectAnalysisModelObjects(istarModel);
mavoModelObjs = MAVOUtils.getAnnotatedMAVOModelObjects(istar);
}
@Override
public Map<String, Model> run(
Map<String, Model> inputsByName, Map<String, GenericElement> genericsByName,
Map<String, MID> outputMIDsByName) throws Exception {
// input
Model istarModel = inputsByName.get(IN_MODEL);
this.init();
// run
collectAnalysisModelObjects(istarModel);
Z3IncrementalSolver z3IncSolver = new Z3IncrementalSolver();
doAnalysis(z3IncSolver);
if (timeTargetsEnabled) {
Z3Model z3Model = doTargets(z3IncSolver);
if (targets == Z3Result.SAT) {
doRNF(z3IncSolver, z3Model);
}
}
// output
Properties outputProperties = new Properties();
writeProperties(outputProperties);
MIDOperatorIOUtils.writePropertiesFile(
outputProperties,
this,
istarModel,
null,
MIDOperatorIOUtils.OUTPUT_PROPERTIES_SUFFIX
);
if (timeRNF != -1) {
writeRNF(istarModel);
}
return new HashMap<>();
}
}