/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package fasp;
import csp.backends.TailorSolver;
import csp.convertors.FuzzyToIntegerConvertor;
import csp.datatypes.CSPSolution;
import expressions.DoubleNegationEliminator;
import expressions.FuzzyExpression;
import fasp.datatypes.*;
import fasp.datatypes.FaspConstant;
import fasp.datatypes.GroundLiteral;
import fasp.parser.parsers.LiteralParser;
import fasp.parser.tokenizer.TokenState;
import finiteReduction.DomainFinder;
import finiteReduction.FiniteReductionConfig;
import fuzzysat.FuzzyClause;
import fuzzysat.FuzzyLiteral;
import fuzzysat.Literal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import operators.MultiOperator;
import operators.N;
import operators.NM;
import operators.TM;
import operators.TW;
import operators.UnaryOperator;
import util.Pair;
/**
*
* @author Jeroen Janssen <Jeroen.Janssen@vub.ac.be>
*/
public class TPLPProgram {
public static final int MAXNODES = 10;
public static final int NROFTESTS = 1;
public static final double THRESHOLD = 0.0;
public static void main(String[] args) throws Exception {
// Constant definitions
String[] townStrings = {"t1", "t2", "t3"};
//String[] townStrings = {"t1","t2"};
//String[] atmStrings = {"a1", "a2"};
String[] atmStrings = {"a1"};
Map<Pair<String, String>, Double> distances = new HashMap<Pair<String, String>, Double>();
distances.put(new Pair<String, String>("t1", "t2"), 0.8);
distances.put(new Pair<String, String>("t2", "t1"), 0.8);
//distances.put(new Pair<String, String>("t1", "t3"), 0.7);
distances.put(new Pair<String, String>("t1", "t3"), 0.6);
//distances.put(new Pair<String, String>("t3", "t1"), 0.7);
distances.put(new Pair<String, String>("t3", "t1"), 0.6);
//distances.put(new Pair<String, String>("t2", "t3"), 0.5);
//distances.put(new Pair<String, String>("t2", "t3"), 0.4);
//distances.put(new Pair<String, String>("t3", "t2"), 0.5);
//distances.put(new Pair<String, String>("t3", "t2"), 0.4);
//distances.put(new Pair<String, String>("t1", "t1"), 1.0);
//distances.put(new Pair<String, String>("t2", "t2"), 1.0);
//distances.put(new Pair<String, String>("t3", "t3"), 1.0);
//distances.put(new Pair<String,String>("t1","t2"),0.7);
//distances.put(new Pair("t2","t1"),0.7);
TestData data = runTest(townStrings, atmStrings, distances, THRESHOLD);
if (data != null) {
if (data.answerSet != null) {
System.out.println(data.toString());
} else {
System.out.println("No answer set found.");
}
} else {
System.out.println("No solution");
}
// ArrayList<ArrayList<Long>> timings = new ArrayList<ArrayList<Long>>();
// for (int i = 0; i < MAXNODES; i++) {
// timings.add(i, new ArrayList<Long>());
// timings.get(i).add(Double.doubleToLongBits(0.0));
// }
// ArrayList<ArrayList<Long>> avgTimings = new ArrayList<ArrayList<Long>>();
// for (int i = 0; i < MAXNODES; i++) {
// avgTimings.add(i, new ArrayList<Long>());
// avgTimings.get(i).add(Double.doubleToLongBits(0.0));
// }
// ArrayList<Long> medianTimings = new ArrayList<Long>();
// ArrayList<ArrayList<Integer>> loops = new ArrayList<ArrayList<Integer>>();
// for (int i = 0; i < MAXNODES; i++) {
// loops.add(i, new ArrayList<Integer>());
// loops.get(i).add(0);
// }
// ArrayList<Integer> avgLoops = new ArrayList<Integer>();
// ArrayList<Integer> medianLoops = new ArrayList<Integer>();
//
// // For nodesizes 3-20 of graphs
// for (int i = 3; i <= MAXNODES; i++) {
// int j = 0;
// while (j < NROFTESTS) {
// System.out.println("***************");
// // Generate a random graph with the right degree for each vertex
// GCProblemInstance inst = generateGCProblemInstance(i, i / 2);
// System.out.println("#nodes=" + i + ",#test=" + j);
// System.out.println(inst);
// long preTime = System.currentTimeMillis();
// TestData result = runTest(inst.townStrings, inst.atmStrings,
// inst.distances, THRESHOLD);
// long time = System.currentTimeMillis() - preTime;
// if (result.answerSet != null) {
// System.out.println("Found result");
// timings.get(i).add(j, time);
// loops.get(i).add(j, result.nrOfLoops);
// Long avgTime = Double.doubleToLongBits(0.0);
// for (int k = 0; k <= j; k++) {
// avgTime += timings.get(i).get(k) / timings.get(i).size();
// }
// avgTimings.get(i).add(j, avgTime);
// int tempAvgLoops = 0;
// for (int k = 0; k < j; k++) {
// tempAvgLoops += loops.get(i).get(k) / loops.get(i).size();
// }
// avgLoops.add(j, tempAvgLoops);
// //System.out.println(inst);
// System.out.println("time: " + time);
// System.out.println("loopsNeed: " + result.nrOfLoops);
// System.out.println(result.answerSet);
// //System.out.println(result.prog);
// System.out.println("---------------");
// System.out.println("Avg time: " + avgTimings.get(j));
// System.out.println("Avg loops: " + avgLoops.get(j));
// System.out.println("***************");
// j++;
// }
// }
// }
}
public static class GCProblemInstance {
String[] townStrings;
String[] atmStrings;
// Actually these are the nearness degrees.
Map<Pair<String, String>, Double> distances;
public GCProblemInstance(String[] townStrings, String[] atmStrings,
Map<Pair<String, String>, Double> distances) {
this.townStrings = townStrings;
this.atmStrings = atmStrings;
this.distances = distances;
}
public String[] getTownStrings() {
return townStrings;
}
public String[] getAtmStrings() {
return atmStrings;
}
public Map<Pair<String, String>, Double> getDistances() {
return distances;
}
public String toString() {
StringBuffer buff = new StringBuffer();
//buff.append("*****************\n");
buff.append("#towns: " + getTownStrings().length + "\n");
buff.append("#atms: " + getAtmStrings().length + "\n");
buff.append("#edges: " + distances.size() + "\n");
buff.append("distances: " + distances.toString() + "\n");
//buff.append("*****************\n");
return buff.toString();
}
}
public static GCProblemInstance generateGCProblemInstance(int nrOfNodes, int nrOfAtms) {
// Generates a dense graph, i.e. #edges < n*log n, with n = #vertices
// Assumes nrOfNodes >=2
// Init
String[] townStrings = new String[nrOfNodes];
String[] atmStrings = new String[nrOfAtms];
Map<Pair<String, String>, Double> distances = new HashMap<Pair<String, String>, Double>();
for (int i = 0; i < nrOfNodes; i++) {
townStrings[i] = "t" + i;
}
for (int i = 0; i < nrOfAtms; i++) {
atmStrings[i] = "a" + i;
}
for (int i = 0; i < nrOfNodes; i++) {
distances.put(new Pair<String, String>(townStrings[i], townStrings[i]), 1.0);
}
// Create edges
// We create between 3/4*(n*log n) and n*log n edges
// And always connect t0 with t1
//Random rand = new Random(12345);
Random rand = new Random();
// Lowest nearness degree is 0.5
int initDist = 9 - rand.nextInt(4);
distances.put(new Pair<String, String>("t0", "t1"), Double.parseDouble("0." + initDist));
distances.put(new Pair<String, String>("t1", "t0"), Double.parseDouble("0." + initDist));
List<String> addedNodes = new ArrayList<String>();
addedNodes.add("t0");
addedNodes.add("t1");
/*int maxNrOfEdges = (int) Math.log(nrOfNodes);
int cutoff = rand.nextInt(maxNrOfEdges / 8 < 1 ? 1 : maxNrOfEdges / 2);*/
// Complete graph has (n*n-n)/2 edges, hence this is max
int maxNrOfEdges = (nrOfNodes * nrOfNodes - nrOfNodes) / 2;
int minNrOfEdges = (int) Math.log(nrOfNodes);
int cutoff = 0;
// We already added the nearness for each node and the nearness for
// t0 and t1\
// FIXME: there can be disconnected nodes, which is not wanted as then no
// proper solution exists!!
// 1. Initialization: connect each free node to some node in the graph
for (int i = 2; i < nrOfNodes; i++) {
String selectTown1 = townStrings[i];
String selectTown2 = addedNodes.get(rand.nextInt(addedNodes.size()));
if (!distances.containsKey(new Pair<String, String>(selectTown1, selectTown2))) {
Double distance = Double.parseDouble("0." + (9 - rand.nextInt(4)));
distances.put(new Pair<String, String>(selectTown1, selectTown2), distance);
distances.put(new Pair<String, String>(selectTown2, selectTown1), distance);
addedNodes.add(selectTown1);
}
}
int nrOfAddedEdges = distances.size() / 2;
while (nrOfAddedEdges < maxNrOfEdges) {
String selectTown1 = townStrings[rand.nextInt(nrOfNodes)];
String selectTown2 = addedNodes.get(rand.nextInt(addedNodes.size()));
if (!distances.containsKey(new Pair<String, String>(selectTown1, selectTown2))) {
Double distance = Double.parseDouble("0." + rand.nextInt(9 - rand.nextInt(4)));
distances.put(new Pair<String, String>(selectTown1, selectTown2), distance);
distances.put(new Pair<String, String>(selectTown2, selectTown1), distance);
nrOfAddedEdges++;
}
}
return new GCProblemInstance(townStrings, atmStrings, distances);
}
// Helper method
// TODO: integrate in factory or constructors
public static GroundLiteral createLiteral(String name, boolean naf, UnaryOperator nafOp, FaspConstant... args) {
ArrayList<FaspConstant> pargs = new ArrayList<FaspConstant>();
for (FaspConstant c : args) {
pargs.add(c);
}
GroundPredicate p = new GroundPredicate(name, pargs);
return new GroundLiteral(p, false, naf, nafOp);
}
public static GroundLiteral createNafLiteral(String name, UnaryOperator nafOp, FaspConstant... args) {
return createLiteral(name, true, nafOp, args);
}
public static GroundLiteral createRegLiteral(String name, FaspConstant... args) {
return createLiteral(name, false, null, args);
}
public static GroundRule createRegularRule(GroundLiteral head, MultiOperator bodyOp, FaspFuzzyExpression... body) {
ArrayList<FaspFuzzyExpression> bodyElts = new ArrayList<FaspFuzzyExpression>();
for (FaspFuzzyExpression b : body) {
bodyElts.add(b);
}
return new GroundRegularRule(head, bodyElts, bodyOp);
}
// Parse the result of the CSP solver
public static GroundLiteral parseLiteral(String str) throws Exception {
NonGroundLiteral lit = new LiteralParser().parse(new TokenState(str));
Map<FaspVariable, FaspConstant> constMap = new HashMap<FaspVariable, FaspConstant>();
return lit.ground(constMap);
}
public static void printSolution(Map<String, Double> solution) {
for (String k : solution.keySet()) {
System.out.println("(" + k + "," + solution.get(k) + ")");
}
}
public static class TestData {
int nrOfLoops;
FaspInterpretation answerSet;
GroundProgram prog;
public TestData(int nrOfLoops, FaspInterpretation answerSet, GroundProgram prog) {
this.nrOfLoops = nrOfLoops;
this.answerSet = answerSet;
this.prog = prog;
}
public int getNrOfLoops() {
return nrOfLoops;
}
public FaspInterpretation getAnswerSet() {
return answerSet;
}
public GroundProgram getProgram() {
return prog;
}
public String toString() {
StringBuffer buff = new StringBuffer();
buff.append(getProgram().toString());
buff.append("Answer Set:\n");
buff.append(answerSet.toString());
buff.append("#loops: " + getNrOfLoops());
return buff.toString();
}
}
public static TestData runTest(String[] townStrings, String[] atmStrings,
Map<Pair<String, String>, Double> distances, Double threshold) throws Exception {
GroundProgram prog = createProgram(townStrings, atmStrings, distances, threshold);
//System.out.println("Program:");
//System.out.println(prog);
//System.out.println(prog);
//DirectedGraph<GroundLiteral, DefaultEdge> depGraph = prog.getDependencyGraph();
//System.out.println("Size of grounding: "+rules.size()+" rules.");
//List<Literal> comp = prog.createCompletion(1.0);
//System.out.println(clauses);
int defaultBound = 10;
int k = 1;
// long initTime = System.currentTimeMillis();
boolean anssetfound = false;
boolean stillPossible = true;
Map<String, Double> solution = null;
FaspInterpretation i = null;
List<Set<GroundLiteral>> allLoops = new ArrayList<Set<GroundLiteral>>();
List<FuzzyClause> clauses = prog.createCompletion2();
List<FuzzyClause> loopClauses = new ArrayList<FuzzyClause>();
int nrOfLoops = 0;
while (!anssetfound && stillPossible) {
//FuzzySATSolver solver = new IncompleteCSPSolver(clauses, 20, 20);
//FuzzySATSolver solver = new IncompleteCSPSolver(clauses,10,1);
//FuzzySATSolver solver = new IncompleteCSPSolver(clauses,20,2);
Map<String, Integer> boolVars = createBoolVars(townStrings, atmStrings,
distances);
ArrayList<String> varOrders = createVarOrderings(townStrings, atmStrings,
distances);
// System.out.println(boolVars);
//ChocoSolver solver = new ChocoSolver(10);
FuzzyToIntegerConvertor ficonv =
new FuzzyToIntegerConvertor(defaultBound, k);
DoubleNegationEliminator dnegElim = new DoubleNegationEliminator();
ArrayList<FuzzyClause> newClauses = new ArrayList<FuzzyClause>();
for (FuzzyClause c : clauses) {
ArrayList<Literal> newLiterals = new ArrayList<Literal>();
for (Literal l : c.getDisjuncts()) {
FuzzyLiteral flit = (FuzzyLiteral) l;
FuzzyExpression newExp = flit.getExpression().accept(dnegElim);
newLiterals.add(new FuzzyLiteral(flit.getLowerBound(),
flit.getUpperBound(), newExp));
}
newClauses.add(new FuzzyClause(newLiterals));
}
// overwrite the old clauses with the simplified ones ...
clauses = newClauses;
// DEBUG output for checking DoubleNegationEliminator
//System.out.println("After DoubleNegationEliminator");
//for (FuzzyClause c : clauses) {
// System.out.println(c);
//}
// optimization
//HashMap trivialAssignments = new HashMap();
HashMap trivialAssignments = new HashMap();
if (FiniteReductionConfig.optimizeClauses) {
boolean changed = true;
while (changed) {
// System.out.println("...");
DomainFinder.simplify(clauses);
changed = DomainFinder.eliminateTriviallySatisfiableClauses(clauses, trivialAssignments);
//System.out.println("Eliminated trivially satisfiable clause");
}
//System.out.println("Optimized the clauses");
}
for (FuzzyClause c : clauses) {
ficonv.addFuzzyClause(c);
}
//System.out.println("Solver running...");
//solution = solver.getModel();
//solution = solver.getModel(varOrders);
//System.out.println("Solver found a model");
TailorSolver solv = new TailorSolver("/home/jeroen/programming/tailorV0.3.2/tailor.jar",
"/home/jeroen/programming/minion-0.10/bin/minion");
solv.read(ficonv.convertToCSPProblem());
System.out.println("Ok, read file. Now solving ...");
CSPSolution cspSolution = solv.solve();
solution = ficonv.convertCSPSolutionToFuzzyModel(cspSolution);
System.out.println("Solving ended!");
if (solution != null) {
solution.putAll(trivialAssignments);
checkModel(clauses, solution);
printSolution(solution);
Map<GroundLiteral, Double> interp = new HashMap<GroundLiteral, Double>();
for (String s : solution.keySet()) {
GroundLiteral lit = parseLiteral(s);
interp.put(lit, solution.get(s));
}
i = new FaspInterpretation(interp);
if (prog.isAnswerSet(i)) {
anssetfound = true;
//System.out.println("Woot! Answer Set!");
} else {
//System.out.println("Model is not an answer set");
//printSolution(solution);
// Find a loop
//System.out.println("Searching loop");
List<Set<GroundLiteral>> loops = prog.findCycles(i);
for (Set<GroundLiteral> loop : loops) {
// For evaluation:
printLoop(loop);
// Compute loop formula
FuzzyClause loopForm = prog.computeLoopFormula2(loop);
// For evaluation:
//System.out.println("Loop formula: " + loopForm);
clauses = prog.createCompletion2();
clauses.add(loopForm);
for (FuzzyClause c : loopClauses) {
clauses.add(c);
}
nrOfLoops++;
//System.out.println(loop);
/*if (allLoops.contains(loop)) {
anssetfound = true;
//System.out.println("ERROR: DOUBLE LOOP!!!");
} else {
allLoops.add(loop);
}*/
}
}
} else {
stillPossible = false;
System.out.println("No solution found!");
}
}
//System.out.println("Solution found!");
if (stillPossible) {
//printSolution(solution);
return new TestData(nrOfLoops, i, prog);
} else {
return new TestData(nrOfLoops, null, prog);
//System.out.println("No answer set exists for this initialization of the solver");
}
}
public static boolean checkModel(List<FuzzyClause> problem, Map<String, Double> model) {
for (FuzzyClause cl : problem) {
if (!cl.isSatisfied(model)) {
System.out.println("WARNING: incorrect model!");
System.out.println(" model = " + model);
System.out.println(" clause = " + cl);
return false;
}
}
return true;
}
public static void printLoop(Set<GroundLiteral> loop) {
System.out.print("Loop: {");
Iterator<GroundLiteral> it = loop.iterator();
if (it.hasNext()) {
System.out.print(it.next());
}
while (it.hasNext()) {
System.out.print("," + it.next());
}
System.out.println("}");
}
private static Map<String, Integer> createBoolVars(String[] townStrings, String[] atmStrings,
Map<Pair<String, String>, Double> distances) {
Map<String, Integer> boolVars = new HashMap<String, Integer>();
ArrayList<FaspConstant> town = new ArrayList<FaspConstant>();
for (String t : townStrings) {
town.add(new FaspConstant(t));
}
ArrayList<FaspConstant> atm = new ArrayList<FaspConstant>();
for (String a : atmStrings) {
atm.add(new FaspConstant(a));
}
for (FaspConstant a : atm) {
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
// Different to the TPLP paper:
if (!t1.equals(t2)) {
GroundLiteral head = createRegLiteral("loc", a, t1, t2);
boolVars.put(head.toString(), 1);
}
}
}
}
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
if (distances.containsKey(new Pair<String, String>(t1.toString(),
t2.toString()))) {
boolVars.put(createRegLiteral("conn", t1, t2).toString(), 1);
boolVars.put(createRegLiteral("conn", t2, t1).toString(), 1);
}
}
}
return boolVars;
}
private static ArrayList<String> createVarOrderings(String[] towns, String[] atms,
Map<Pair<String, String>, Double> distances) {
ArrayList<String> varOrder = new ArrayList<String>();
ArrayList<FaspConstant> town = new ArrayList<FaspConstant>();
for (String t : towns) {
town.add(new FaspConstant(t));
}
ArrayList<FaspConstant> atm = new ArrayList<FaspConstant>();
for (String a : atms) {
atm.add(new FaspConstant(a));
}
// 1. Add the near and conn predicates that are given as facts first:
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
if (distances.containsKey(new Pair(t1, t2))) {
varOrder.add(createRegLiteral("near", t1, t2).toString());
varOrder.add(createRegLiteral("near", t2, t1).toString());
varOrder.add(createRegLiteral("conn", t1, t2).toString());
varOrder.add(createRegLiteral("conn", t2, t1).toString());
}
}
}
// 2. Add the loc predicates
for (FaspConstant a : atm) {
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
varOrder.add(createRegLiteral("loc", a, t1, t2).toString());
varOrder.add(createRegLiteral("loc", a, t2, t1).toString());
}
}
}
// 3. Add the near' and near predicates
for (FaspConstant a : atm) {
for (FaspConstant t : town) {
varOrder.add(createRegLiteral("locNear2", a, t).toString());
varOrder.add(createRegLiteral("locNear", a, t).toString());
}
}
// 4. Add the atmNear predicates
for (FaspConstant a : atm) {
for (FaspConstant t : town) {
varOrder.add(createRegLiteral("atmNear", a, t).toString());
}
}
// 5. Add the nearestAtm predicate
for (FaspConstant t : town) {
varOrder.add(createRegLiteral("nearestAtm", t).toString());
}
// 6. Add the totNear predicate
varOrder.add(createRegLiteral("totNear").toString());
return varOrder;
}
public static GroundProgram createProgram(String[] towns, String[] atms,
Map<Pair<String, String>, Double> distances, Double k) {
// Town and ATM definitions
ArrayList<FaspConstant> town = new ArrayList<FaspConstant>();
for (String t : towns) {
town.add(new FaspConstant(t));
}
ArrayList<FaspConstant> atm = new ArrayList<FaspConstant>();
for (String a : atms) {
atm.add(new FaspConstant(a));
}
// Program
ArrayList<GroundRule> rules = new ArrayList<GroundRule>();
// Distance and connection facts
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
if (distances.containsKey(new Pair<String, String>(t1.getName(), t2.getName()))) {
GroundLiteral headd = createRegLiteral("near", t1, t2);
GroundLiteral headc = createRegLiteral("conn", t1, t2);
GroundRule factd = createRegularRule(headd, new TW(),
new LattVal(distances.get(new Pair<String, String>(t1.getName(), t2.getName()))));
GroundRule factc = createRegularRule(headc, new TW(), new LattVal(1.0));
rules.add(factd);
rules.add(factc);
}
}
}
// gloc rule
for (FaspConstant a : atm) {
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
// Different to the TPLP paper:
if (!t1.equals(t2)) {
GroundLiteral head = createRegLiteral("loc", a, t1, t2);
GroundLiteral bodyl = createRegLiteral("conn", t1, t2);
ArrayList<FaspFuzzyExpression> body = new ArrayList<FaspFuzzyExpression>();
body.add(bodyl);
for (FaspConstant tt1 : town) {
for (FaspConstant tt2 : town) {
if (!(((t1.equals(tt1)) && (t2.equals(tt2))) || ((t1.equals(tt2))
|| (t2.equals(tt1))))
&& (!tt1.equals(tt2))) {
GroundLiteral betaLit = createLiteral("loc", true, new NM(), a, tt1, tt2);
body.add(betaLit);
}
}
}
GroundRule locRule = new GroundRegularRule(head, body, new TW());
rules.add(locRule);
}
}
}
}
// gnear rule
for (FaspConstant a : atm) {
for (FaspConstant t : town) {
// Why doesn't Java just support new ArrayList<FaspConstant>({a,t}) ?
GroundLiteral head = createLiteral("locNear", false, null, a, t);
GroundLiteral bodyElt = createLiteral("locNear2", true, new N(), a, t);
GroundRule gnear = createRegularRule(head, new TW(), bodyElt);
rules.add(gnear);
}
}
// gnear' rule
for (FaspConstant a : atm) {
for (FaspConstant t1 : town) {
GroundLiteral head = createLiteral("locNear2", false, null, a, t1);
for (FaspConstant t2 : town) {
GroundLiteral b1 = createRegLiteral("loc", a, t1, t2);
GroundLiteral b2 = createNafLiteral("near", new N(), t1, t2);
GroundLiteral b3 = createRegLiteral("locNear", a, t2);
GroundRule gnearP = createRegularRule(head, new TW(), b1, b2, b3);
rules.add(gnearP);
}
}
}
// nearr rule
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
GroundLiteral head = createRegLiteral("near", t1, t2);
for (FaspConstant t3 : town) {
GroundLiteral b1 = createRegLiteral("conn", t1, t3);
GroundLiteral b2 = createRegLiteral("near", t1, t3);
GroundLiteral b3 = createRegLiteral("near", t3, t2);
GroundRule nearr = createRegularRule(head, new TW(), b1, b2, b3);
rules.add(nearr);
}
}
}
// locr rule
for (FaspConstant a : atm) {
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
// Small optimization
if (!t1.equals(t2)) {
GroundLiteral head = createRegLiteral("loc", a, t1, t2);
GroundLiteral body = createRegLiteral("loc", a, t2, t1);
GroundRule locr = createRegularRule(head, new TW(), body);
rules.add(locr);
}
}
}
}
// atmr rule
for (FaspConstant a : atm) {
for (FaspConstant t : town) {
//GroundLiteral head = createRegLiteral("isNear", a, t);
GroundLiteral head = createRegLiteral("atmNear", a, t);
for (FaspConstant t1 : town) {
for (FaspConstant t2 : town) {
GroundLiteral b1 = createRegLiteral("loc", a, t1, t2);
GroundLiteral b2 = createRegLiteral("locNear", a, t1);
GroundLiteral b3 = createRegLiteral("near", t, t1);
GroundRule atmr = createRegularRule(head, new TW(), b1, b2, b3);
rules.add(atmr);
}
}
}
}
// nearestAtm rule
for (FaspConstant t : town) {
GroundLiteral head = createRegLiteral("nearestAtm", t);
for (FaspConstant a : atm) {
GroundLiteral b = createRegLiteral("atmNear", a, t);
GroundRule nearestAtm = createRegularRule(head, new TW(), b);
rules.add(nearestAtm);
}
}
// tDist rule
GroundLiteral tDistHead = createRegLiteral("totNear");
ArrayList<FaspFuzzyExpression> tDistBody = new ArrayList<FaspFuzzyExpression>();
for (FaspConstant a : atm) {
for (FaspConstant t : town) {
tDistBody.add(createRegLiteral("atmNear", a, t));
}
}
GroundRule tDistRule = new GroundRegularRule(tDistHead, tDistBody, new TM());
rules.add(tDistRule);
/*GroundLiteral tDistHead = createRegLiteral("totNear");
ArrayList<FaspFuzzyExpression> tDistBody = new ArrayList<FaspFuzzyExpression>();
for (FaspConstant t : town) {
tDistBody.add(createRegLiteral("nearestAtm",t));
}
GroundRule tDistRule = new GroundRegularRule(tDistHead,tDistBody, new TM());
rules.add(tDistRule);*/
// constraint rule
ArrayList<FaspFuzzyExpression> constrBody = new ArrayList<FaspFuzzyExpression>();
constrBody.add(createNafLiteral("totNear", new N()));
// We use 1-k because constraint (1-k) <- (1-totNear) means
// 1-k >= 1-totNear, hence k <= totNear
rules.add(new GroundRegularConstraint(new LattVal(1 - k), constrBody, new TW()));
// Print the grounded program
/*for (GroundRule r : rules) {
System.out.println(r);
}*/
return new GroundProgram(rules);
}
}