@SuppressWarnings("rawtypes")
	public SolutionState solve(int timeLimit, int bound) {
        int n = graph.getNbVertices();
        int minCost = graph.getMinArcCost();
        int maxCost = graph.getMaxArcCost();
        int[][] cost = graph.getCost();
        next = new int[n];
        Solver solver = new Solver();

        // Create variables
        // xNext[i] = vertex visited after i
        IntVar[] xNext = new IntVar[n];
        for (int i = 0; i < n; i++)
            xNext[i] = VariableFactory.enumerated("Next " + i, graph.getSucc(i), solver);
        // xCost[i] = cost of arc (i,xNext[i])
        IntVar[] xCost = VariableFactory.boundedArray("Cost ", n, minCost, maxCost, solver);
        // xTotalCost = total cost of the solution
        IntVar xTotalCost = VariableFactory.bounded("Total cost ", n * minCost, bound - 1, solver);

        // Add constraints
        for (int i = 0; i < n; i++)
            solver.post(IntConstraintFactory.element(xCost[i], cost[i], xNext[i], 0, "none"));
        solver.post(IntConstraintFactory.circuit(xNext, 0));
        solver.post(IntConstraintFactory.sum(xCost, xTotalCost));

        // limit CPU time
        SearchMonitorFactory.limitTime(solver, timeLimit);
        // set the branching heuristic (branch on xNext only by selecting smallest domains first)
        solver.set(IntStrategyFactory.firstFail_InDomainMin(xNext));
        // try to find and prove the optimal solution
        solver.findOptimalSolution(ResolutionPolicy.MINIMIZE, xTotalCost);
        // record solution and state
        if (solver.getMeasures().getSolutionCount() > 0) {
            if (solver.getSearchLoop().hasReachedLimit())
                state = SolutionState.SOLUTION_FOUND;
            else
                state = SolutionState.OPTIMAL_SOLUTION_FOUND;
            for (int i = 0; i < n; i++)
                next[i] = xNext[i].getValue();
            totalCost = xTotalCost.getValue();
        } else {
            if (solver.getSearchLoop().hasReachedLimit())
                state = SolutionState.NO_SOLUTION_FOUND;
            else
                state = SolutionState.INCONSISTENT;
        }
        return state;
    }