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

io.mindmaps.graql.internal.reasoner.predicate.Relation 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 io.mindmaps.MindmapsGraph;
import io.mindmaps.concept.RoleType;
import io.mindmaps.concept.Type;
import io.mindmaps.graql.Graql;
import io.mindmaps.graql.Var;
import io.mindmaps.graql.admin.VarAdmin;
import io.mindmaps.graql.internal.reasoner.query.Query;
import io.mindmaps.util.ErrorMessage;
import javafx.util.Pair;

import java.util.*;

import static io.mindmaps.graql.internal.reasoner.Utility.getCompatibleRoleTypes;

public class Relation extends AtomBase {

    private final Set castings = new HashSet<>();

    public Relation(VarAdmin pattern) {
        super(pattern);
        castings.addAll(pattern.getCastings());
    }

    public Relation(VarAdmin pattern, Query par) {
        super(pattern, par);
        castings.addAll(pattern.getCastings());
    }

    public Relation(String id, Map roleMap, Query par){
        super(constructRelation(id, roleMap), par);
        castings.addAll(getPattern().asVar().getCastings());
    }

    public Relation(Relation a) {
        super(a);
        castings.addAll(a.getPattern().asVar().getCastings());
    }

    @Override
    public Atomic clone(){
        return new Relation(this);
    }

    //rolePlayer-roleType
    public static VarAdmin constructRelation(String id, Map roleMap) {
        Var var = Graql.var().isa(id);
        roleMap.forEach( (player, role) -> var.rel(role, player));
        return var.admin().asVar();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Relation)) return false;
        Relation a2 = (Relation) obj;

        //TODO need to compare roles and roleplayers
        return this.getTypeId().equals(a2.getTypeId()) && this.getVarNames().equals(a2.getVarNames());
    }

    @Override
    public int hashCode() {
        int hashCode = 1;
        hashCode = hashCode * 37 + this.typeId.hashCode();
        hashCode = hashCode * 37 + getVarNames().hashCode();
        return hashCode;
    }

    @Override
    public boolean isEquivalent(Object obj) {
        if (!(obj instanceof Relation)) return false;
        Relation a2 = (Relation) obj;
        boolean isEquivalent = this.getTypeId().equals(a2.getTypeId());

        //check whether subs correspond to same role players
        Map roleConceptMap = getRoleConceptIdMap();
        Map childRoleConceptMap = a2.getRoleConceptIdMap();
        Iterator it = roleConceptMap.keySet().iterator();
        while(it.hasNext() && isEquivalent){
            RoleType role = it.next();
            isEquivalent = childRoleConceptMap.containsKey(role) &&
                    childRoleConceptMap.get(role).equals(roleConceptMap.get(role));
        }

        return isEquivalent;

    }

    @Override
    public int equivalenceHashCode(){
        int hashCode = 1;
        hashCode = hashCode * 37 + this.typeId.hashCode();
        hashCode = hashCode * 37 + this.getRoleConceptIdMap().hashCode();
        return hashCode;
    }

    @Override
    public boolean isRelation(){ return true;}

    public boolean hasExplicitRoleTypes(){
        boolean rolesDefined = true;
        Iterator it = castings.iterator();
        while (it.hasNext() && rolesDefined)
            rolesDefined = it.next().getRoleType().isPresent();
        return rolesDefined;
    }
    @Override
    public boolean containsVar(String name) {
        boolean varFound = false;
        Iterator it = castings.iterator();
        while(it.hasNext() && !varFound)
            varFound = it.next().getRolePlayer().getName().equals(name);
        return varFound;
    }

    @Override
    public void unify(String from, String to) {
        castings.forEach(c -> {
            String var = c.getRolePlayer().getName();
            if (var.equals(from)) {
                c.getRolePlayer().setName(to);
            }
            else if (var.equals(to)) {
                c.getRolePlayer().setName("captured->" + var);
            }
        });
    }

    @Override
    public void unify (Map mappings) {
        castings.forEach(c -> {
            String var = c.getRolePlayer().getName();
            if (mappings.containsKey(var) ) {
                String target = mappings.get(var);
                c.getRolePlayer().setName(target);
            }
            else if (mappings.containsValue(var)) {
                c.getRolePlayer().setName("captured->" + var);
            }
            });
    }

    @Override
    public Set getVarNames(){
        Set vars = new HashSet<>();
        castings.forEach(c -> vars.add(c.getRolePlayer().getName()));
        return vars;
    }

    @Override
    public String getVal(){
        throw new IllegalAccessError(ErrorMessage.NO_VAL_IN_RELATION.getMessage());
    }

    /**
     * Attempts to infer the implicit roleTypes of vars in a relAtom
     * @return map containing a varName - varType, varRoleType triple
     */
    public Map> getVarTypeRoleMap() {
        Map> roleVarTypeMap = new HashMap<>();
        if (getParentQuery() == null) return roleVarTypeMap;

        MindmapsGraph graph =  getParentQuery().getGraph().orElse(null);
        String relTypeId = getTypeId();
        Set vars = getVarNames();
        Map varTypeMap = getParentQuery().getVarTypeMap();

        for (String var : vars) {
            Type type = varTypeMap.get(var);
            String roleTypeId = "";
            for(VarAdmin.Casting c : castings) {
                if (c.getRolePlayer().getName().equals(var))
                    roleTypeId = c.getRoleType().flatMap(VarAdmin::getId).orElse("");
            }
            //roletype explicit
            if (!roleTypeId.isEmpty())
                roleVarTypeMap.put(var, new Pair<>(type, graph.getRoleType(roleTypeId)));
            else {
                if (type != null) {
                    Set cRoles = getCompatibleRoleTypes(type.getId(), relTypeId, getParentQuery().getGraph().orElse(null));

                    //if roleType is unambigous
                    if (cRoles.size() == 1)
                        roleVarTypeMap.put(var, new Pair<>(type, cRoles.iterator().next()));
                    else
                        roleVarTypeMap.put(var, new Pair<>(type, null));

                }
            }
        }
        return roleVarTypeMap;
    }

    /**
     * Attempts to infer the implicit roleTypes and matching types based on contents of the parent query
     * @return map containing a RoleType-Type pair
     */
    public Map> getRoleVarTypeMap() {
        Map> roleVarTypeMap = new HashMap<>();

        if (getParentQuery() == null) return roleVarTypeMap;


        MindmapsGraph graph =  getParentQuery().getGraph().orElse(null);
        Map varTypeMap = getParentQuery().getVarTypeMap();
        Set allocatedVars = new HashSet<>();
        Set allocatedRoles = new HashSet<>();

        castings.forEach( c -> {
            String var = c.getRolePlayer().getName();
            String roleTypeId = c.getRoleType().flatMap(VarAdmin::getId).orElse("");
            Type type = varTypeMap.get(var);
            if (!roleTypeId.isEmpty()) {
                RoleType role = graph.getRoleType(roleTypeId);
                roleVarTypeMap.put(role, new Pair<>(var, type));
                allocatedVars.add(var);
                allocatedRoles.add(role);
            }
        });

        String relTypeId = getTypeId();
        Set varsToAllocate = getVarNames();
        varsToAllocate.removeAll(allocatedVars);
        for (String var : varsToAllocate) {
            Type type = varTypeMap.get(var);

            if (type != null) {
                Set cRoles = getCompatibleRoleTypes(type.getId(), relTypeId, graph);
                //if roleType is unambigous
                if (cRoles.size() == 1) {
                    RoleType role = cRoles.iterator().next();
                    roleVarTypeMap.put(role, new Pair<>(var, type));
                    allocatedVars.add(var);
                    allocatedRoles.add(role);
                }
            }
        }

        Collection rolesToAllocate = graph.getRelationType(getTypeId()).hasRoles();
        rolesToAllocate.removeAll(allocatedRoles);
        varsToAllocate.removeAll(allocatedVars);
        if (rolesToAllocate.size() == 1 && varsToAllocate.size() == 1) {
            RoleType role = rolesToAllocate.iterator().next();
            String var = varsToAllocate.iterator().next();
            Type type = varTypeMap.get(var);
            roleVarTypeMap.put(role, new Pair<>(var, type));
        }

        return roleVarTypeMap;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy