use of ai.grakn.graql.admin.RelationPlayer in project grakn by graknlabs.
the class RelationshipAtom method rewriteWithVariableRoles.
/**
* if any {@link Role} variable of the parent is user defined rewrite ALL {@link Role} variables to user defined (otherwise unification is problematic)
* @param parentAtom parent atom that triggers rewrite
* @return new relation atom with user defined {@link Role} variables if necessary or this
*/
private RelationshipAtom rewriteWithVariableRoles(Atom parentAtom) {
if (!parentAtom.requiresRoleExpansion())
return this;
VarPattern relVar = getPattern().admin().getProperty(IsaProperty.class).map(prop -> getVarName().isa(prop.type())).orElse(getVarName());
for (RelationPlayer rp : getRelationPlayers()) {
VarPatternAdmin rolePattern = rp.getRole().orElse(null);
if (rolePattern != null) {
Var roleVar = rolePattern.var();
Label roleLabel = rolePattern.getTypeLabel().orElse(null);
relVar = relVar.rel(roleVar.asUserDefined().label(roleLabel), rp.getRolePlayer());
} else {
relVar = relVar.rel(rp.getRolePlayer());
}
}
return create(relVar.admin(), getPredicateVariable(), getTypeId(), getParentQuery());
}
use of ai.grakn.graql.admin.RelationPlayer in project grakn by graknlabs.
the class RelationshipAtom method getMultiUnifier.
@Override
public MultiUnifier getMultiUnifier(Atom pAtom, UnifierComparison unifierType) {
Unifier baseUnifier = super.getUnifier(pAtom);
Set<Unifier> unifiers = new HashSet<>();
if (pAtom.isRelation()) {
// This is safe due to the check above
assert (pAtom instanceof RelationshipAtom);
RelationshipAtom parentAtom = (RelationshipAtom) pAtom;
// this is important for cases like unifying ($r1: $x, $r2: $y) with itself
if (this.equals(parentAtom) && this.getPartialSubstitutions().collect(toSet()).equals(parentAtom.getPartialSubstitutions().collect(toSet())) && this.getTypeConstraints().collect(toSet()).equals(parentAtom.getTypeConstraints().collect(toSet()))) {
return new MultiUnifierImpl();
}
boolean unifyRoleVariables = parentAtom.getRelationPlayers().stream().map(RelationPlayer::getRole).flatMap(CommonUtil::optionalToStream).anyMatch(rp -> rp.var().isUserDefinedName());
getRelationPlayerMappings(parentAtom, unifierType).forEach(mappingList -> {
Multimap<Var, Var> varMappings = HashMultimap.create();
mappingList.forEach(rpm -> {
// add role player mapping
varMappings.put(rpm.getKey().getRolePlayer().var(), rpm.getValue().getRolePlayer().var());
// add role var mapping if needed
VarPattern childRolePattern = rpm.getKey().getRole().orElse(null);
VarPattern parentRolePattern = rpm.getValue().getRole().orElse(null);
if (parentRolePattern != null && childRolePattern != null && unifyRoleVariables) {
varMappings.put(childRolePattern.admin().var(), parentRolePattern.admin().var());
}
});
unifiers.add(baseUnifier.merge(new UnifierImpl(varMappings)));
});
} else {
unifiers.add(baseUnifier);
}
return new MultiUnifierImpl(unifiers);
}
use of ai.grakn.graql.admin.RelationPlayer in project grakn by graknlabs.
the class RelationshipAtom method inferRoles.
/**
* attempt to infer role types of this relation and return a fresh relationship with inferred role types
* @return either this if nothing/no roles can be inferred or fresh relation with inferred role types
*/
private RelationshipAtom inferRoles(Answer sub) {
// return if all roles known and non-meta
List<Role> explicitRoles = getExplicitRoles().collect(Collectors.toList());
Map<Var, Type> varTypeMap = getParentQuery().getVarTypeMap(sub);
boolean allRolesMeta = explicitRoles.stream().allMatch(role -> Schema.MetaSchema.isMetaLabel(role.getLabel()));
boolean roleRecomputationViable = allRolesMeta && (!sub.isEmpty() || !Sets.intersection(varTypeMap.keySet(), getRolePlayers()).isEmpty());
if (explicitRoles.size() == getRelationPlayers().size() && !roleRecomputationViable)
return this;
GraknTx graph = getParentQuery().tx();
Role metaRole = graph.admin().getMetaRole();
List<RelationPlayer> allocatedRelationPlayers = new ArrayList<>();
RelationshipType relType = getSchemaConcept() != null ? getSchemaConcept().asRelationshipType() : null;
// explicit role types from castings
List<RelationPlayer> inferredRelationPlayers = new ArrayList<>();
getRelationPlayers().forEach(rp -> {
Var varName = rp.getRolePlayer().var();
VarPatternAdmin rolePattern = rp.getRole().orElse(null);
if (rolePattern != null) {
Label roleLabel = rolePattern.getTypeLabel().orElse(null);
// allocate if variable role or if label non meta
if (roleLabel == null || !Schema.MetaSchema.isMetaLabel(roleLabel)) {
inferredRelationPlayers.add(RelationPlayer.of(rolePattern, varName.admin()));
allocatedRelationPlayers.add(rp);
}
}
});
// remaining roles
// role types can repeat so no matter what has been allocated still the full spectrum of possibilities is present
// TODO make restrictions based on cardinality constraints
Set<Role> possibleRoles = relType != null ? relType.relates().collect(toSet()) : inferPossibleTypes(sub).stream().filter(Concept::isRelationshipType).map(Concept::asRelationshipType).flatMap(RelationshipType::relates).collect(toSet());
// possible role types for each casting based on its type
Map<RelationPlayer, Set<Role>> mappings = new HashMap<>();
getRelationPlayers().stream().filter(rp -> !allocatedRelationPlayers.contains(rp)).forEach(rp -> {
Var varName = rp.getRolePlayer().var();
Type type = varTypeMap.get(varName);
mappings.put(rp, top(type != null ? compatibleRoles(type, possibleRoles) : possibleRoles));
});
// allocate all unambiguous mappings
mappings.entrySet().stream().filter(entry -> entry.getValue().size() == 1).forEach(entry -> {
RelationPlayer rp = entry.getKey();
Var varName = rp.getRolePlayer().var();
Role role = Iterables.getOnlyElement(entry.getValue());
VarPatternAdmin rolePattern = Graql.var().label(role.getLabel()).admin();
inferredRelationPlayers.add(RelationPlayer.of(rolePattern, varName.admin()));
allocatedRelationPlayers.add(rp);
});
// fill in unallocated roles with metarole
getRelationPlayers().stream().filter(rp -> !allocatedRelationPlayers.contains(rp)).forEach(rp -> {
Var varName = rp.getRolePlayer().var();
VarPatternAdmin rolePattern = rp.getRole().orElse(null);
rolePattern = rolePattern != null ? rolePattern.var().label(metaRole.getLabel()).admin() : Graql.var().label(metaRole.getLabel()).admin();
inferredRelationPlayers.add(RelationPlayer.of(rolePattern, varName.admin()));
});
VarPattern relationPattern = relationPattern(getVarName(), inferredRelationPlayers);
VarPatternAdmin newPattern = (isDirect() ? relationPattern.directIsa(getPredicateVariable()) : relationPattern.isa(getPredicateVariable())).admin();
return create(newPattern, getPredicateVariable(), getTypeId(), getParentQuery());
}
use of ai.grakn.graql.admin.RelationPlayer in project grakn by graknlabs.
the class RelationshipAtom method relationPattern.
/**
* construct a $varName (rolemap) isa $typeVariable relation
* @param varName variable name
* @param relationPlayers list of rolePlayer-roleType mappings
* @return corresponding {@link VarPatternAdmin}
*/
private VarPattern relationPattern(Var varName, List<RelationPlayer> relationPlayers) {
VarPattern var = varName;
for (RelationPlayer rp : relationPlayers) {
VarPatternAdmin rolePattern = rp.getRole().orElse(null);
var = rolePattern != null ? var.rel(rolePattern, rp.getRolePlayer()) : var.rel(rp.getRolePlayer());
}
return var.admin();
}
use of ai.grakn.graql.admin.RelationPlayer in project grakn by graknlabs.
the class RelationshipProperty method mapToAtom.
@Override
public Atomic mapToAtom(VarPatternAdmin var, Set<VarPatternAdmin> vars, ReasonerQuery parent) {
// set varName as user defined if reified
// reified if contains more properties than the RelationshipProperty itself and potential IsaProperty
boolean isReified = var.getProperties().filter(prop -> !RelationshipProperty.class.isInstance(prop)).anyMatch(prop -> !AbstractIsaProperty.class.isInstance(prop));
VarPattern relVar = isReified ? var.var().asUserDefined() : var.var();
for (RelationPlayer rp : relationPlayers()) {
VarPattern rolePattern = rp.getRole().orElse(null);
VarPattern rolePlayer = rp.getRolePlayer();
if (rolePattern != null) {
Var roleVar = rolePattern.admin().var();
// look for indirect role definitions
IdPredicate roleId = getUserDefinedIdPredicate(roleVar, vars, parent);
if (roleId != null) {
Concept concept = parent.tx().getConcept(roleId.getPredicate());
if (concept != null) {
if (concept.isRole()) {
Label roleLabel = concept.asSchemaConcept().getLabel();
rolePattern = roleVar.label(roleLabel);
} else {
throw GraqlQueryException.nonRoleIdAssignedToRoleVariable(var);
}
}
}
relVar = relVar.rel(rolePattern, rolePlayer);
} else
relVar = relVar.rel(rolePlayer);
}
// isa part
AbstractIsaProperty isaProp = var.getProperty(AbstractIsaProperty.class).orElse(null);
IdPredicate predicate = null;
// if no isa property present generate type variable
Var typeVariable = isaProp != null ? isaProp.type().var() : Graql.var();
// Isa present
if (isaProp != null) {
VarPatternAdmin isaVar = isaProp.type();
Label label = isaVar.getTypeLabel().orElse(null);
if (label != null) {
predicate = IdPredicate.create(typeVariable, label, parent);
} else {
typeVariable = isaVar.var();
predicate = getUserDefinedIdPredicate(typeVariable, vars, parent);
}
}
ConceptId predicateId = predicate != null ? predicate.getPredicate() : null;
relVar = isaProp instanceof DirectIsaProperty ? relVar.directIsa(typeVariable.asUserDefined()) : relVar.isa(typeVariable.asUserDefined());
return RelationshipAtom.create(relVar.admin(), typeVariable, predicateId, parent);
}
Aggregations