/** * Copyright (c) 2010, 2013 Darmstadt University of Technology. * 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: * Marcel Bruch - initial API and implementation. */ package org.eclipse.recommenders.overrides; import static java.lang.String.format; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.recommenders.jayes.BayesNet; import org.eclipse.recommenders.jayes.BayesNode; import org.eclipse.recommenders.jayes.inference.jtree.JunctionTreeAlgorithm; import org.eclipse.recommenders.utils.Recommendation; import org.eclipse.recommenders.utils.gson.GsonUtil; import org.eclipse.recommenders.utils.names.IMethodName; import org.eclipse.recommenders.utils.names.ITypeName; import org.eclipse.recommenders.utils.names.VmMethodName; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.reflect.TypeToken; public class JayesOverrideModel implements IOverrideModel { public static IOverrideModel load(InputStream is, ITypeName type) throws IOException { final Type listType = new TypeToken<List<OverrideObservation>>() { }.getType(); final List<OverrideObservation> observations = GsonUtil.deserialize(is, listType); if (observations.size() == 0) { // XXX sanitize bad models! // we still need to ensure minimum quality for models . observations.add(new OverrideObservation()); } final JayesOverrideModelBuilder b = new JayesOverrideModelBuilder(type, observations); final IOverrideModel network = b.build(); return network; } private JunctionTreeAlgorithm junctionTreeAlgorithm; private ITypeName typeName; private BayesNode patternNode; private Map<IMethodName, BayesNode> methodNodes; protected JayesOverrideModel(final ITypeName typeName, final BayesNet network, final BayesNode patternNode, final List<BayesNode> methodNodes) { this.typeName = typeName; this.patternNode = patternNode; junctionTreeAlgorithm = new JunctionTreeAlgorithm(); junctionTreeAlgorithm.setNetwork(network); createMethodNameMapping(methodNodes); } private void createMethodNameMapping(List<BayesNode> methods) { methodNodes = Maps.newHashMap(); for (final BayesNode methodNode : methods) { methodNodes.put(VmMethodName.get(methodNode.getName()), methodNode); } } @Override public void reset() { junctionTreeAlgorithm.setEvidence(new HashMap<BayesNode, String>()); } @Override public ITypeName getType() { return typeName; } @Override public ImmutableSet<String> getKnownPatterns() { return ImmutableSet.copyOf(patternNode.getOutcomes()); } @Override public ImmutableSet<IMethodName> getKnownMethods() { return ImmutableSet.copyOf(methodNodes.keySet()); } @Override public void setObservedMethod(final IMethodName methodName) { final BayesNode methodNode = methodNodes.get(methodName); if (methodNode != null) { junctionTreeAlgorithm.addEvidence(methodNode, "true"); } } @Override public List<Recommendation<IMethodName>> recommendOverrides() { final List<Recommendation<IMethodName>> recommendations = Lists.newLinkedList(); for (final BayesNode node : methodNodes.values()) { if (junctionTreeAlgorithm.getEvidence().containsKey(node)) { continue; } final double probability = junctionTreeAlgorithm.getBeliefs(node)[0]; final IMethodName method = VmMethodName.get(node.getName()); recommendations.add(Recommendation.newRecommendation(method, probability)); } return recommendations; } @Override public String toString() { return format("Model for '%s'", typeName); } }