/** * 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.graph_mavo.operator; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jdt.annotation.NonNull; import edu.toronto.cs.se.mmint.MMINT; import edu.toronto.cs.se.mmint.MMINTException; import edu.toronto.cs.se.mmint.MIDTypeRegistry; import edu.toronto.cs.se.mavo.MAVOElement; import edu.toronto.cs.se.mavo.MAVOPackage; 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.operator.impl.RandomOperatorImpl; import edu.toronto.cs.se.mmint.mid.utils.FileUtils; import edu.toronto.cs.se.mmint.mid.utils.MIDOperatorIOUtils; import edu.toronto.cs.se.modelepedia.graph_mavo.Edge; import edu.toronto.cs.se.modelepedia.graph_mavo.Graph; import edu.toronto.cs.se.modelepedia.graph_mavo.Graph_MAVOFactory; import edu.toronto.cs.se.modelepedia.graph_mavo.Graph_MAVOPackage; import edu.toronto.cs.se.modelepedia.graph_mavo.Node; public class GenerateRandomGraphMAVO extends RandomOperatorImpl { // input-output private final static @NonNull String OUT_MODEL = "random"; /** Min number of model objects in the random graph. */ private static final String PROPERTY_IN_MINMODELOBJS = "minModelObjs"; /** Max number of model objects in the random graph. */ private static final String PROPERTY_IN_MAXMODELOBJS = "maxModelObjs"; private static final String PROPERTY_IN_EDGESTONODESRATIO = "edges.toNodesRatio"; /** % of MAVO model objects in the random model. */ private static final String PROPERTY_IN_PERCMAVO = "percMavo"; /** % of may model objects among the MAVO ones. */ private static final String PROPERTY_IN_PERCMAY = "percMay"; /** % of set model objects among the MAVO ones. */ private static final String PROPERTY_IN_PERCSET = "percSet"; /** % of var model objects among the MAVO ones. */ private static final String PROPERTY_IN_PERCVAR = "percVar"; private static final String NODE_NAME_PREFIX = "n"; private static final String EDGE_NAME_PREFIX = "e"; private static final String RANDOM_MODEL_NAME = "random"; private int minModelObjs; private int maxModelObjs; private double edgesToNodesRatio; private double percMavo; private double percMay; private double percSet; private double percVar; private Map<String, MAVOElement> mavoModelObjs; @Override public void readInputProperties(Properties inputProperties) throws MMINTException { super.readInputProperties(inputProperties); maxModelObjs = MIDOperatorIOUtils.getIntProperty(inputProperties, PROPERTY_IN_MAXMODELOBJS); minModelObjs = MIDOperatorIOUtils.getOptionalIntProperty(inputProperties, PROPERTY_IN_MINMODELOBJS, maxModelObjs); if (minModelObjs > maxModelObjs) { throw new MMINTException("minModelElems (" + minModelObjs + ") > maxModelElems (" + maxModelObjs + ")"); } edgesToNodesRatio = MIDOperatorIOUtils.getDoubleProperty(inputProperties, PROPERTY_IN_EDGESTONODESRATIO); percMavo = MIDOperatorIOUtils.getDoubleProperty(inputProperties, PROPERTY_IN_PERCMAVO); percMay = MIDOperatorIOUtils.getDoubleProperty(inputProperties, PROPERTY_IN_PERCMAY); percSet = MIDOperatorIOUtils.getDoubleProperty(inputProperties, PROPERTY_IN_PERCSET); percVar = MIDOperatorIOUtils.getDoubleProperty(inputProperties, PROPERTY_IN_PERCVAR); } private void init() { // state mavoModelObjs = new HashMap<>(); } private int addMayEdges(Node mayNode, List<MAVOElement> mavoAnnotatableModelObjs) { int i = 0; for (Edge edgeAsSrc : mayNode.getEdgesAsSource()) { if (!edgeAsSrc.isMay()) { mavoAnnotatableModelObjs.remove(edgeAsSrc); edgeAsSrc.setMay(true); mavoModelObjs.put(edgeAsSrc.getFormulaVariable(), edgeAsSrc); i++; } } for (Edge edgeAsTgt : mayNode.getEdgesAsTarget()) { if (!edgeAsTgt.isMay()) { mavoAnnotatableModelObjs.remove(edgeAsTgt); edgeAsTgt.setMay(true); mavoModelObjs.put(edgeAsTgt.getFormulaVariable(), edgeAsTgt); i++; } } return i; } private void addMAVOElements(List<MAVOElement> mavoableModelObjs, EStructuralFeature mavoFeature, double mavoPerc) { List<MAVOElement> mavoAnnotatableModelObjs = new ArrayList<>(mavoableModelObjs); MAVOElement mavoModelObj; int numMavo = (int) Math.round(mavoPerc * mavoableModelObjs.size()); for (int i = 0; i < numMavo; i++) { mavoModelObj = mavoAnnotatableModelObjs.remove(state.nextInt(mavoAnnotatableModelObjs.size())); mavoModelObj.eSet(mavoFeature, true); if (mavoFeature == MAVOPackage.eINSTANCE.getMAVOElement_May() && mavoModelObj instanceof Node) { i += addMayEdges((Node) mavoModelObj, mavoAnnotatableModelObjs); } mavoModelObjs.put(mavoModelObj.getFormulaVariable(), mavoModelObj); } } private Graph generateRandomGraph() throws Exception { int totModelObjs = state.nextInt(maxModelObjs - minModelObjs + 1) + minModelObjs; int[] numModelObjs = new int[2]; numModelObjs[0] = Math.max( 1, (int) Math.round(totModelObjs / (1 + edgesToNodesRatio)) ); numModelObjs[1] = totModelObjs - numModelObjs[0]; // generate nodes and edges List<MAVOElement> randomModelObjs = new ArrayList<>(); Graph randomGraph = Graph_MAVOFactory.eINSTANCE.createGraph(); EList<Node> randomGraphNodes = randomGraph.getNodes(); String name; Node node; for (int i = 0; i < numModelObjs[0]; i++) { node = Graph_MAVOFactory.eINSTANCE.createNode(); name = NODE_NAME_PREFIX + (i+1); node.setName(name); node.setFormulaVariable(name); randomGraphNodes.add(node); randomModelObjs.add(node); } EList<Edge> randomGraphEdges = randomGraph.getEdges(); Edge edge; for (int i = 0; i < numModelObjs[1]; i++) { edge = Graph_MAVOFactory.eINSTANCE.createEdge(); name = EDGE_NAME_PREFIX + (i+1); edge.setName(name); edge.setFormulaVariable(name); edge.setSource(randomGraphNodes.get(state.nextInt(numModelObjs[0]))); edge.setTarget(randomGraphNodes.get(state.nextInt(numModelObjs[0]))); randomGraphEdges.add(edge); randomModelObjs.add(edge); } // add mavo annotations List<MAVOElement> mavoableModelObjs = new ArrayList<>(); int numMavo = (int) Math.round(percMavo * randomModelObjs.size()); for (int i = 0; i < numMavo; i++) { mavoableModelObjs.add(randomModelObjs.remove(state.nextInt(randomModelObjs.size()))); } addMAVOElements(mavoableModelObjs, MAVOPackage.eINSTANCE.getMAVOElement_May(), percMay); addMAVOElements(mavoableModelObjs, MAVOPackage.eINSTANCE.getMAVOElement_Set(), percSet); addMAVOElements(mavoableModelObjs, MAVOPackage.eINSTANCE.getMAVOElement_Var(), percVar); return randomGraph; } public Map<String, MAVOElement> getMAVOModelObjects() { return mavoModelObjs; } @Override public Map<String, Model> run( Map<String, Model> inputsByName, Map<String, GenericElement> genericsByName, Map<String, MID> outputMIDsByName) throws Exception { // input MID instanceMID = outputMIDsByName.get(OUT_MODEL); this.init(); // create random graph Graph randomGraph = generateRandomGraph(); String lastSegmentUri = RANDOM_MODEL_NAME + (new Date()).getTime() + MMINT.MODEL_FILEEXTENSION_SEPARATOR + Graph_MAVOPackage.eNAME; String subdir = getInputSubdir(); if (subdir != null) { lastSegmentUri = subdir + MMINT.URI_SEPARATOR + lastSegmentUri; } // output String randomGraphModelUri = FileUtils.replaceLastSegmentInUri(MMINT.getActiveInstanceMIDFile().getFullPath().toString(), lastSegmentUri); FileUtils.writeModelFile(randomGraph, randomGraphModelUri, true); Model graphModelType = MIDTypeRegistry.getType(Graph_MAVOPackage.eINSTANCE.getNsURI()); Model randomGraphModel = graphModelType.createInstanceAndEditor(randomGraphModelUri, instanceMID); Map<String, Model> outputsByName = new HashMap<>(); outputsByName.put(OUT_MODEL, randomGraphModel); return outputsByName; } }