blob: 8e0fe40ee5c99cdfd2bd3e037845657b818376e4 [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.quasitree;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Buildable;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.IReteLayoutStrategy;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.RetePatternBuildException;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.Stub;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.helpers.BuildHelper;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.helpers.LayoutHelper;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.DeferredPConstraint;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.EnumerablePConstraint;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PSystem;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.matcher.IPatternMatcherContext;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.util.Options;
/**
* @author Bergmann Gábor
*
*/
public class QuasiTreeLayout<PatternDescription, StubHandle, Collector>
implements
IReteLayoutStrategy<PatternDescription, StubHandle, Collector> {
/* (non-Javadoc)
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.IReteLayoutStrategy#layout(org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction.psystem.PSystem)
*/
@Override
public Stub<StubHandle> layout(PSystem<PatternDescription, StubHandle, Collector> pSystem) throws RetePatternBuildException {
return new Scaffold(pSystem).run();
}
public class Scaffold {
PSystem<PatternDescription, StubHandle, Collector> pSystem;
PatternDescription pattern;
IPatternMatcherContext<PatternDescription> context;
Buildable<PatternDescription, StubHandle, Collector> buildable;
Set<DeferredPConstraint> deferredConstraints = null;
Set<Stub<StubHandle>> forefront = new LinkedHashSet<Stub<StubHandle>>();
Scaffold(PSystem<PatternDescription, StubHandle, Collector> pSystem) {
this.pSystem = pSystem;
pattern = pSystem.getPattern();
context = pSystem.getContext();
buildable = pSystem.getBuildable();
}
/**
* @return
*/
public Stub<StubHandle> run() throws RetePatternBuildException {
try {
context.logDebug(getClass().getSimpleName() + ": patternbody build started");
// UNIFICATION AND WEAK INEQUALITY ELMINATION
LayoutHelper.unifyVariablesAlongEqualities(pSystem);
LayoutHelper.eliminateWeakInequalities(pSystem);
// UNARY ELIMINATION WITH TYPE INFERENCE
if (Options.calcImpliedTypes) {
LayoutHelper.eliminateInferrableUnaryTypes(pSystem, context);
}
// PREVENTIVE CHECKS
LayoutHelper.checkSanity(pSystem);
// PROCESS CONSTRAINTS
deferredConstraints = pSystem.getConstraintsOfType(DeferredPConstraint.class);
Set<EnumerablePConstraint> enumerables =
pSystem.getConstraintsOfType(EnumerablePConstraint.class);
for (EnumerablePConstraint<PatternDescription, StubHandle> enumerable : enumerables) {
Stub<StubHandle> stub = enumerable.getStub();
admitStub(stub);
}
if (enumerables.isEmpty()) { // EXTREME CASE
Stub<StubHandle> stub = buildable.buildStartStub(new Object[]{}, new Object[]{});
admitStub(stub);
}
// JOIN FOREFRONT STUBS WHILE POSSIBLE
while (forefront.size() > 1) {
// TODO QUASI-TREE TRIVIAL JOINS?
List<JoinCandidate<StubHandle>> candidates = generateJoinCandidates();
JoinOrderingHeuristics<PatternDescription, StubHandle, Collector> ordering =
new JoinOrderingHeuristics<PatternDescription, StubHandle, Collector>();
JoinCandidate<StubHandle> selectedJoin = Collections.min(candidates, ordering);
doJoin(selectedJoin.getPrimary(), selectedJoin.getSecondary());
}
// FINAL CHECK, whether all exported variables are present
assert(forefront.size() == 1);
Stub<StubHandle> finalStub = forefront.iterator().next();
LayoutHelper.finalCheck(pSystem, finalStub);
context.logDebug(getClass().getSimpleName() + ": patternbody build concluded");
return finalStub;
} catch (RetePatternBuildException ex) {
ex.setPatternDescription(pattern);
throw ex;
}
}
public List<JoinCandidate<StubHandle>> generateJoinCandidates() {
List<JoinCandidate<StubHandle>> candidates = new ArrayList<JoinCandidate<StubHandle>>();
int bIndex = 0;
for (Stub<StubHandle> b : forefront) {
int aIndex = 0;
for (Stub<StubHandle> a : forefront) {
if (aIndex++ >= bIndex) break;
candidates.add(new JoinCandidate<StubHandle>(a, b));
}
bIndex++;
}
return candidates;
}
private void admitStub(Stub<StubHandle> stub) throws RetePatternBuildException {
for (DeferredPConstraint<PatternDescription, StubHandle> deferred : deferredConstraints) {
if (!stub.getAllEnforcedConstraints().contains(deferred)) {
if (deferred.isReadyAt(stub)) {
admitStub(deferred.checkOn(stub));
return;
}
}
}
forefront.add(stub);
}
private void doJoin(Stub<StubHandle> primaryStub, Stub<StubHandle> secondaryStub) throws RetePatternBuildException {
Stub<StubHandle> joinedStub = BuildHelper.naturalJoin(buildable, primaryStub, secondaryStub);
forefront.remove(primaryStub);
forefront.remove(secondaryStub);
admitStub(joinedStub);
}
}
}