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

io.mindmaps.graql.internal.reasoner.predicate.AtomBase Maven / Gradle / Ivy

/*
 * MindmapsDB - A Distributed Semantic Database
 * Copyright (C) 2016  Mindmaps Research Ltd
 *
 * MindmapsDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MindmapsDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MindmapsDB. If not, see .
 */

package io.mindmaps.graql.internal.reasoner.predicate;

import com.google.common.collect.Sets;
import io.mindmaps.MindmapsGraph;
import io.mindmaps.concept.Rule;
import io.mindmaps.util.ErrorMessage;
import io.mindmaps.concept.RoleType;
import io.mindmaps.concept.Type;
import io.mindmaps.graql.*;
import io.mindmaps.graql.admin.PatternAdmin;
import io.mindmaps.graql.admin.ValuePredicateAdmin;
import io.mindmaps.graql.admin.VarAdmin;
import io.mindmaps.graql.internal.pattern.Patterns;
import io.mindmaps.graql.internal.reasoner.query.Query;
import java.util.stream.Collectors;
import javafx.util.Pair;

import java.util.*;

public abstract class AtomBase implements Atomic{

    protected String varName;
    protected Type type = null;
    protected final String typeId;
    protected final PatternAdmin atomPattern;
    private Query parent = null;

    public AtomBase() {
        this.varName = null;
        this.typeId = null;
        this.atomPattern = null;
    }

    public AtomBase(VarAdmin pattern) {
        this.atomPattern = pattern;
        Pair varData = extractDataFromVar(atomPattern.asVar());
        this.varName = varData.getKey();
        this.typeId = varData.getValue();
    }

    public AtomBase(VarAdmin pattern, Query par) {
        this(pattern);
        this.parent = par;
    }

    public AtomBase(AtomBase a) {
        if (a.getParentQuery() != null)
            this.parent = a.getParentQuery();

        this.atomPattern = Patterns.mergeVars(Sets.newHashSet(a.atomPattern.asVar()));
        Pair varData = extractDataFromVar(atomPattern.asVar());
        varName = varData.getKey();
        typeId = varData.getValue();
    }

    public abstract Atomic clone();

    private Pair extractDataFromVar(VarAdmin var) {
        String vTypeId;
        String vName = var.getName();

        Map> resourceMap = var.getResourcePredicates();
        if (resourceMap.size() != 0) {
            if (resourceMap.size() != 1)
                throw new IllegalArgumentException(ErrorMessage.MULTIPLE_RESOURCES.getMessage(var.toString()));

            Map.Entry> entry = resourceMap.entrySet().iterator().next();
            vTypeId = entry.getKey().getId().orElse("");
        }
        else
            vTypeId = var.getType().flatMap(VarAdmin::getId).orElse("");

        return new Pair<>(vName, vTypeId);
    }

    @Override
    public String toString(){ return atomPattern.toString(); }

    @Override
    public boolean isRuleResolvable() {
        Type type = getParentQuery().getGraph().orElse(null).getType(getTypeId());
        return type != null && !type.getRulesOfConclusion().isEmpty();
    }

    @Override
    public boolean isRecursive(){
        if (isResource()) return false;
        boolean atomRecursive = false;

        String typeId = getTypeId();
        if (typeId.isEmpty()) return false;
        Type type = getParentQuery().getGraph().orElse(null).getType(typeId);
        Collection presentInConclusion = type.getRulesOfConclusion();
        Collection presentInHypothesis = type.getRulesOfHypothesis();

        for(Rule rule : presentInConclusion)
            atomRecursive |= presentInHypothesis.contains(rule);

        return atomRecursive;
    }
    @Override
    public boolean containsVar(String name){ return getVarNames().contains(name);}

    @Override
    public PatternAdmin getPattern(){ return atomPattern;}
    
    @Override
    public MatchQuery getMatchQuery(MindmapsGraph graph) {
        QueryBuilder qb = Graql.withGraph(graph);
        MatchQuery matchQuery = qb.match(getPattern());

        //add substitutions
        Map varSubMap = getVarSubMap();
        Set selectVars = getVarNames();
        varSubMap.forEach( (var, sub) -> {
            Set patterns = new HashSet<>();
            patterns.add(sub.getPattern());
            matchQuery.admin().getPattern().getPatterns().add(Patterns.conjunction(patterns));
        });
        return matchQuery.admin().select(selectVars);
    }

    @Override
    public Query getParentQuery(){
        if(parent == null)
            throw new IllegalStateException(ErrorMessage.PARENT_MISSING.getMessage(this.toString()));
        return parent;
    }

    @Override
    public void setParentQuery(Query q){ parent = q;}

    private void setVarName(String var){
        varName = var;
        atomPattern.asVar().setName(var);
    }

    @Override
    public void unify(String from, String to) {
        String var = getVarName();
        if (var.equals(from)) {
            setVarName(to);
        } else if (var.equals(to)) {
            setVarName("captured->" + var);
        }
    }

    @Override
    public void unify(Map unifiers){
        String var = getVarName();
        if (unifiers.containsKey(var)) {
            setVarName(unifiers.get(var));
        }
        else if (unifiers.containsValue(var)) {
            setVarName("captured->" + var);
        }
    }

    @Override
    public String getVarName(){ return varName;}
    @Override
    public Set getVarNames(){
        return Sets.newHashSet(varName);
    }
    @Override
    public Type getType(){
        if (type == null)
            type = getParentQuery().getGraph().orElse(null).getType(typeId);
        return type;
    }
    @Override
    public String getTypeId(){ return typeId;}
    @Override
    public String getVal(){ return null;}

    @Override
    public Map getUnifiers(Atomic parentAtom) {
        Set varsToAllocate = parentAtom.getVarNames();
        Set childBVs = getVarNames();
        Map unifiers = new HashMap<>();
        Map> childMap = getVarTypeRoleMap();
        Map> parentMap = parentAtom.getRoleVarTypeMap();

        //try based on substitutions
        Query parentQuery = parentAtom.getParentQuery();
        getParentQuery().getSubstitutions().stream().filter(sub -> containsVar(sub.getVarName())).forEach(sub -> {
            String chVar = sub.getVarName();
            String id = sub.getVal();
            Set parentSubs = parentQuery.getSubstitutions().stream()
                        .filter(s -> s.getVal().equals(id)).collect(Collectors.toSet());
            String pVar = parentSubs.isEmpty()? "" : parentSubs.iterator().next().getVarName();
            if (!pVar.isEmpty()) {
                if (!chVar.equals(pVar)) unifiers.put(chVar, pVar);
                childBVs.remove(chVar);
                varsToAllocate.remove(pVar);
            }
        });

        //try based on roles
        for (String chVar : childBVs) {
            RoleType role = childMap.containsKey(chVar) ? childMap.get(chVar).getValue() : null;
            String pVar = role != null && parentMap.containsKey(role) ? parentMap.get(role).getKey() : "";
            if (pVar.isEmpty())
                pVar = varsToAllocate.iterator().next();

            if (!chVar.equals(pVar)) unifiers.put(chVar, pVar);
            varsToAllocate.remove(pVar);
        }
        return unifiers;
    }

    @Override
    public Set getSubstitutions() {
        return getParentQuery().getAtoms().stream()
                .filter(Atomic::isSubstitution)
                .filter(atom -> containsVar(atom.getVarName()))
                .collect(Collectors.toSet());
    }

    @Override
    public Set getTypeConstraints(){
        return getParentQuery().getTypeConstraints().stream()
                .filter(atom -> containsVar(atom.getVarName()))
                .collect(Collectors.toSet());
    }

    @Override
    public Set getValuePredicates(){
        return getParentQuery().getAtoms().stream()
                .filter(Atomic::isValuePredicate)
                .filter(atom -> containsVar(atom.getVarName()))
                .collect(Collectors.toSet());
    }

    @Override
    public Map getVarSubMap() {
        Map map = new HashMap<>();
        getSubstitutions().forEach( sub -> {
            String var = sub.getVarName();
            map.put(var, sub);
        });
        return map;
    }

    @Override
    public Map getRoleConceptIdMap(){
        Map roleConceptMap = new HashMap<>();
        Map varSubMap = getVarSubMap();
        Map> roleVarMap = getRoleVarTypeMap();

        roleVarMap.forEach( (role, varTypePair) -> {
            String var = varTypePair.getKey();
            roleConceptMap.put(role, varSubMap.containsKey(var) ? varSubMap.get(var).getVal() : "");
        });
        return roleConceptMap;
    }

    public Map> getVarTypeRoleMap() {
        Map> roleVarTypeMap = new HashMap<>();
        if (getParentQuery() == null) return roleVarTypeMap;

        Set vars = getVarNames();
        Map varTypeMap = getParentQuery().getVarTypeMap();

        vars.forEach(var -> {
            Type type = varTypeMap.get(var);
            roleVarTypeMap.put(var, new Pair<>(type, null));
        });
        return roleVarTypeMap;
    }

    public Map> getRoleVarTypeMap() { return new HashMap<>();}
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy