blob: dc24ad758530fd1ab9a156372e1aa54d3d80524c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2010 Gabor Bergmann and Daniel Varro
* 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:
* Gabor Bergmann - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.helpers;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Buildable;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Stub;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PVariable;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.TupleMask;
/**
* @author Bergmann Gábor
*
*/
public class BuildHelper {
/**
* If two or more variables are the same in the variablesTuple of the stub, then a checker node is built to enforce their equality.
* @return the derived stub that contains the additional checkers, or the original if no action was neccessary.
*/
public static <StubHandle> Stub<StubHandle> enforceVariableCoincidences(Buildable<?, StubHandle, ?> buildable, Stub<StubHandle> stub) {
Map<Object, List<Integer>> indexWithMupliplicity =
stub.getVariablesTuple().invertIndexWithMupliplicity();
for (Map.Entry<Object, List<Integer>> pVariableIndices : indexWithMupliplicity.entrySet()) {
List<Integer> indices = pVariableIndices.getValue();
if (indices.size() > 1) {
int[] indexArray = new int[indices.size()];
int m = 0;
for (Integer index : indices)
indexArray[m++] = index;
stub = buildable.buildEqualityChecker(stub, indexArray);
// TODO also trim here?
}
}
return stub;
}
/**
* Trims the results in the stub into a collector, by selecting exported variables in a particular order.
* @return the derived stub that contains the additional checkers, or the original if no action was neccessary.
*/
public static <StubHandle, Collector> void projectIntoCollector(
Buildable<?, StubHandle, Collector> buildable,
Stub<StubHandle> stub, Collector collector,
PVariable[] selectedVariables)
{
int paramNum = selectedVariables.length;
int[] tI = new int[paramNum];
for (int i = 0; i < paramNum; i++) {
tI[i] = stub.getVariablesIndex().get(selectedVariables[i]);
}
int tiW = stub.getVariablesTuple().getSize();
TupleMask trim = new TupleMask(tI, tiW);
Stub<StubHandle> trimmer = buildable.buildTrimmer(stub, trim);
buildable.buildConnection(trimmer, collector);
}
/**
* Calculated index mappings for a join, based on the common variables of the two parent stubs.
* @author Bergmann Gábor
*
*/
public static class JoinHelper<StubHandle> {
private TupleMask primaryMask;
private TupleMask secondaryMask;
private TupleMask complementerMask;
/**
* @pre enforceVariableCoincidences() has been called on both sides.
* @param primaryStub
* @param secondaryStub
*/
public JoinHelper(Stub<StubHandle> primaryStub, Stub<StubHandle> secondaryStub) {
super();
Set<PVariable> primaryVariables =
primaryStub.getVariablesTuple().getDistinctElements();
Set<PVariable> secondaryVariables =
secondaryStub.getVariablesTuple().getDistinctElements();
int oldNodes = 0;
Set<Integer> introducingSecondaryIndices = new TreeSet<Integer>();
for (PVariable var : secondaryVariables) {
if (primaryVariables.contains(var)) oldNodes++;
else introducingSecondaryIndices.add(secondaryStub.getVariablesIndex().get(var));
}
int[] primaryIndices = new int[oldNodes];
final int[] secondaryIndices = new int[oldNodes];
int k = 0;
for (PVariable var : secondaryVariables) {
if (primaryVariables.contains(var)) {
primaryIndices[k] = primaryStub.getVariablesIndex().get(var);
secondaryIndices[k] = secondaryStub.getVariablesIndex().get(var);
k++;
}
}
int[] complementerIndices = new int[introducingSecondaryIndices.size()];
int l = 0;
for (Integer integer : introducingSecondaryIndices) {
complementerIndices[l++] = integer;
}
primaryMask = new TupleMask(
primaryIndices,
primaryStub.getVariablesTuple().getSize());
secondaryMask = new TupleMask(
secondaryIndices,
secondaryStub.getVariablesTuple().getSize());
complementerMask = new TupleMask(
complementerIndices,
secondaryStub.getVariablesTuple().getSize());
}
/**
* @return the primaryMask
*/
public TupleMask getPrimaryMask() {
return primaryMask;
}
/**
* @return the secondaryMask
*/
public TupleMask getSecondaryMask() {
return secondaryMask;
}
/**
* @return the complementerMask
*/
public TupleMask getComplementerMask() {
return complementerMask;
}
}
public static <StubHandle> Stub<StubHandle> naturalJoin(
Buildable<?, StubHandle, ?> buildable,
Stub<StubHandle> primaryStub, Stub<StubHandle> secondaryStub)
{
JoinHelper<StubHandle> joinHelper = new JoinHelper<StubHandle>(primaryStub, secondaryStub);
return buildable.buildBetaNode(
primaryStub, secondaryStub,
joinHelper.getPrimaryMask(),
joinHelper.getSecondaryMask(),
joinHelper.getComplementerMask(),
false);
}
}