public void solveReified(
      JacopSoftConstraintProblem scsp,
      DirectedConstraintGraph dcg,
      HashMap<Constraint, WrappedPrimitiveConstraint> constraintMapper) {
    constraintMap = new HashMap<String, WrappedPrimitiveConstraint>();
    allIndicatorVariables = new ArrayList<BooleanVar>(constraintMapper.size());

    constantOne = new BooleanVar(scsp.getStore(), "constOne", 1, 1);
    constantZero = new BooleanVar(scsp.getStore(), "constZero", 0, 0);
    store = scsp.getStore();

    for (Entry<Constraint, WrappedPrimitiveConstraint> entry : constraintMapper.entrySet()) {
      constraintMap.put(entry.getKey().getName(), entry.getValue());
      allIndicatorVariables.add(entry.getValue().getViolationIndicator());
    }

    IntVar[] vars =
        new IntVar
            [scsp.getVariables().size() + allIndicatorVariables.size() + 3]; // including zero one
    // constants

    if (weighted) {
      for (BooleanVar bv : allIndicatorVariables) {
        bv.weight = Integer.MAX_VALUE / 2;
      }
    }
    vars = allIndicatorVariables.toArray(vars);

    ArrayList<IntVar> classicalVars = new ArrayList<IntVar>(scsp.getVariables());

    for (int i = allIndicatorVariables.size(); i < vars.length - 3; ++i) {
      vars[i] = classicalVars.get(i - allIndicatorVariables.size());
    }
    vars[vars.length - 1] = scsp.getObjective();
    vars[vars.length - 2] = constantZero;
    vars[vars.length - 3] = constantOne;

    search = new DepthFirstSearch<IntVar>();
    search.setPrintInfo(debug);

    select = new InputOrderSelect<IntVar>(store, vars, new IndomainMin<IntVar>());

    if (weighted) {
      select =
          new SimpleSelect<IntVar>(vars, new WeightedDegree<IntVar>(), new IndomainMin<IntVar>());
    }
    // now for the actual enumeration

    objective = scsp.getObjective();
    if (weighted) {
      enumerator = new WeightedViolationDegreeEnumerator(dcg);
    } else {
      enumerator = new ConstraintRelationshipViolationDegreeEnumerator(dcg);
    }

    enumerator.addViolationDegreeListener(this);
    enumerator.enumerate();
  }
  private void notifyHard(MultiSet<String> exploredSet) {
    // exclude all constraints that are in exploredSet from the set of
    // constraints
    // first impose all

    int targetWeight = getWeight(exploredSet);
    if (upperCostBound >= 0 && targetWeight >= upperCostBound) {
      if (debug) {
        System.out.println(
            "Infeasible: Target upper bound "
                + targetWeight
                + " but upper bound for problem is "
                + upperCostBound);
      }
      enumerator.foundSolutionOrInfeasibility();
      wasSolved = false;
      return;
    }

    // System.out.println("Trying ... "+exploredSet + " -> weight: "+targetWeight);
    for (org.jacop.constraints.Constraint c : idToConstraintMap.values()) {
      if (!exploredSet.contains(c.id)) c.impose(store);
    }

    // now exclude the perhaps unnecessary ones
    for (String s : exploredSet) {
      org.jacop.constraints.Constraint c = idToConstraintMap.get(s);
      c.removeConstraint();
    }

    // now do some actual solving

    store.setLevel(store.level + 1);
    boolean result = search.labeling(store, select);

    if (result) {
      wasSolved = true;
      objectiveValue = targetWeight;
      enumerator.foundSolutionOrInfeasibility();

      if (debug) {
        System.out.println("Found a best solution with cost " + targetWeight);
        System.out.println(store);
      }
    }

    store.removeLevel(store.level);
    store.setLevel(store.level - 1);
  }
  public boolean solveHard(JacopSoftConstraintProblem jscsp) {
    solveReified = false;
    idToConstraintMap =
        new HashMap<String, org.jacop.constraints.Constraint>(jscsp.getConstraints().size());
    for (org.jacop.constraints.Constraint jconstraint : jscsp.getConstraints()) {
      idToConstraintMap.put(jconstraint.id, jconstraint);
    }

    IntVar[] vars = new IntVar[jscsp.getVariables().size()]; // including zero one
    // constants

    ArrayList<IntVar> classicalVars = new ArrayList<IntVar>(jscsp.getVariables());

    store = jscsp.getStore();
    vars = classicalVars.toArray(vars);
    search = new DepthFirstSearch<IntVar>();
    search.setPrintInfo(debug);

    select = new InputOrderSelect<IntVar>(store, vars, new IndomainMin<IntVar>());

    if (weighted) {
      select =
          new SimpleSelect<IntVar>(vars, new WeightedDegree<IntVar>(), new IndomainMin<IntVar>());
    }
    graph = jscsp.getDirectedConstraintGraph();
    upperCostBound = jscsp.getUpperCostBound();

    if (weighted) {
      enumerator = new WeightedViolationDegreeEnumerator(graph);
    } else {
      enumerator = new ConstraintRelationshipViolationDegreeEnumerator(graph);
    }

    enumerator.addViolationDegreeListener(this);
    wasSolved = false;
    enumerator.enumerate();
    return wasSolved;
  }
  private void notifyReified(MultiSet<String> exploredSet) {

    if (debug) {
      System.out.println("Checking ... " + exploredSet);
    }
    satisfiedConstraints = new ArrayList<PrimitiveConstraint>(constraintMap.size());
    violatedConstraints = new ArrayList<PrimitiveConstraint>(constraintMap.size());

    HashSet<String> violatedIds = new HashSet<String>(exploredSet.size() * 2);

    for (String violatedConstraint : exploredSet) {
      WrappedPrimitiveConstraint wpc = constraintMap.get(violatedConstraint);
      BooleanVar indicator = wpc.getViolationIndicator();

      // violation indicator must be true!
      PrimitiveConstraint nextIndicatorForce = new XeqY(indicator, constantOne);
      nextIndicatorForce.impose(store);
      // try constant
      PrimitiveConstraint nextIndicatorConst = new XeqC(indicator, 1);
      store.impose(nextIndicatorConst);

      violatedIds.add(violatedConstraint);

      violatedConstraints.add(nextIndicatorForce);
      violatedConstraints.add(nextIndicatorConst);
    }

    for (Entry<String, WrappedPrimitiveConstraint> remainingEntry : constraintMap.entrySet()) {
      if (!violatedIds.contains(remainingEntry.getKey())) {
        BooleanVar indicator = remainingEntry.getValue().getViolationIndicator();

        PrimitiveConstraint nextIndicatorForce =
            new XeqY(indicator, constantZero); // no penalty for those
        nextIndicatorForce.impose(store);
        // try constant
        PrimitiveConstraint nextForce = new XeqC(indicator, 0);
        nextForce.impose(store);

        satisfiedConstraints.add(nextIndicatorForce);
        satisfiedConstraints.add(nextForce);
      }
    }

    // now do some actual solving

    store.setLevel(store.level + 1);

    boolean result = search.labeling(store, select);

    if (result) {
      objectiveValue = objective.value();
      wasSolved = true;
      enumerator.foundSolutionOrInfeasibility();
      if (debug) {
        System.out.println("Found a best solution with cost: " + objective.value());
        System.out.println(store);
      }
    }

    store.removeLevel(store.level);
    store.setLevel(store.level - 1);

    // now cleanup
    for (PrimitiveConstraint pc : satisfiedConstraints) {
      pc.removeConstraint();
    }

    for (PrimitiveConstraint pc : violatedConstraints) {
      pc.removeConstraint();
    }
  }