# File lib/declarative_authorization/development_support/change_analyzer.rb, line 30
      def find_approaches_for (change_action, type, options, &tests)
        raise ArgumentError, "Missing options" if !options[:on] or !options[:to]

        # * strategy for removing: [remove privilege, add privilege to different role]
        @seen_states = Set.new
        # * heuristic: change of failed tests;  small number of policy items
        strategy = case [change_action, type]
                   when [:remove, :permission]
                     [:remove_role_from_user, :remove_privilege, :add_privilege,
                       :add_role, :assign_role_to_user]
                   when [:add, :permission]
                     [:add_role, :add_privilege, :assign_role_to_user]
                   else
                     raise ArgumentError, "Unknown change action/type: #{[change_action, type].inspect}"
                   end

        candidates = []
        viable_approaches = []
        approach_checker = ApproachChecker.new(self, tests)

        starting_candidate = Approach.new(@engine, options[:users], [])
        if starting_candidate.check(approach_checker)
          viable_approaches << starting_candidate
        else
          candidates << starting_candidate
        end

        step_count = 0
        while !candidates.empty? and step_count < 100
          next_step(viable_approaches, candidates, approach_checker, options[:to], 
              options[:on], strategy)
          step_count += 1
        end

        # remove subsets

        viable_approaches.sort!
      end