Author: andy
Date: Sun Nov 17 21:56:55 2013
New Revision: 1542842

URL: http://svn.apache.org/r1542842
Log:
Placement for union (first attempt)

Added:
    jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java
Modified:
    jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java
    jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java

Modified: jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java?rev=1542842&r1=1542841&r2=1542842&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java (original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/OptMain.java Sun Nov 17 21:56:55 2013
@@ -26,91 +26,118 @@ import com.hp.hpl.jena.query.Query ;
 import com.hp.hpl.jena.query.QueryFactory ;
 import com.hp.hpl.jena.sparql.ARQConstants ;
 import com.hp.hpl.jena.sparql.algebra.* ;
+import com.hp.hpl.jena.sparql.algebra.op.OpJoin ;
 import com.hp.hpl.jena.sparql.algebra.op.OpLabel ;
 import com.hp.hpl.jena.sparql.algebra.optimize.* ;
 import com.hp.hpl.jena.sparql.algebra.optimize.Optimize.RewriterFactory ;
+import com.hp.hpl.jena.sparql.engine.main.JoinClassifier ;
 import com.hp.hpl.jena.sparql.sse.SSE ;
 import com.hp.hpl.jena.sparql.util.Context ;
 
 public class OptMain {
+    // LeftJoin - Fixed vars only (LHS) OpVars.  VarFinder.fixed(null)
+    // UNION - fixed : intersection
+    // Test - UNION
 
-    public static void main(String... argv) throws Exception {
-        {
+    // Also TransformDistinctToReduced (JENA-585)and 
TransformOrderByDistincApplication 
+    
+    // JENA-383 : The query optimizer generates a suboptimal query plan in 
case of nested optionals followed by a filter
+
+    // JENA-293 : Allow the filter placement optimziation to push FILTER 
though BIND.
+    //    Filter push throughs.
+    // JENA-384 : SubstituteFilterOptimize :: Interaction of optimization 
(TransformFilterEquality) and initial binding
+
+    // Was Op.equals a good idea?
+    // Calculate vars for an expr once and cache : op.getVars.
+    
+    // Checking:
+    // filter-equality-13 -- scope issue for leftjoin, conditional in a 
sequence.   
+    //   Can't push in the filer to the sequence as may yield no binding -> 
need fixed vars  
+    // TestTranformFilters : 
+    //    optionalEqualitySubQuery_01 -- looks OK -- JENA-432
+    //    optionalEquality_01 JENA-383 -- WRONG - Lost RHS of conditional
+    //    optionalEqualityScope_01 -- WRONG - 
+    
+    // Double push in a sequence of conditional then BGP.
+    // JoinStartegy and FilterPlacement interaction.
+
+    public static void main(String... argv) {
+        testFailure() ;
+    }
+            
+    public static void testFailure() {       
         String DIR = "/home/afs/Jena/jena-arq/testing/ARQ/OptFilterEquality" ;
-        
-        //arq.sparql.main("--engine=ref", 
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
-        //arq.sparql.main(                
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+
+        arq.sparql.main(                
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+        rewire() ;
+        arq.sparql.main(                
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+        dewire() ;
+//        arq.sparql.main(                
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
+//        System.exit(0) ;
 
         Query q = QueryFactory.read(DIR+"/filter-equality-13.rq") ;
         Op op1 = Algebra.compile(q) ;
         Op op2 = Algebra.optimize(op1) ;
         System.out.println(op2);
         rewire() ;
+        // Pushing filter over the (conditional) is wrong
+        // Need to look for MUST be fixed variables, which is not what OpVars. 
mentioned vars is.
+        // nor is VarFinder.fixed (but is that wrong?)
+        
+/*        
+(filter (= ?x <http://example.org/x1>)
+  (sequence
+    (conditional
+      (table unit)
+      (bgp (triple ?x <http://example.org/qq> ?o2)))
+    (bgp (triple ?x <http://example.org/p> ?o1))))
+
+Rewrite2
+(sequence
+  (filter (= ?x <http://example.org/x1>)
+    (conditional
+      (table unit)
+      (bgp (triple ?x <http://example.org/qq> ?o2))))
+  (filter (= ?x <http://example.org/x1>)
+    (bgp (triple ?x <http://example.org/p> ?o1))))
+*/
         op2 = Algebra.optimize(op1) ;
         System.out.println(op2);
 
-        
-        //arq.sparql.main(                
"--query="+DIR+"/filter-equality-13.rq", "--data="+DIR+"/data-4.ttl");
-        
         System.exit(0) ;
+    }
+    
+    static void varFinder() {
+        if ( false )
+        {
+            Op op = SSE.parseOp("(union (bgp (?s ?p ?o1)) (bgp (?s ?p ?o2)))") 
;
+            System.out.println(op) ;
+            // ** WRONG?? Exact meaning of "defined"?
+            System.out.println(VarFinder2.fixed(op)) ;
+            System.out.println(VarFinder2.optDefined(op)) ;
+            System.exit(0) ;
         }
-        // Project (and other blockers?)
-        
-        // Tests
-        //  coverage, 
-        //  repeated application.
-        //  BGPs directly.
-        //  Complex/recurse tests
-
-        // Transformations are applied "bottom up"
-        // - should this be top down?
-        // - what happens if hits a filter?  Currently, it stops.
-        
-        // test combined with filter equality.
-        
-        // What about covered left but partial right?
-        // Push left (join),)
-        // Push left (left join) 
-        // Other cases
-        
-        // Check order of all optimziations - equality last.
-        
-        // Also TransformDistinctToReduced (JENA-585)and 
TransformOrderByDistincApplication 
-        
-        // Combinations e.g. placement then equality
-        
-        
-        // JENA-383 : The query optimizer generates a suboptimal query plan in 
case of nested optionals followed by a filter
-
-        // JENA-293 : Allow the filter placement optimziation to push FILTER 
though BIND.
-        //    Filter push throughs.
-        // JENA-384 : SubstituteFilterOptimize :: Interaction of optimization 
(TransformFilterEquality) and initial binding
-
-        // Filter placement
-        // * Nesting
-        // * Join
-        // Need to say what was pushed.
-        
-        // Full optimization tests
-        
-        // Was Op.equals a good idea?
-        // Calculate vars for an expr once and cache : op.getVars.
-        
-        // Push in inside a sequence?
-        
-        
-        
-        // Checking:
-        // filter-equality-13 -- scope issue for leftjoin, conditional in a 
sequence.   
-        //   Can't push in the filer to the sequence as may yield no binding 
-> need fixed vars  
-        // TestTranformFilters : 
-        //    optionalEqualitySubQuery_01 -- looks OK -- JENA-432
-        //    optionalEquality_01 JENA-383 -- WRONG - Lost RHS of conditional
-        //    optionalEqualityScope_01 -- WRONG - 
-        
-        // Double push in a sequence of conditional then BGP.
-        // JonStartegy and FilterPlacement interaction.
-        
+        {
+            // See alt VarFinder
+            String[] x = {
+                "(join (bgp (?s ?p ?o)) (union (bgp (?s ?p ?o)) (bgp (?s ?p 
?o1))) )",
+                "(join (bgp (?s ?p ?o)) (union (bgp (?s ?p ?z)) (bgp (?s ?p1 
?z))) )"
+            } ;
+            
+            for (String s : x ) {
+                System.out.println("--------") ;
+                Op op = SSE.parseOp(s) ;
+                System.out.println(op) ;
+                System.out.println("fixed: "+VarFinder2.fixed(op)) ;
+                System.out.println("Opt:   "+VarFinder2.optDefined(op)) ;
+                boolean nonLinear = JoinClassifier.isLinear((OpJoin)op) ;
+                System.out.println(nonLinear) ;
+            }
+            System.exit(0) ;
+        }
+    }
+    
+    static void placement() {
         if ( false ) {
             //String input = "(filter (?x 123) (sequence (conditional (table 
unit) 
             String input = StrUtils.strjoinNL
@@ -186,6 +213,10 @@ public class OptMain {
     private static void rewire() {
         Optimize.setFactory(new RewriterFactory2()); 
     }
+    
+    private static void dewire() {
+        Optimize.setFactory(Optimize.stdOptimizationFactory) ;
+    }
 
     static class RewriterFactory2 implements RewriterFactory {
 

Modified: jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java?rev=1542842&r1=1542841&r2=1542842&view=diff
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java 
(original)
+++ jena/Scratch/AFS/Dev/src-dev/opt/TransformFilterPlacement_Rewrite.java Sun 
Nov 17 21:56:55 2013
@@ -121,6 +121,10 @@ public class TransformFilterPlacement_Re
             placement = placeLeftJoin(exprs, (OpLeftJoin)input) ;
         else if ( input instanceof OpFilter )
             placement = placeFilter(exprs, (OpFilter)input) ;
+        else if ( input instanceof OpUnion )
+            placement = placeUnion(exprs, (OpUnion)input) ;
+        
+        
         // These are operations where chnaging the order of operations
         // does not in itself make a differencebut enables expressions
         // to be pushed own down to where they might make a difference.
@@ -368,8 +372,19 @@ public class TransformFilterPlacement_Re
         return result(op, nLeft.unplaced) ;
     }
     
-    private static <T> boolean disjoint(Collection<T> collection, 
Collection<T> possibleElts) {
-        return CollectionUtils.disjoint(collection, possibleElts) ;
+    private static Placement placeUnion(ExprList exprs, OpUnion input) {
+        // Unsubtle - push into both sides.
+        // Neater - for all unpushed put outside the union. 
+        Op left = input.getLeft() ;
+        Placement pLeft = transform(exprs, left) ;
+        left = buildFilter(pLeft) ;
+        
+        Op right = input.getRight() ;
+        Placement pRight = transform(exprs, right) ;
+        right = buildFilter(pRight) ;
+        
+        Op op2 = OpUnion.create(left, right) ;
+        return result(op2, emptyList) ;
     }
 
     /** Try to optimize (filter (extend ...)) */
@@ -461,10 +476,16 @@ public class TransformFilterPlacement_Re
         return op ;
     }
 
+    private static <T> boolean disjoint(Collection<T> collection, 
Collection<T> possibleElts) {
+        return CollectionUtils.disjoint(collection, possibleElts) ;
+    }
+
     /** Place expressions around an Op */
     private static Op buildFilter(Placement placement) {
         if ( placement == null )
             return null ;
+        if ( placement.unplaced.isEmpty() )
+            return placement.op ;
         return buildFilter(placement.unplaced, placement.op) ;
     }
     

Added: jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java?rev=1542842&view=auto
==============================================================================
--- jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java (added)
+++ jena/Scratch/AFS/Dev/src-dev/opt/VarFinder2.java Sun Nov 17 21:56:55 2013
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opt;
+
+import static com.hp.hpl.jena.sparql.util.VarUtils.addVar ;
+import static com.hp.hpl.jena.sparql.util.VarUtils.addVars ;
+
+import java.util.* ;
+import java.util.Map.Entry ;
+
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.algebra.OpVisitorBase ;
+import com.hp.hpl.jena.sparql.algebra.op.* ;
+import com.hp.hpl.jena.sparql.core.BasicPattern ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.core.VarExprList ;
+import com.hp.hpl.jena.sparql.expr.Expr ;
+import com.hp.hpl.jena.sparql.expr.ExprList ;
+
+public class VarFinder2
+{
+    // See also VarUtils and OpVars.
+    // This class is specific to the needs of the main query engine and 
scoping of variables
+    
+    public static Set<Var> optDefined(Op op)
+    {
+        return VarUsageVisitor.apply(op).optDefines ;
+    }
+    
+    public static Set<Var> fixed(Op op)
+    {
+        return VarUsageVisitor.apply(op).defines ;
+    }
+    
+    public static Set<Var> filter(Op op)
+    {
+        return VarUsageVisitor.apply(op).filterMentions ;
+    }
+
+    VarUsageVisitor varUsageVisitor ;
+    
+    public VarFinder2(Op op)
+    { varUsageVisitor = VarUsageVisitor.apply(op) ; }
+    
+    public Set<Var> getOpt() { return varUsageVisitor.optDefines ; }
+    public Set<Var> getFilter() { return varUsageVisitor.filterMentions ; }
+    public Set<Var> getAssign() { return varUsageVisitor.assignMentions ; }
+    public Set<Var> getFixed() { return varUsageVisitor.defines ; }
+    
+    private static class VarUsageVisitor extends OpVisitorBase //implements 
OpVisitor
+    {
+        static VarUsageVisitor apply(Op op)
+        {
+            VarUsageVisitor v = new VarUsageVisitor() ;
+            op.visit(v) ;
+            return v ;
+        }
+
+        Set<Var> defines = null ;
+        Set<Var> optDefines = null ;
+        Set<Var> filterMentions = null ;
+        Set<Var> assignMentions = null ;
+
+        VarUsageVisitor()
+        {
+            defines = new HashSet<Var>() ;   
+            optDefines = new HashSet<Var>() ;
+            filterMentions = new HashSet<Var>() ;
+            assignMentions = new HashSet<Var>() ;
+        }
+        
+        VarUsageVisitor(Set<Var> _defines, Set<Var> _optDefines, Set<Var> 
_filterMentions, Set<Var> _assignMentions)
+        {
+            defines = _defines ;
+            optDefines = _optDefines ;
+            filterMentions = _filterMentions ;
+            assignMentions = _assignMentions ;
+        }
+        
+        @Override
+        public void visit(OpQuadPattern quadPattern)
+        {
+            addVar(defines, quadPattern.getGraphNode()) ;
+            BasicPattern triples = quadPattern.getBasicPattern() ;
+            addVars(defines, triples) ;
+        }
+
+        @Override
+        public void visit(OpBGP opBGP)
+        {
+            BasicPattern triples = opBGP.getPattern() ;
+            addVars(defines, triples) ;
+        }
+        
+        @Override
+        public void visit(OpExt opExt)
+        {
+            opExt.effectiveOp().visit(this) ;
+        }
+        
+        @Override
+        public void visit(OpJoin opJoin)
+        {
+            joinAcc(opJoin.getLeft()) ;
+            joinAcc(opJoin.getRight()) ;
+        }
+        
+        @Override
+        public void visit(OpSequence opSequence)
+        {
+            for ( Op op : opSequence.getElements() )
+                joinAcc(op) ;    
+        }
+        
+        private void joinAcc(Op op)
+        {
+            VarUsageVisitor usage = VarUsageVisitor.apply(op) ;
+            
+            defines.addAll(usage.defines) ;
+            optDefines.addAll(usage.optDefines) ;
+            filterMentions.addAll(usage.filterMentions) ;
+        }
+
+        @Override
+        public void visit(OpLeftJoin opLeftJoin)
+        {
+            leftJoin(opLeftJoin.getLeft(), opLeftJoin.getRight(), 
opLeftJoin.getExprs()) ;
+        }
+        
+        @Override
+        public void visit(OpConditional opLeftJoin)
+        { 
+            leftJoin(opLeftJoin.getLeft(), opLeftJoin.getRight(), null) ;
+        }
+
+        private void leftJoin(Op left, Op right, ExprList exprs)
+        {
+            VarUsageVisitor leftUsage = VarUsageVisitor.apply(left) ;
+            VarUsageVisitor rightUsage = VarUsageVisitor.apply(right) ;
+            
+            defines.addAll(leftUsage.defines) ;
+            optDefines.addAll(leftUsage.optDefines) ;
+            filterMentions.addAll(leftUsage.filterMentions) ;
+            assignMentions.addAll(leftUsage.assignMentions) ;
+            
+            optDefines.addAll(rightUsage.defines) ;     // Asymmetric.
+            optDefines.addAll(rightUsage.optDefines) ;
+            filterMentions.addAll(rightUsage.filterMentions) ;
+            assignMentions.addAll(rightUsage.assignMentions) ;
+            
+            // Remove any definites that are in the optionals 
+            // as, overall, they are definites 
+            optDefines.removeAll(leftUsage.defines) ;
+
+            // And the associated filter.
+            if ( exprs != null )
+                exprs.varsMentioned(filterMentions);
+        }
+        
+        @Override
+        public void visit(OpUnion opUnion)
+        {
+            VarUsageVisitor leftUsage = 
VarUsageVisitor.apply(opUnion.getLeft()) ;
+            VarUsageVisitor rightUsage = 
VarUsageVisitor.apply(opUnion.getRight()) ;
+
+            // defines = intersection(left.define, right.define)
+            // Optional = optional either side and not in both sides. 
+
+//            Set<Var> def = SetUtils.intersection(leftUsage.defines, 
rightUsage.defines) ;
+//            Set<Var> opt1 = SetUtils.difference(leftUsage.defines, def) ;
+//            Set<Var> opt2 = SetUtils.difference(rightUsage.defines, def) ;
+//            
+//            
+//            defines.addAll(def) ;
+//            optDefines.addAll(opt1) ;
+//            optDefines.addAll(opt2) ;
+//            optDefines.addAll(leftUsage.optDefines) ;
+//            optDefines.addAll(rightUsage.optDefines) ;
+//
+//            filterMentions.addAll(leftUsage.filterMentions) ;
+//            filterMentions.addAll(rightUsage.filterMentions) ;
+//            assignMentions.addAll(rightUsage.assignMentions) ;
+//            assignMentions.addAll(leftUsage.assignMentions) ;
+
+            defines.addAll(leftUsage.defines) ;
+            optDefines.addAll(leftUsage.optDefines) ;
+            filterMentions.addAll(leftUsage.filterMentions) ;
+            assignMentions.addAll(leftUsage.assignMentions) ;
+            
+            defines.addAll(rightUsage.defines) ;
+            optDefines.addAll(rightUsage.optDefines) ;
+            filterMentions.addAll(rightUsage.filterMentions) ;
+            assignMentions.addAll(rightUsage.assignMentions) ;
+        }
+
+        @Override
+        public void visit(OpGraph opGraph)
+        {
+            addVar(defines, opGraph.getNode()) ;
+            opGraph.getSubOp().visit(this) ;
+        }
+        
+        // @Override
+        @Override
+        public void visit(OpFilter opFilter)
+        {
+            opFilter.getExprs().varsMentioned(filterMentions);
+            opFilter.getSubOp().visit(this) ;
+        }
+        
+        @Override
+        public void visit(OpAssign opAssign)
+        {
+            opAssign.getSubOp().visit(this) ;
+            processVarExprList(opAssign.getVarExprList()) ;
+        }
+        
+        @Override
+        public void visit(OpExtend opExtend)
+        {
+            opExtend.getSubOp().visit(this) ;
+            processVarExprList(opExtend.getVarExprList()) ;
+        }
+        
+        private void processVarExprList(VarExprList varExprList)
+        {
+            Map<Var, Expr> map = varExprList.getExprs() ;
+            for ( Entry<Var, Expr> e : map.entrySet() )
+            {
+                defines.add(e.getKey()) ;
+                e.getValue().varsMentioned(assignMentions);
+            }
+        }
+        
+        @Override
+        public void visit(OpProject opProject)
+        {
+            List<Var> vars = opProject.getVars() ;
+            VarUsageVisitor subUsage = 
VarUsageVisitor.apply(opProject.getSubOp()) ;
+            
+            subUsage.defines.retainAll(vars) ;
+            subUsage.optDefines.retainAll(vars) ;
+            subUsage.optDefines.retainAll(vars) ;
+            defines.addAll(subUsage.defines) ;
+            optDefines.addAll(subUsage.optDefines) ;
+            filterMentions.addAll(subUsage.filterMentions) ;
+            assignMentions.addAll(subUsage.assignMentions) ;
+        }
+
+        @Override
+        public void visit(OpTable opTable)
+        { 
+            defines.addAll(opTable.getTable().getVars()) ;
+        }
+
+        @Override
+        public void visit(OpNull opNull)
+        { }
+    }
+}


Reply via email to