def join_empty_heaps(empty1,empty2,candidate,to_remove): join=[] #first join the emptyheap equalities for disj1 in empty1: for disj2 in empty2: aux=list(disj1)+list(disj2) aux=input.join_equalities(aux) aux2=[] for i in aux: aux2.append(input.remove_multiple_occurences(i)) join.append(aux2) # remove candidate if "to_remove" is set if to_remove: join2=[] for disj in join: disj2=[] for i in disj: if candidate in i: i.pop(i.index(candidate)) if not len(i)==1: disj2.append(i) else: disj2.append(i) join2.append(disj2) join=join2 return join
def join_empty_LHS(call,params,new_call2,new_params2,old_call2,old_params2,preds,empty2): # RHS: call + params # new top call: new_call2 + new_params2 # # first we find a mapping of internal parameters from the predicate "call" # to the internal parameters of the predicate "new_call2" # * internal call parameter (preds[call][0]) -> top level params (params) # -> new top level params (new_params2) -> internal new top call parameter (preds[new_call2][0]) # * internal parameter from the call equal to nil are translated into "nil-Xn" internal parameters of the new call call_p_map={} nil_pos=1 for i in range(len(preds[call][0])): if params[i]=="nil": call_p_map[preds[call][0][i]]="nil-X%i"%nil_pos if not ("nil-X%i"%nil_pos in preds[new_call2][0]): raise JoinFailed("JOIN: ERROR: this line should not be accesible") nil_pos=nil_pos+1 elif params[i] in new_params2: call_p_map[preds[call][0][i]]=preds[new_call2][0][new_params2.index(params[i])] elif params[i] in old_params2: # handle the param on which the join is applied if "to_remove was true" (-->this param is not part of new_params2) call_p_map[preds[call][0][i]]=preds[old_call2][0][old_params2.index(params[i])] else: raise JoinFailed("JOIN: ERROR: this line should not be accesible") # map the empty2 inside the rule. if not len(empty2)==1: raise JoinFailed("JOIN: not implemented") # we suppose that the equality contains only a single disjunct # the other situation is not implemented disj=empty2[0] equal=[] for conj in disj: new_conj=[] for x in conj: new_conj.append(preds[old_call2][0][old_params2.index(x)]) if x=="nil": new_conj.append("nil") equal.append(new_conj) equal1=[] for x in equal: equal1.append(input.remove_multiple_occurences(x)) equal1=input.join_equalities(equal1) new_rule_params=preds[new_call2][0] # in the forbid variable, we store parameters, which are checked for the following: # they must be existentially quantified # they must be used only in call and call2 forbid=[] # for each rule create a new rule new_rules=[] for (al,pt,cls,eq) in preds[call][1]: # the system of predicates must be forward connected, so call_p_map[al] must be defined ... alloc=call_p_map[al] # find representatives mapping={} for conj in equal1: if alloc in conj: repres=alloc else: tmp=input.intersect_lists(new_rule_params,conj) if tmp>1: # equality between formal parameters implemented only if they are equal to the allocated node if "nil" in conj: for x in conj: if x=="nil": pass else: if new_params2[new_rule_params.index(x)]=="nil": repres=x else: # add to the forbid to_forbid=new_params2[new_rule_params.index(x)] if not (to_forbid in forbid): forbid.append(to_forbid) else: raise JoinFailed("JOIN: not implemented") elif tmp==1: for p in new_rule_params: if p in conj: repres=dp else: repres=conj[0] for x in conj: mapping[x]=repres # the original rule is translated as folows: # first all variables are translated according to the "all_p_map" # every variable outside all_p_map is translated to an unique new name # second all variables are translated according to the "mapping" new_al=apply_maps(al,call_p_map,mapping,new_params2,0) new_pt=[] for x in pt: new_pt.append(apply_maps(x,call_p_map,mapping,new_params2,0)) new_cls=[] for (call_pred,call_par) in cls: new_call_par=[] for x in call_par: new_call_par.append(apply_maps(x,call_p_map,mapping,new_params2,0)) new_cls.append((call_pred,new_call_par)) new_eq=[] for x in eq: new_eq.append(apply_maps(x,call_p_map,mapping,new_params2,1)) for x in mapping.keys(): if mapping[x]==new_al and (not x in new_eq): new_eq.append(x) # pop alocated node fron the equality list - not needed if new_al in new_eq: new_eq.pop(new_eq.index(new_al)) new_rules.append((new_al,new_pt,new_cls,new_eq)) # add the newly created rules inside preds par,rules=preds[new_call2] rules=rules+new_rules preds[new_call2]=(par,rules) return forbid