org.aksw.sparqlify.database.ExprIndex Maven / Gradle / Ivy
The newest version!
package org.aksw.sparqlify.database;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
import org.aksw.commons.collections.CartesianProduct;
import org.aksw.commons.collections.FlatMapView;
import org.aksw.jena_sparql_api.normal_form.Clause;
import org.aksw.jena_sparql_api.normal_form.Dnf;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.Expr;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
class DnfIndex {
private Multimap singleVarExpr = HashMultimap.create();
//private Map specific
// NOTE: Additions are conjunctive!
public void add(Dnf dnf) {
Collection clauses = dnf.getClauses();
//dnf.getCommonExprs()
}
}
/**
*
* TODO Clarify: Do I want disjunctive or conjunctive normal form?
* (a and b) or (c and d) or
* (a or b) and(c or d) ?
* I guess the former is better, as (a and not a) can be easily detected
*
* What happens if we allow conjunctions of disjunctive normal forms?
* ((a, b) or (c, d) AND ((x) or (y)))
* becomes
* (abx or aby or cdx or cdy) (so the cross product of the involved clauses)
*
* Maybe i could do virtual clauses:
* CrossJoinClause(Clauses ...)
*
*
*
* Hm, but with CNF it is easier to add new expressions.
*
* @author Claus Stadler
*
*/
public class ExprIndex {
private ExprIndex parent;
// TODO I need this method due to the lack of suppert for CNF lookups on tables right now
public void getEffectiveDnf(Collection vars) {
}
/**
* I use this method for getting constraints for finding view candidates
*
*
* @param dnfs
* @param index
* @param dnfIndex
* @param blacklist
* @param depth
* @param parentClause
* @param result
*/
public void calcEffectiveClauses(final List dnfs, int index, final Set blacklist, Clause parentClause, final Set result) {
if(index >= dnfs.size()) {
if(parentClause != null) {
result.add(parentClause);
}
return;
}
Dnf dnf = dnfs.get(index);
for(Clause clause : dnf.getClauses()) {
if(blacklist.contains(clause)) {
continue;
}
Clause merged;
if(parentClause == null) {
merged = parentClause;
} else {
Set exprs = new HashSet(parentClause.getExprs());
exprs.addAll(clause.getExprs());
merged = new Clause(exprs);
calcEffectiveClauses(dnfs, index + 1, blacklist, merged, result);
}
}
}
/**
* This method is an ugly hack right, but I don't know
* where to better calculate it
*
* @return
*/
public Set calcEffectiveClauses() {
Set result = new HashSet();
List> tmp = new ArrayList>();
for(Dnf dnf : dnfs) {
tmp.add(dnf.getClauses());
}
CartesianProduct cartesian = CartesianProduct.create(tmp);
for(List list : cartesian) {
Set exprs = new HashSet();
for(Clause c : list) {
exprs.addAll(c.getExprs());
}
result.add(new Clause(exprs));
}
return result;
}
public Set getEffectiveClauses() {
return effectiveClauses;
}
private Set effectiveClauses;
//private List dnfs = new ArrayList();
// The DNFs are sorted by number of clauses
private NavigableMap> dnfGroups = new TreeMap>();
private Collection dnfs = new FlatMapView(dnfGroups.values());
private Set varsMentioned = new HashSet();
//private Map
//private Map commonSingleVarExprs
//private Dnf dnf = new Dnf();
//private Map varToClauses = new HashMap();
//private ExprList exprs = new ExprList();
//private Multimap varToExprs = HashMultimap.create();
//VarExprList x;
//private Map varToPrefixes = new HashMap();
//private Map
public ExprIndex() {
}
public ExprIndex(ExprIndex parent) {
this.parent = parent;
/*
for(Dnf dnf : parent.getDnf()) {
add(dnf);
}*/
}
public ExprIndex(ExprIndex parent, Iterable exprs) {
this.parent = parent;
addAll(exprs);
}
public ExprIndex(Set dnfs) {
addAll(dnfs);
}
public ExprIndex getParent() {
return parent;
}
public Collection getDnf() {
return dnfs;
}
public Set getVarsMentioned() {
return varsMentioned;
}
void add(Dnf dnf) {
int n = dnf.getClauses().size();
Set set = dnfGroups.get(n);
if(set == null) {
set = new HashSet();
dnfGroups.put(n, set);
}
set.add(dnf);
varsMentioned.addAll(dnf.getVarsMentioned());
this.effectiveClauses = calcEffectiveClauses();
}
void addAll(Collection dnfs) {
for(Dnf dnf : dnfs) {
add(dnf);
}
}
void add(Expr expr) {
Dnf dnf = Dnf.create(expr);
add(dnf);
//dnfs.add(dnf);
/*
exprs.add(expr);
for(Var var : exprs.getVarsMentioned()) {
varToExprs.put(var, expr);
}*/
//DnfUtils.toDnf(expr);
//varToExp
}
/**
* Any clause containing a var means, that in order for the clause to evaluate
* to true, the expression it is involved must be true.
*
* @param var
* @return
*/
public Set getAllClausesWith(Var var) {
Set result = new HashSet();
for(Set dnfGroup : dnfGroups.values()) {
for(Dnf dnf : dnfGroup) {
Collection clauses = dnf.get(var);
result.addAll(clauses);
}
}
return result;
}
public Set getAllSingleVarExprs(Var var) {
Set result = new HashSet();
for(Set dnfGroup : dnfGroups.values()) {
for(Dnf dnf : dnfGroup) {
Collection clauses = dnf.get(Collections.singleton(var));
result.addAll(clauses);
}
}
return result;
}
public void addAll(Iterable exprs) {
for(Expr expr : exprs) {
add(expr);
}
}
@Override
public String toString() {
return dnfs.toString();
}
public ExprIndex filterByVars(Set requiredVars) {
//List filteredDnfs = new ArrayList();
ExprIndex result = new ExprIndex();
for(Set dnfGroup : dnfGroups.values()) {
for(Dnf dnf : dnfGroup) {
Set clauses = dnf.filterByVars(requiredVars);
Dnf filteredDnf = new Dnf(clauses);
result.add(filteredDnf);
}
}
return result;
}
}
/*
class EffectiveClauseIterator
extends SinglePrefetchIterator
{
//private ExprIndex dnfIndex;
private Set blacklist;
private StackCartesianProductIterator it;
public EffectiveClauseIterator(ExprIndex dnfIndex, Set blacklist) {
Collection dnfs = dnfIndex.getDnf();
List> clauses = new ArrayList>();
for(Dnf dnf : dnfs) {
clauses.add(dnf.getClauses());
}
//DescenderIterator it = new DescenderIterator(clauses, )
this.it = new StackCartesianProductIterator(clauses);
}
@Override
protected Clause prefetch() throws Exception {
while(it.hasNext()) {
List item = it.next();
Clause newClause = item.get(item.size() - 1);
if(blacklist.contains(newClause)) {
continue;
} else if(it.canDescend()) {
it.descend();
}
}
}
}
*/
/**
* A class intended for keeping track of possible constant values of a variable.
*
* Do I have to work with clauses? Or is it possible to simplify?
*
* OK, I don't think this class makes sense right now.
* If we map a variable to a constant, then we don't need to deal with alternatives.
* And if we want to mess around with expressions and satisfiability, then we can just
* work on the expression level, rather trying to destill possible constant assignments from the exprs
* (althought it might be useable for optimization)
*
* @author Claus Stadler
*
* @param
*/
class ValueSet
{
private Set> alternatives;
/**
* Example 1: Alternatives, or
* (a = x || a = y)
* -> ((x), (y))
*
* ... && (a = x || a = z)
* -> a = x
*
*
*
* Example 2: Negated alternatives
* (?a != y || ?a != z) -> no constraint derivable
* "x is either not an Animal or it is not a Person"
* ((!y), (!z))
*
*
* Example 3: Negative alternatives
* (?a != y && ?a != z)
* "x is neither an Animal nor a Person"
* -> neg = (!y, !z)
*
* Example 4: Mixed
* (?a = x || ?a = y || ?a != y || ?a != z)
*
*
* Example 5: Mixed
* (?a = v || ?a = w) && (?a != v && ?a != y)
* -> (?a = v && ?a != v && ?a != y) || (?a = w && ?a != v && ?a != y)
* -> (false) || (?a = w && ?a != v && ?a != y)
* pos = {w}
*
*
* So stating an equality
*
* @param values
*/
public void stateAlternatives(Set values) {
}
}