public TreeMap<Comparable, TreeSet<Comparable>> reduction() {
        // compute the reducible elements
        TreeMap red = this.getReducibleElements();
        // collect elements implied by nothing
        TreeSet<Comparable> truth = this.closure(new TreeSet<Comparable>());
        // modify each rule
        for (Object x : red.keySet()) {
            TreeSet<Rule> rules = this.getRules();
            rules = (TreeSet<Rule>) rules.clone();
            for (Rule r : rules) {
                Rule r2 = new Rule();
                boolean modif = false;
                // replace the reducible element by its equivalent in the premise
                TreeSet premise = r.getPremise();
                premise = (TreeSet) premise.clone();
                if (premise.contains(x)) {
                    premise.remove(x);
                    premise.addAll((TreeSet) red.get(x));
                    r2.addAllToPremise(premise);
                    modif = true;
                } else {
                    r2.addAllToPremise(premise);
                }
                // replace the reducible element by its equivalent in the conclusion
                TreeSet conclusion = r.getConclusion();
                conclusion = (TreeSet) conclusion.clone();
                if (conclusion.contains(x)) {
                    conclusion.remove(x);
                    conclusion.addAll((TreeSet) red.get(x));
                    r2.addAllToConclusion(conclusion);
                    modif = true;
                } else {
                    r2.addAllToConclusion(conclusion);
                }
                // replace the rule if modified
                if (modif) {
                    if (truth.containsAll(r2.getConclusion())) {
                        this.removeRule(r); // Conclusions of this rule are always true, thus the rule is useless
                    } else {
                        this.replaceRule(r, r2);
                    }
                } else {
                    if (truth.containsAll(r.getConclusion())) {
                        this.removeRule(r); // Conclusions of this rule are always true, thus the rule is useless
                    }
                }
            }
            // remove the reducible elements from the elements set
            this.deleteElement((Comparable) x);
        }
        return red;
    }