
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