All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.clarkparsia.pellet.sparqldl.engine.CostBasedQueryPlanNew Maven / Gradle / Ivy

// Copyright (c) 2006 - 2008, Clark & Parsia, LLC. 
// This source code is available under the terms of the Affero General Public
// License v3.
//
// Please see LICENSE.txt for full license terms, including the availability of
// proprietary exceptions.
// Questions, comments, or requests for clarification: [email protected]

package com.clarkparsia.pellet.sparqldl.engine;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.mindswap.pellet.exceptions.UnsupportedQueryException;
import org.mindswap.pellet.utils.ATermUtils;

import aterm.ATermAppl;

import com.clarkparsia.pellet.sparqldl.model.Query;
import com.clarkparsia.pellet.sparqldl.model.QueryAtom;
import com.clarkparsia.pellet.sparqldl.model.QueryPredicate;
import com.clarkparsia.pellet.sparqldl.model.ResultBinding;

/**
 * 

* Title: Query Plan the Uses Full Query Reordering. *

*

* Description: *

*

* Copyright: Copyright (c) 2007 *

*

* Company: Clark & Parsia, LLC. *

* * @author Petr Kremen */ public class CostBasedQueryPlanNew extends QueryPlan { private static final Logger log = Logger.getLogger( CostBasedQueryPlanNew.class.getName() ); private List sortedAtoms; private int index; private int size; private QueryCost cost; public CostBasedQueryPlanNew(Query query) { super( query ); QuerySizeEstimator.computeSizeEstimate( query ); index = 0; size = query.getAtoms().size(); cost = new QueryCost( query.getKB() ); sortedAtoms = null; if( size == 0 ) { return; } else if( size == 1 ) { sortedAtoms = query.getAtoms(); } else { double minCost = chooseOrdering( new ArrayList( query.getAtoms() ), new ArrayList( size ), new HashSet(), false, Double.POSITIVE_INFINITY ); if( sortedAtoms == null ) { throw new UnsupportedQueryException( "No safe ordering for query: " + query ); } if( log.isLoggable( Level.FINE ) ) { log.log( Level.FINE, "WINNER : Cost=" + minCost + " ,atoms=" + sortedAtoms ); } } } /** * Recursive function that will inspect all possible orderings for a list of * query atoms and returns the cost for the best ordering (min cost) found. * Best ordering is saved in the sortedAtoms field. The ordering of atoms is * created recursively where each step adds one more atom to the current * ordering. Current ordering is discarded if it is found to be non-optimal * and we have already found an ordering which is not non-optimal. * Non-optimal heuristic currently is defined as follows: For each atom at * position i > 1 in the ordered list, there should be at least one atom at * position j < i s.t. two atoms share at least one variable. This * heuristics is defined to avoid even considering cartesian products, e.g. * ClassAtom(?x, A), ClassAtom(?y,B), PropertyValueAtom(?x, p, ?y). For some * queries, all orderings may be non-optimal, e.g. ClassAtom(?x,A), * ClassAtom(?y, B). * * @param atoms * Atoms that have not yet been added to the ordered list * @param orderedAtoms * Atoms that have been ordered so far * @param boundVars * Variables that have referenced by the atoms in the ordered * list * @param notOptimal * Current ordered list is found to be non-optimal * @param minCost * Minimum cost found so far * @return Minimum cost found from an ordering that has the given ordered * list as the prefix */ private double chooseOrdering(List atoms, List orderedAtoms, Set boundVars, boolean notOptimal, double minCost) { if( atoms.isEmpty() ) { if( notOptimal ) { if( sortedAtoms == null ) { sortedAtoms = new ArrayList( orderedAtoms ); } } else { double queryCost = cost.estimate( orderedAtoms ); log.fine( "Cost " + queryCost + " for " + orderedAtoms ); if( queryCost < minCost ) { sortedAtoms = new ArrayList( orderedAtoms ); minCost = queryCost; } } return minCost; } LOOP: for( int i = 0; i < atoms.size(); i++ ) { QueryAtom atom = atoms.get( i ); boolean newNonOptimal = notOptimal; Set newBoundVars = new HashSet( boundVars ); // TODO reorder UV atoms after all class and property variables are // bound. if( !atom.isGround() ) { int boundCount = 0; int unboundCount = 0; for( ATermAppl a : atom.getArguments() ) { if( ATermUtils.isVar( a ) ) { if( newBoundVars.add( a ) ) { unboundCount++; /* * It is not valid to have an ordering like * NotKnown(ClassAtom(?x, A)), ClassAtom(?x, B). * This is because variables in negation atom will * not be bound by the query evaluation. However, if * an atom in the query later binds the variable to * a value the result will be incorrect because * earlier evaluation of negation was not evaluated * with that binding. */ if( atom.getPredicate().equals( QueryPredicate.NotKnown ) ) { for( int j = 0; j < atoms.size(); j++ ) { QueryAtom nextAtom = atoms.get( j ); if( i == j || nextAtom.getPredicate().equals( QueryPredicate.NotKnown ) ) { continue; } if( nextAtom.getArguments().contains( a ) ) { if( log.isLoggable( Level.FINE ) ) log.fine( "Unbound vars for not" ); continue LOOP; } } } } else { boundCount++; } } } if( boundCount == 0 && newBoundVars.size() > unboundCount ) { if( sortedAtoms != null ) { if( log.isLoggable( Level.FINE ) ) log.fine( "Stop at not optimal ordering" ); continue; } else { if( log.isLoggable( Level.FINE ) ) log.fine( "Continue not optimal ordering, no solution yet." ); newNonOptimal = true; } } } atoms.remove( atom ); orderedAtoms.add( atom ); if( log.isLoggable( Level.FINE ) ) log.fine( "Atom[" + i + "/" + atoms.size() + "] " + atom + " from " + atoms + " to " + orderedAtoms ); minCost = chooseOrdering( atoms, orderedAtoms, newBoundVars, newNonOptimal, minCost ); atoms.add( i, atom ); orderedAtoms.remove( orderedAtoms.size() - 1 ); } return minCost; } @Override public QueryAtom next(final ResultBinding binding) { return sortedAtoms.get( index++ ).apply( binding ); } @Override public boolean hasNext() { return index < size; } @Override public void back() { index--; } @Override public void reset() { index = 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy