/**
*
*/
package xhail.core.terms;
import java.util.AbstractMap.SimpleEntry;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import xhail.core.statements.ModeB;
import xhail.core.statements.ModeH;
import xhail.core.terms.Placemarker.Type;
/**
* @author stefano
*
*/
/**
* @author stefano
*
*/
public interface SchemeTerm {
public static Map<Atom, Collection<Term>> generateAndOutput(Scheme scheme, Collection<Term> substitutes, Map<SchemeTerm, Set<Atom>> table,
Collection<Atom> facts) {
if (null == scheme)
throw new IllegalArgumentException(
"Illegal 'scheme' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>, Collection<Atom>): "
+ scheme);
if (null == substitutes)
throw new IllegalArgumentException(
"Illegal 'substitutes' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>, Collection<Atom>): "
+ substitutes);
if (null == table)
throw new IllegalArgumentException(
"Illegal 'table' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>, Collection<Atom>): "
+ table);
if (null == facts)
throw new IllegalArgumentException(
"Illegal 'facts' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>, Collection<Atom>): "
+ facts);
Map<Atom, Collection<Term>> generated = generateAndOutput(scheme, substitutes, table);
Map<Atom, Collection<Term>> result = new HashMap<>();
for (Atom atom : generated.keySet()) {
// System.err.println(atom);
if (!facts.contains(atom))
result.put(atom, generated.get(atom));
}
return result;
}
public static Map<Atom, Collection<Term>> generateAndOutput(Scheme scheme, Collection<Term> substitutes, Map<SchemeTerm, Set<Atom>> table) {
if (null == scheme)
throw new IllegalArgumentException(
"Illegal 'scheme' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>): " + scheme);
if (null == substitutes)
throw new IllegalArgumentException(
"Illegal 'substitutes' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>): " + substitutes);
if (null == table)
throw new IllegalArgumentException(
"Illegal 'table' argument in SchemeTerm.generateAndOutput(Scheme, Collection<Term>, Map<SchemeTerm, Set<Atom>>): " + table);
Map<Atom.Builder, Collection<Term>> builders = new HashMap<>();
builders.put(new Atom.Builder(scheme.getIdentifier()), Collections.emptySet());
for (int i = 0; i < scheme.getArity(); i++) {
SchemeTerm schemeterm = scheme.getTerm(i);
Map<Atom.Builder, Collection<Term>> temporary = new HashMap<>();
if (schemeterm instanceof Number) {
for (Atom.Builder builder : builders.keySet()) {
Set<Term> value = new HashSet<>(builders.get(builder));
Atom.Builder key = builder.addTerm((Number) schemeterm);
temporary.put(key, value);
}
} else if (schemeterm instanceof Quotation) {
for (Atom.Builder builder : builders.keySet()) {
Set<Term> value = new HashSet<>(builders.get(builder));
Atom.Builder key = builder.addTerm((Quotation) schemeterm);
temporary.put(key, value);
}
} else if (schemeterm instanceof Placemarker) {
Placemarker placemarker = (Placemarker) schemeterm;
if (Type.INPUT == placemarker.getType()) {
for (Atom.Builder builder : builders.keySet()) {
for (Term substitute : substitutes) {
Set<Term> value = new HashSet<>(builders.get(builder));
Atom.Builder key = builder.clone().addTerm(substitute);
temporary.put(key, value);
}
}
} else {
boolean isOutput = Type.OUTPUT == placemarker.getType();
Collection<Atom> candidates = table.get(placemarker);
for (Atom.Builder builder : builders.keySet()) {
for (Atom candidate : candidates) {
Term utilise;
if (candidate.getIdentifier().equals(placemarker.getIdentifier()) && 1 == candidate.getArity())
utilise = candidate.getTerm(0);
else
utilise = candidate;
Set<Term> value = new HashSet<>(builders.get(builder));
if (isOutput)
value.add(utilise);
Atom.Builder key = builder.clone().addTerm(utilise);
temporary.put(key, value);
}
}
}
} else { // if (schemeterm instanceof Scheme)
Map<Atom, Collection<Term>> returned = generateAndOutput((Scheme) schemeterm, substitutes, table);
for (Atom.Builder builder : builders.keySet()) {
for (Atom atom : returned.keySet()) {
Set<Term> value = new HashSet<>(builders.get(builder));
value.addAll(returned.get(atom));
Atom.Builder key = builder.clone().addTerm(atom);
temporary.put(key, value);
}
}
}
builders = temporary;
}
Map<Atom, Collection<Term>> result = new HashMap<>();
for (Atom.Builder builder : builders.keySet())
result.put(builder.build(), builders.get(builder));
return result;
}
public static Map.Entry<Collection<Atom>, Collection<Term>> matchAndOutput(Scheme scheme, Collection<Atom> atoms, Collection<Term> substitutes) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.matchAndOutput(Scheme, Collection<Atom>, Collection<Term>): " + scheme);
if (null == atoms)
throw new IllegalArgumentException("Illegal 'atoms' argument in SchemeTerm.matchAndOutput(Scheme, Collection<Atom>, Collection<Term>): " + atoms);
if (null == substitutes)
throw new IllegalArgumentException("Illegal 'substitutes' argument in SchemeTerm.matchAndOutput(Scheme, Collection<Atom>, Collection<Term>): "
+ substitutes);
Set<Atom> matches = new HashSet<>();
Set<Term> outputs = new HashSet<>();
for (Atom atom : atoms) {
Collection<Term> output = matchAndOutput(scheme, atom, substitutes);
if (null != output) {
matches.add(atom);
outputs.addAll(output);
}
}
return new SimpleEntry<Collection<Atom>, Collection<Term>>(matches, outputs);
}
public static Collection<Term> matchAndOutput(Scheme scheme, Atom atom, Collection<Term> substitutes) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.matchAndOutput(Scheme, Atom, Collection<Term>): " + scheme);
if (null == atom)
throw new IllegalArgumentException("Illegal 'atom' argument in SchemeTerm.matchAndOutput(Scheme, Atom, Collection<Term>): " + atom);
if (null == substitutes)
throw new IllegalArgumentException("Illegal 'substitutes' argument in SchemeTerm.matchAndOutput(Scheme, Atom, Collection<Term>): " + substitutes);
if (!atom.getIdentifier().equals(scheme.getIdentifier()) || atom.getArity() != scheme.getArity())
return null;
Set<Term> result = new HashSet<>();
for (int i = 0; i < scheme.getArity(); i++) {
SchemeTerm schemeterm = scheme.getTerm(i);
if (schemeterm instanceof Number) {
Term term = atom.getTerm(i);
if (!(term instanceof Number))
return null;
if (((Number) term).getValue() != ((Number) schemeterm).getValue())
return null;
} else if (schemeterm instanceof Quotation) {
Term term = atom.getTerm(i);
if (!(term instanceof Quotation))
return null;
if (((Quotation) term).getContent() == ((Quotation) schemeterm).getContent())
return null;
} else if (schemeterm instanceof Placemarker) {
Placemarker placemarker = (Placemarker) schemeterm;
if (Type.INPUT == placemarker.getType()) {
if (!substitutes.contains(atom.getTerm(i)))
return null;
} else if (Type.OUTPUT == placemarker.getType())
result.add(atom.getTerm(i));
} else if (schemeterm instanceof Scheme) {
Term term = atom.getTerm(i);
if (!(term instanceof Atom))
return null;
Collection<Term> subresult = matchAndOutput((Scheme) schemeterm, (Atom) term, substitutes);
if (null == subresult)
return null;
result.addAll(subresult);
} else
return null;
}
return result;
}
/**
* POSSIBLY NOT NEEDED
*
* @param scheme
* @param atom
* @param substitutes
* @return
*/
public static boolean isMatching(Scheme scheme, Atom atom, Collection<Term> substitutes) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.isMatching(Scheme, Atom, Collection<Term>): " + scheme);
if (null == atom)
throw new IllegalArgumentException("Illegal 'atom' argument in SchemeTerm.isMatching(Scheme, Atom, Collection<Term>): " + atom);
if (null == substitutes)
throw new IllegalArgumentException("Illegal 'substitutes' argument in SchemeTerm.isMatching(Scheme, Atom, Collection<Term>): " + substitutes);
if (!atom.getIdentifier().equals(scheme.getIdentifier()) || atom.getArity() != scheme.getArity())
return false;
for (int i = 0; i < scheme.getArity(); i++) {
SchemeTerm schemeterm = scheme.getTerm(i);
if (schemeterm instanceof Number) {
Term term = atom.getTerm(i);
if (!(term instanceof Number))
return false;
if (((Number) term).getValue() != ((Number) schemeterm).getValue())
return false;
} else if (schemeterm instanceof Quotation) {
Term term = atom.getTerm(i);
if (!(term instanceof Quotation))
return false;
if (((Quotation) term).getContent() == ((Quotation) schemeterm).getContent())
return false;
} else if (schemeterm instanceof Placemarker) {
Placemarker placemarker = (Placemarker) schemeterm;
if (Type.INPUT == placemarker.getType())
if (!substitutes.contains(atom.getTerm(i)))
return false;
} else if (schemeterm instanceof Scheme) {
Term term = atom.getTerm(i);
if (!(term instanceof Atom))
return false;
if (!isMatching((Scheme) schemeterm, (Atom) term, substitutes))
return false;
} else
return false;
}
return true;
}
/**
* POSSIBLY NOT NEEDED
*
* @param scheme
* @param atom
* @return
*/
public static boolean isMatching(Scheme scheme, Atom atom) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.isMatching(Scheme, Atom): " + scheme);
if (null == atom)
throw new IllegalArgumentException("Illegal 'atom' argument in SchemeTerm.isMatching(Scheme, Atom): " + atom);
if (!atom.getIdentifier().equals(scheme.getIdentifier()) || atom.getArity() != scheme.getArity())
return false;
for (int i = 0; i < scheme.getArity(); i++) {
SchemeTerm schemeterm = scheme.getTerm(i);
if (schemeterm instanceof Number) {
Term term = atom.getTerm(i);
if (!(term instanceof Number))
return false;
if (((Number) term).getValue() != ((Number) schemeterm).getValue())
return false;
} else if (schemeterm instanceof Quotation) {
Term term = atom.getTerm(i);
if (!(term instanceof Quotation))
return false;
if (((Quotation) term).getContent() == ((Quotation) schemeterm).getContent())
return false;
} else if (schemeterm instanceof Placemarker) {
} else if (schemeterm instanceof Scheme) {
Term term = atom.getTerm(i);
if (!(term instanceof Atom))
return false;
if (!isMatching((Scheme) schemeterm, (Atom) term))
return false;
} else
return false;
}
return true;
}
public static Map<SchemeTerm, Set<Atom>> lookup(final ModeH[] modeHs, final ModeB[] modeBs, final Collection<Atom> facts) {
if (null == modeHs)
throw new IllegalArgumentException("Illegal 'modeHs' argument in SchemeTerm.getParts(ModeH[], ModeB[], Collection<Atom>): " + modeHs);
if (null == modeBs)
throw new IllegalArgumentException("Illegal 'modeBs' argument in SchemeTerm.getParts(ModeH[], ModeB[], Collection<Atom>): " + modeBs);
if (null == facts)
throw new IllegalArgumentException("Illegal 'facts' argument in SchemeTerm.getParts(ModeH[], ModeB[], Collection<Atom>): " + facts);
Map<SchemeTerm, Set<Atom>> result = new HashMap<>();
for (ModeH mode : modeHs) {
Scheme scheme = mode.getScheme();
result.put(scheme, new HashSet<>());
for (Placemarker placemarker : scheme.getPlacemarkers())
if (!result.containsKey(placemarker))
result.put(placemarker, new HashSet<>());
}
for (ModeB mode : modeBs) {
Scheme scheme = mode.getScheme();
result.put(scheme, new HashSet<>());
for (Placemarker placemarker : scheme.getPlacemarkers())
if (!result.containsKey(placemarker))
result.put(placemarker, new HashSet<>());
}
for (SchemeTerm scheme : result.keySet()) {
Set<Atom> part = result.get(scheme);
for (Atom fact : facts) {
if (SchemeTerm.subsumes(scheme, fact, facts))
part.add(fact);
}
}
return result;
}
public static boolean subsumes(SchemeTerm scheme, Term term, Collection<Atom> facts) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.subsumes(SchemeTerm, Term, Collection<Atom>): " + scheme);
if (null == term)
throw new IllegalArgumentException("Illegal 'term' argument in SchemeTerm.subsumes(SchemeTerm, Term, Collection<Atom>): " + term);
if (null == facts)
throw new IllegalArgumentException("Illegal 'facts' argument in SchemeTerm.subsumes(SchemeTerm, Term, Collection<Atom>): " + facts);
if (scheme instanceof Scheme) {
Scheme current = (Scheme) scheme;
if (!(term instanceof Atom))
return false;
Atom atom = (Atom) term;
if (!atom.getIdentifier().equals(current.getIdentifier()) || atom.getArity() != current.getArity())
return false;
for (int i = 0; i < current.getArity(); i++)
if (!subsumes(current.getTerm(i), atom.getTerm(i), facts))
return false;
return true;
} else if (scheme instanceof Placemarker) {
Placemarker current = (Placemarker) scheme;
if (term instanceof Variable)
return false;
if (facts.contains(new Atom.Builder(current.getIdentifier()).addTerm(term).build()))
return true;
if (term instanceof Atom) {
Atom atom = (Atom) term;
return atom.getIdentifier().equals(current.getIdentifier()) && 1 == atom.getArity();
}
return false;
} else
return false;
}
public static Collection<Term> findSubstitutes(Scheme scheme, Term candidate) {
if (null == scheme)
throw new IllegalArgumentException("Illegal 'scheme' argument in SchemeTerm.findSubstitutes(Scheme, Term): " + scheme);
if (null == candidate)
throw new IllegalArgumentException("Illegal 'candidate' argument in Scheme.findSubstitutes(Scheme, Term): " + candidate);
if (!(candidate instanceof Atom))
return Collections.emptySet();
Atom atom = (Atom) candidate;
if (!atom.getIdentifier().equals(scheme.getIdentifier()) || atom.getArity() != scheme.getArity())
return Collections.emptySet();
Set<Term> result = new HashSet<>();
for (int i = 0; i < scheme.getArity(); i++) {
SchemeTerm term = scheme.getTerm(i);
if (term instanceof Placemarker) {
Placemarker placemarker = (Placemarker) term;
if (placemarker.getType() == Type.INPUT)
result.add(atom.getTerm(i));
} else if (term instanceof Scheme)
result.addAll(findSubstitutes((Scheme) term, atom.getTerm(i)));
}
return result;
}
public Term generalises(Term term, Map<Term, Variable> map);
public Term generalises(Set<Variable> set);
// public Map<Term, Collection<Atom>> matching(Set<Term> usables,
// Map<SchemeTerm, Set<Atom>> parts);
}