/*******************************************************************************
* Copyright (c) 2010-2014, Marton Bur, Akos Horvath, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-v20.html.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package tools.refinery.viatra.runtime.localsearch.planner;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import tools.refinery.viatra.runtime.localsearch.matcher.integration.LocalSearchHints;
import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation;
import tools.refinery.viatra.runtime.localsearch.plan.SearchPlanForBody;
import tools.refinery.viatra.runtime.localsearch.planner.compiler.IOperationCompiler;
import tools.refinery.viatra.runtime.matchers.backend.ResultProviderRequestor;
import tools.refinery.viatra.runtime.matchers.context.IQueryBackendContext;
import tools.refinery.viatra.runtime.matchers.context.IQueryRuntimeContext;
import tools.refinery.viatra.runtime.matchers.planning.SubPlan;
import tools.refinery.viatra.runtime.matchers.psystem.PBody;
import tools.refinery.viatra.runtime.matchers.psystem.PVariable;
import tools.refinery.viatra.runtime.matchers.psystem.basicdeferred.ExportedParameter;
import tools.refinery.viatra.runtime.matchers.psystem.queries.PParameter;
import tools.refinery.viatra.runtime.matchers.psystem.queries.PQuery;
import tools.refinery.viatra.runtime.matchers.psystem.rewriters.PBodyNormalizer;
import tools.refinery.viatra.runtime.matchers.psystem.rewriters.PDisjunctionRewriter;
import tools.refinery.viatra.runtime.matchers.psystem.rewriters.PDisjunctionRewriterCacher;
import tools.refinery.viatra.runtime.matchers.psystem.rewriters.PQueryFlattener;
/**
*
* @author Marton Bur
* @noreference This class is not intended to be referenced by clients.
*/
public class LocalSearchPlanner implements ILocalSearchPlanner {
// Externally set tools for planning
private final PDisjunctionRewriter preprocessor;
private final LocalSearchRuntimeBasedStrategy plannerStrategy;
private final IQueryRuntimeContext runtimeContext;
private final LocalSearchHints configuration;
private final IOperationCompiler operationCompiler;
private final IQueryBackendContext context;
private final ResultProviderRequestor resultRequestor;
/**
* @param resultRequestor
* @since 1.7
*/
public LocalSearchPlanner(IQueryBackendContext backendContext, IOperationCompiler compiler, Logger logger,
final LocalSearchHints configuration, ResultProviderRequestor resultRequestor)
{
this.runtimeContext = backendContext.getRuntimeContext();
this.configuration = configuration;
this.operationCompiler = compiler;
this.resultRequestor = resultRequestor;
PQueryFlattener flattener = new PQueryFlattener(configuration.getFlattenCallPredicate());
/*
* TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=439358: The normalizer is initialized with the false
* parameter to turn off unary constraint elimination to work around an issue related to plan ordering: the
* current implementation of the feature target checking operations expect that the source types were checked
* before. However, this causes duplicate constraint checks in the search plan that might affect performance
* negatively.
*/
PBodyNormalizer normalizer = new PBodyNormalizer(runtimeContext.getMetaContext()) {
@Override
protected boolean shouldCalculateImpliedTypes(PQuery query) {
return false;
}
};
preprocessor = new PDisjunctionRewriterCacher(flattener, normalizer);
plannerStrategy = new LocalSearchRuntimeBasedStrategy();
context = backendContext;
}
/**
* Creates executable plans for the provided query. It is required to call one of the
* initializePlanner()
methods before calling this method.
*
* @param querySpec
* @param boundParameters
* a set of bound parameters
* @return a mapping between ISearchOperation list and a mapping, that holds a PVariable-Integer mapping for the
* list of ISearchOperations
*/
@Override
public Collection plan(PQuery querySpec, Set boundParameters) {
// 1. Preparation
preprocessor.setTraceCollector(configuration.getTraceCollector());
Set normalizedBodies = preprocessor.rewrite(querySpec.getDisjunctBodies()).getBodies();
List plansForBodies = new ArrayList<>(normalizedBodies.size());
for (PBody normalizedBody : normalizedBodies) {
// 2. Plan creation
// Context has matchers for the referred Queries (IQuerySpecifications)
Set boundVariables = calculatePatternAdornmentForPlanner(boundParameters, normalizedBody);
PlanState searchPlanInternal = plannerStrategy.plan(normalizedBody, boundVariables, context, resultRequestor, configuration);
SubPlan plan = plannerStrategy.convertPlan(boundVariables, searchPlanInternal);
// 3. PConstraint -> POperation compilation step
// * Pay extra caution to extend operations, when more than one variables are unbound
List compiledOperations = operationCompiler.compile(plan, boundParameters);
// Store the variable mappings for the plans for debug purposes (traceability information)
SearchPlanForBody compiledPlan = new SearchPlanForBody(normalizedBody,
operationCompiler.getVariableMappings(), plan, compiledOperations,
operationCompiler.getDependencies(),
searchPlanInternal, searchPlanInternal.getCost());
plansForBodies.add(compiledPlan);
}
return plansForBodies;
}
private Set calculatePatternAdornmentForPlanner(Set boundParameters, PBody normalizedBody) {
Map parameterMapping = new HashMap<>();
for (ExportedParameter constraint : normalizedBody.getSymbolicParameters()) {
parameterMapping.put(constraint.getPatternParameter(), constraint.getParameterVariable());
}
Set boundVariables = new HashSet<>();
for (PParameter parameter : boundParameters) {
PVariable mappedParameter = parameterMapping.get(parameter);
boundVariables.add(mappedParameter);
}
return boundVariables;
}
}