Example #1
0
    def guess_bad_solve(self, specs):
        # TODO: Check features as well
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        def mysat(specs):
            dists = self.get_dists(specs)
            groups = build_groups(dists)
            m, v, w = self.build_vw(groups)
            clauses = set(self.gen_clauses(v, groups, specs))
            return sat(clauses)

        # Don't show the dots from solve2 in normal mode but do show the
        # dotlog messages with --debug
        dotlog.setLevel(logging.INFO)
        specs = [s for s in specs if not s.optional]
        hint = minimal_unsatisfiable_subset(specs, sat=mysat, log=True)
        if not hint:
            return ''
        hint = list(map(str, hint))
        if len(hint) == 1:
            # TODO: Generate a hint from the dependencies.
            ret = (("\nHint: '{0}' has unsatisfiable dependencies (see 'conda "
                "info {0}')").format(hint[0].split()[0]))
        else:
            ret = """
Hint: the following packages conflict with each other:
  - %s

Use 'conda info %s' etc. to see the dependencies for each package.""" % ('\n  - '.join(hint), hint[0].split()[0])
        return ret
Example #2
0
    def guess_bad_solve(self, specs, features):
        # TODO: Check features as well
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        # Don't show the dots from solve2 in normal mode but do show the
        # dotlog messages with --debug
        dotlog.setLevel(logging.WARN)

        def sat(specs):
            try:
                self.solve2(specs, features, guess=False, unsat_only=True)
            except RuntimeError:
                return False
            return True

        hint = minimal_unsatisfiable_subset(specs, sat=sat, log=True)
        if not hint:
            return ''
        if len(hint) == 1:
            # TODO: Generate a hint from the dependencies.
            return ((
                "\nHint: '{0}' has unsatisfiable dependencies (see 'conda "
                "info {0}')").format(hint[0].split()[0]))
        return ("""
Hint: the following packages conflict with each other:
  - %s""" % '\n  - '.join(hint))
Example #3
0
    def guess_bad_solve(self, specs):
        # TODO: Check features as well
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        def mysat(specs):
            dists = self.get_dists(specs)
            groups = build_groups(dists)
            m, v, w = self.build_vw(groups)
            clauses = set(self.gen_clauses(v, groups, specs))
            return sat(clauses)

        # Don't show the dots from solve2 in normal mode but do show the
        # dotlog messages with --debug
        dotlog.setLevel(logging.INFO)
        specs = [s for s in specs if not s.optional]
        hint = minimal_unsatisfiable_subset(specs, sat=mysat, log=True)
        if not hint:
            return ''
        hint = list(map(str, hint))
        if len(hint) == 1:
            # TODO: Generate a hint from the dependencies.
            ret = (("\nHint: '{0}' has unsatisfiable dependencies (see 'conda "
                "info {0}')").format(hint[0].split()[0]))
        else:
            ret = """
Hint: the following packages conflict with each other:
  - %s

Use 'conda info %s' etc. to see the dependencies for each package.""" % ('\n  - '.join(hint), hint[0].split()[0])
        return ret
Example #4
0
    def guess_bad_solve(self, specs, features):
        # TODO: Check features as well
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        # Don't show the dots from solve2 in normal mode but do show the
        # dotlog messages with --debug
        dotlog.setLevel(logging.WARN)

        def sat(specs):
            try:
                self.solve2(specs, features, guess=False, unsat_only=True)
            except RuntimeError:
                return False
            return True

        hint = minimal_unsatisfiable_subset(specs, sat=sat, log=True)
        if not hint:
            return ''
        if len(hint) == 1:
            # TODO: Generate a hint from the dependencies.
            return (("\nHint: '{0}' has unsatisfiable dependencies (see 'conda "
                "info {0}')").format(hint[0].split()[0]))
        return ("""
Hint: the following packages conflict with each other:
  - %s""" % '\n  - '.join(hint))
Example #5
0
def execute_instructions(plan, index=None, verbose=False, _commands=None):
    """
    Execute the instructions in the plan

    :param plan: A list of (instruction, arg) tuples
    :param index: The meta-data index
    :param verbose: verbose output
    :param _commands: (For testing only) dict mapping an instruction to executable if None
    then the default commands will be used
    """
    if _commands is None:
        _commands = commands

    if verbose:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

    state = {'i': None, 'prefix': config.root_dir, 'index': index}

    for instruction, args in plan:

        if not isinstance(args, (list, tuple)):
            args = (args,)

        log.debug(' %s%r' % (instruction, args))

        if state['i'] is not None and instruction in progress_cmds:
            state['i'] += 1
Example #6
0
    def guess_bad_solve(self, specs, features):
        # TODO: Check features as well
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()
        # Don't show the dots in normal mode but do show the dotlog messages
        # with --debug
        dotlog.setLevel(logging.WARN)
        hint = []
        # Try to find the largest satisfiable subset
        found = False
        if len(specs) > 10:
            stderrlog.info("WARNING: This could take a while. Type Ctrl-C to exit.\n")

        for i in range(len(specs), 0, -1):
            if found:
                logging.getLogger('progress.stop').info(None)
                break

            # Too lazy to compute closed form expression
            ncombs = len(list(combinations(specs, i)))
            logging.getLogger('progress.start').info(ncombs)
            for j, comb in enumerate(combinations(specs, i), 1):
                try:
                    logging.getLogger('progress.update').info(('%s/%s' % (j,
                        ncombs), j))
                    self.solve2(comb, features, guess=False, unsat_only=True)
                except RuntimeError:
                    pass
                else:
                    rem = set(specs) - set(comb)
                    rem.discard('conda')
                    if len(rem) == 1:
                        hint.append("%s" % rem.pop())
                    else:
                        hint.append("%s" % ' and '.join(rem))

                    found = True
        if not hint:
            return ''
        if len(hint) == 1:
            return ("\nHint: %s has a conflict with the remaining packages" %
                    hint[0])
        return ("""
Hint: the following combinations of packages create a conflict with the
remaining packages:
  - %s""" % '\n  - '.join(hint))
Example #7
0
File: plan.py Project: jschaf/conda
def execute_plan(plan, index=None, verbose=False):
    if verbose:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

    # set default prefix
    prefix = config.root_dir
    i = None
    cmds = cmds_from_plan(plan)

    for cmd, arg in cmds:
        if i is not None and cmd in progress_cmds:
            i += 1
            getLogger('progress.update').info((install.name_dist(arg), i))

        if cmd == PREFIX:
            prefix = arg
        elif cmd == PRINT:
            getLogger('print').info(arg)
        elif cmd == FETCH:
            fetch(index, arg)
        elif cmd == PROGRESS:
            i = 0
            maxval = int(arg)
            getLogger('progress.start').info(maxval)
        elif cmd == EXTRACT:
            install.extract(config.pkgs_dirs[0], arg)
        elif cmd == RM_EXTRACTED:
            install.rm_extracted(config.pkgs_dirs[0], arg)
        elif cmd == RM_FETCHED:
            install.rm_fetched(config.pkgs_dirs[0], arg)
        elif cmd == LINK:
            link(prefix, arg)
        elif cmd == UNLINK:
            install.unlink(prefix, arg)
        elif cmd == SYMLINK_CONDA:
            install.symlink_conda(prefix, arg)
        else:
            raise Exception("Did not expect command: %r" % cmd)

        if i is not None and cmd in progress_cmds and maxval == i:
            i = None
            getLogger('progress.stop').info(None)

    install.messages(prefix)
Example #8
0
def execute_plan(plan, index=None, verbose=False):
    if verbose:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

    # set default prefix
    prefix = config.root_dir
    i = None
    cmds = cmds_from_plan(plan)

    for cmd, arg in cmds:
        if i is not None and cmd in progress_cmds:
            i += 1
            getLogger('progress.update').info((install.name_dist(arg), i))

        if cmd == PREFIX:
            prefix = arg
        elif cmd == PRINT:
            getLogger('print').info(arg)
        elif cmd == FETCH:
            fetch(index, arg)
        elif cmd == PROGRESS:
            i = 0
            maxval = int(arg)
            getLogger('progress.start').info(maxval)
        elif cmd == EXTRACT:
            install.extract(config.pkgs_dirs[0], arg)
        elif cmd == RM_EXTRACTED:
            install.rm_extracted(config.pkgs_dirs[0], arg)
        elif cmd == RM_FETCHED:
            install.rm_fetched(config.pkgs_dirs[0], arg)
        elif cmd == LINK:
            link(prefix, arg, index=index)
        elif cmd == UNLINK:
            install.unlink(prefix, arg)
        elif cmd == SYMLINK_CONDA:
            install.symlink_conda(prefix, arg)
        else:
            raise Exception("Did not expect command: %r" % cmd)

        if i is not None and cmd in progress_cmds and maxval == i:
            i = None
            getLogger('progress.stop').info(None)

    install.messages(prefix)
Example #9
0
def execute_instructions(plan, index=None, verbose=False, _commands=None):
    """
    Execute the instructions in the plan

    :param plan: A list of (instruction, arg) tuples
    :param index: The meta-data index
    :param verbose: verbose output
    :param _commands: (For testing only) dict mapping an instruction to executable if None
    then the default commands will be used
    """
    if _commands is None:
        _commands = commands

    if verbose:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

    state = {'i': None, 'prefix': config.root_dir, 'index': index}

    for instruction, arg in plan:

        log.debug(' %s(%r)' % (instruction, arg))

        if state['i'] is not None and instruction in progress_cmds:
            state['i'] += 1
            getLogger('progress.update').info((install.name_dist(arg),
                state['i']-1))
        cmd = _commands.get(instruction)

        if cmd is None:
            raise InvalidInstruction(instruction)

        cmd(state, arg)

        if (state['i'] is not None and instruction in progress_cmds
                and state['maxval'] == state['i']):
            state['i'] = None
            getLogger('progress.stop').info(None)

    install.messages(state['prefix'])
Example #10
0
def execute_instructions(plan, index=None, verbose=False, _commands=None):
    """
    Execute the instructions in the plan

    :param plan: A list of (instruction, arg) tuples
    :param index: The meta-data index
    :param verbose: verbose output
    :param _commands: (For testing only) dict mapping an instruction to executable if None
    then the default commands will be used
    """
    if _commands is None:
        _commands = commands

    if verbose:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

    state = {'i': None, 'prefix': config.root_dir, 'index': index}

    for instruction, arg in plan:

        log.debug(' %s(%r)' % (instruction, arg))

        if state['i'] is not None and instruction in progress_cmds:
            state['i'] += 1
            getLogger('progress.update').info((install.name_dist(arg),
                                               state['i'] - 1))
        cmd = _commands.get(instruction)

        if cmd is None:
            raise InvalidInstruction(instruction)

        cmd(state, arg)

        if (state['i'] is not None and instruction in progress_cmds and
                state['maxval'] == state['i']):
            state['i'] = None
            getLogger('progress.stop').info(None)

    install.messages(state['prefix'])
Example #11
0
def minimal_unsatisfiable_subset(clauses, log=False):
    """
    Given a set of clauses, find a minimal unsatisfiable subset (an
    unsatisfiable core)

    A set is a minimal unsatisfiable subset if no proper subset is
    unsatisfiable.  A set of clauses may have many minimal unsatisfiable
    subsets of different sizes.

    if log=True, progress bars will be displayed with the progress.
    """

    if log:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()
        start = lambda x: logging.getLogger('progress.start').info(x)
        update = lambda x, y: logging.getLogger('progress.update').info(
            ("%s/%s" % (x, y), x))
        stop = lambda: logging.getLogger('progress.stop').info(None)
    else:
        start = lambda x: None
        update = lambda x, y: None
        stop = lambda: None

    clauses = tuple(clauses)
    if sat(clauses):
        raise ValueError("Clauses are not unsatisfiable")

    # Algorithm suggested from
    # http://www.slideshare.net/pvcpvc9/lecture17-31382688. We do a binary
    # search on the clauses by splitting them in halves A and B. If A or B is
    # UNSAT, we use that and repeat. Otherwise, we recursively check A, but
    # each time we do a sat query, we include B, until we have a minimal
    # subset A* of A such that A* U B is UNSAT. Then we find a minimal subset
    # B* of B such that A* U B* is UNSAT. Then A* U B* will be a minimal
    # unsatisfiable subset of the original set of clauses.

    # Proof: If some proper subset C of A* U B* is UNSAT, then there is some
    # clause c in A* U B* not in C. If c is in A*, then that means (A* - {c})
    # U B* is UNSAT, and hence (A* - {c}) U B is UNSAT, since it is a
    # superset, which contradicts A* being the minimal subset of A with such
    # property. Similarly, if c is in B, then A* U (B* - {c}) is UNSAT, but B*
    # - {c} is a strict subset of B*, contradicting B* being the minimal
    # subset of B with this property.

    def split(S):
        """
        Split S into two equal parts
        """
        S = tuple(S)
        L = len(S)
        return S[:L // 2], S[L // 2:]

    def minimal_unsat(clauses, include=()):
        """
        Return a minimal subset A of clauses such that A + include is
        unsatisfiable.

        Implicitly assumes that clauses + include is unsatisfiable.
        """
        global L, d

        # assert not sat(clauses + include), (len(clauses), len(include))

        # Base case: Since clauses + include is implicitly assumed to be
        # unsatisfiable, if clauses has only one element, it must be its own
        # minimal subset
        if len(clauses) == 1:
            return clauses

        A, B = split(clauses)

        # If one half is unsatisfiable (with include), we can discard the
        # other half.

        # To display progress, every time we discard clauses, we update the
        # progress by that much.
        # dotlog.debug("")
        if not sat(A + include):
            d += len(B)
            update(d, L)
            return minimal_unsat(A, include)
        # dotlog.debug("")
        if not sat(B + include):
            d += len(A)
            update(d, L)
            return minimal_unsat(B, include)

        Astar = minimal_unsat(A, B + include)
        Bstar = minimal_unsat(B, Astar + include)
        return Astar + Bstar

    global L, d
    L = len(clauses)
    d = 0
    start(L)
    ret = minimal_unsat(clauses)
    # Commented out because it hides the progress
    # stop()
    return ret
Example #12
0
def minimal_unsatisfiable_subset(clauses, sat, log=False):
    """
    Given a set of clauses, find a minimal unsatisfiable subset (an
    unsatisfiable core)

    A set is a minimal unsatisfiable subset if no proper subset is
    unsatisfiable.  A set of clauses may have many minimal unsatisfiable
    subsets of different sizes.

    If log=True, progress bars will be displayed with the progress.

    sat should be a function that takes a tuple of clauses and returns True if
    the clauses are satisfiable and False if they are not.  The algorithm will
    work with any order-reversing function (reversing the order of subset and
    the order False < True), that is, any function where (A <= B) iff (sat(B)
    <= sat(A)), where A <= B means A is a subset of B and False < True).

    Algorithm
    =========

    Algorithm suggested from
    http://www.slideshare.net/pvcpvc9/lecture17-31382688. We do a binary
    search on the clauses by splitting them in halves A and B. If A or B is
    UNSAT, we use that and repeat. Otherwise, we recursively check A, but each
    time we do a sat query, we include B, until we have a minimal subset A* of
    A such that A* U B is UNSAT. Then we find a minimal subset B* of B such
    that A* U B* is UNSAT. Then A* U B* will be a minimal unsatisfiable subset
    of the original set of clauses.

    Proof: If some proper subset C of A* U B* is UNSAT, then there is some
    clause c in A* U B* not in C. If c is in A*, then that means (A* - {c}) U
    B* is UNSAT, and hence (A* - {c}) U B is UNSAT, since it is a superset,
    which contradicts A* being the minimal subset of A with such
    property. Similarly, if c is in B, then A* U (B* - {c}) is UNSAT, but B* -
    {c} is a strict subset of B*, contradicting B* being the minimal subset of
    B with this property.

    """
    if log:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        def start(x):
            return logging.getLogger('progress.start').info(x)

        def update(x, y):
            logging.getLogger('progress.update').info(("%s/%s" % (x, y), x))

        def stop():
            return logging.getLogger('progress.stop').info(None)
    else:

        def start(x):
            pass

        def update(x, y):
            pass

        def stop():
            pass

    clauses = tuple(clauses)
    if sat(clauses):
        raise ValueError("Clauses are not unsatisfiable")

    def split(S):
        """
        Split S into two equal parts
        """
        S = tuple(S)
        L = len(S)
        return S[:L//2], S[L//2:]

    def minimal_unsat(clauses, include=()):
        """
        Return a minimal subset A of clauses such that A + include is
        unsatisfiable.

        Implicitly assumes that clauses + include is unsatisfiable.
        """
        global L, d

        # assert not sat(clauses + include), (len(clauses), len(include))

        # Base case: Since clauses + include is implicitly assumed to be
        # unsatisfiable, if clauses has only one element, it must be its own
        # minimal subset
        if len(clauses) == 1:
            return clauses

        A, B = split(clauses)

        # If one half is unsatisfiable (with include), we can discard the
        # other half.

        # To display progress, every time we discard clauses, we update the
        # progress by that much.
        if not sat(A + include):
            d += len(B)
            update(d, L)
            return minimal_unsat(A, include)
        if not sat(B + include):
            d += len(A)
            update(d, L)
            return minimal_unsat(B, include)

        Astar = minimal_unsat(A, B + include)
        Bstar = minimal_unsat(B, Astar + include)
        return Astar + Bstar

    global L, d
    L = len(clauses)
    d = 0
    start(L)
    ret = minimal_unsat(clauses)
    stop()
    return ret
Example #13
0
def minimal_unsatisfiable_subset(clauses, log=False):
    """
    Given a set of clauses, find a minimal unsatisfiable subset (an
    unsatisfiable core)

    A set is a minimal unsatisfiable subset if no proper subset is
    unsatisfiable.  A set of clauses may have many minimal unsatisfiable
    subsets of different sizes.

    if log=True, progress bars will be displayed with the progress.
    """

    if log:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()
        start = lambda x: logging.getLogger('progress.start').info(x)
        update = lambda x, y: logging.getLogger('progress.update').info(("%s/%s" % (x, y), x))
        stop = lambda: logging.getLogger('progress.stop').info(None)
    else:
        start = lambda x: None
        update = lambda x, y: None
        stop = lambda: None

    clauses = tuple(clauses)
    if sat(clauses):
        raise ValueError("Clauses are not unsatisfiable")

    # Algorithm suggested from
    # http://www.slideshare.net/pvcpvc9/lecture17-31382688. We do a binary
    # search on the clauses by splitting them in halves A and B. If A or B is
    # UNSAT, we use that and repeat. Otherwise, we recursively check A, but
    # each time we do a sat query, we include B, until we have a minimal
    # subset A* of A such that A* U B is UNSAT. Then we find a minimal subset
    # B* of B such that A* U B* is UNSAT. Then A* U B* will be a minimal
    # unsatisfiable subset of the original set of clauses.

    # Proof: If some proper subset C of A* U B* is UNSAT, then there is some
    # clause c in A* U B* not in C. If c is in A*, then that means (A* - {c})
    # U B* is UNSAT, and hence (A* - {c}) U B is UNSAT, since it is a
    # superset, which contradicts A* being the minimal subset of A with such
    # property. Similarly, if c is in B, then A* U (B* - {c}) is UNSAT, but B*
    # - {c} is a strict subset of B*, contradicting B* being the minimal
    # subset of B with this property.

    def split(S):
        """
        Split S into two equal parts
        """
        S = tuple(S)
        L = len(S)
        return S[:L//2], S[L//2:]

    def minimal_unsat(clauses, include=()):
        """
        Return a minimal subset A of clauses such that A + include is
        unsatisfiable.

        Implicitly assumes that clauses + include is unsatisfiable.
        """
        global L, d

        # assert not sat(clauses + include), (len(clauses), len(include))

        # Base case: Since clauses + include is implicitly assumed to be
        # unsatisfiable, if clauses has only one element, it must be its own
        # minimal subset
        if len(clauses) == 1:
            return clauses

        A, B = split(clauses)

        # If one half is unsatisfiable (with include), we can discard the
        # other half.

        # To display progress, every time we discard clauses, we update the
        # progress by that much.
        # dotlog.debug("")
        if not sat(A + include):
            d += len(B)
            update(d, L)
            return minimal_unsat(A, include)
        # dotlog.debug("")
        if not sat(B + include):
            d += len(A)
            update(d, L)
            return minimal_unsat(B, include)

        Astar = minimal_unsat(A, B + include)
        Bstar = minimal_unsat(B, Astar + include)
        return Astar + Bstar

    global L, d
    L = len(clauses)
    d = 0
    start(L)
    ret = minimal_unsat(clauses)
    # Commented out because it hides the progress
    # stop()
    return ret
Example #14
0
def minimal_unsatisfiable_subset(clauses, sat, log=False):
    """
    Given a set of clauses, find a minimal unsatisfiable subset (an
    unsatisfiable core)

    A set is a minimal unsatisfiable subset if no proper subset is
    unsatisfiable.  A set of clauses may have many minimal unsatisfiable
    subsets of different sizes.

    If log=True, progress bars will be displayed with the progress.

    sat should be a function that takes a tuple of clauses and returns True if
    the clauses are satisfiable and False if they are not.  The algorithm will
    work with any order-reversing function (reversing the order of subset and
    the order False < True), that is, any function where (A <= B) iff (sat(B)
    <= sat(A)), where A <= B means A is a subset of B and False < True).

    Algorithm
    =========

    Algorithm suggested from
    http://www.slideshare.net/pvcpvc9/lecture17-31382688. We do a binary
    search on the clauses by splitting them in halves A and B. If A or B is
    UNSAT, we use that and repeat. Otherwise, we recursively check A, but each
    time we do a sat query, we include B, until we have a minimal subset A* of
    A such that A* U B is UNSAT. Then we find a minimal subset B* of B such
    that A* U B* is UNSAT. Then A* U B* will be a minimal unsatisfiable subset
    of the original set of clauses.

    Proof: If some proper subset C of A* U B* is UNSAT, then there is some
    clause c in A* U B* not in C. If c is in A*, then that means (A* - {c}) U
    B* is UNSAT, and hence (A* - {c}) U B is UNSAT, since it is a superset,
    which contradicts A* being the minimal subset of A with such
    property. Similarly, if c is in B, then A* U (B* - {c}) is UNSAT, but B* -
    {c} is a strict subset of B*, contradicting B* being the minimal subset of
    B with this property.

    """
    if log:
        from conda.console import setup_verbose_handlers
        setup_verbose_handlers()

        def start(x):
            return logging.getLogger('progress.start').info(x)

        def update(x, y):
            logging.getLogger('progress.update').info(("%s/%s" % (x, y), x))

        def stop():
            return logging.getLogger('progress.stop').info(None)
    else:

        def start(x):
            pass

        def update(x, y):
            pass

        def stop():
            pass

    clauses = tuple(clauses)
    if sat(clauses):
        raise ValueError("Clauses are not unsatisfiable")

    def split(S):
        """
        Split S into two equal parts
        """
        S = tuple(S)
        L = len(S)
        return S[:L//2], S[L//2:]

    def minimal_unsat(clauses, include=()):
        """
        Return a minimal subset A of clauses such that A + include is
        unsatisfiable.

        Implicitly assumes that clauses + include is unsatisfiable.
        """
        global L, d

        # assert not sat(clauses + include), (len(clauses), len(include))

        # Base case: Since clauses + include is implicitly assumed to be
        # unsatisfiable, if clauses has only one element, it must be its own
        # minimal subset
        if len(clauses) == 1:
            return clauses

        A, B = split(clauses)

        # If one half is unsatisfiable (with include), we can discard the
        # other half.

        # To display progress, every time we discard clauses, we update the
        # progress by that much.
        if not sat(A + include):
            d += len(B)
            update(d, L)
            return minimal_unsat(A, include)
        if not sat(B + include):
            d += len(A)
            update(d, L)
            return minimal_unsat(B, include)

        Astar = minimal_unsat(A, B + include)
        Bstar = minimal_unsat(B, Astar + include)
        return Astar + Bstar

    global L, d
    L = len(clauses)
    d = 0
    start(L)
    ret = minimal_unsat(clauses)
    stop()
    return ret
    from conda.exports import NoPackagesFound
    from conda.exports import Resolve
    from conda.exports import string_types
    from conda.models.dist import Dist as _Dist

    def get_key(dist_or_filename):
        return dist_or_filename

    def copy_index(index):
        return {_Dist(key): index[key] for key in index.keys()}

    def ensure_dist_or_dict(fn):
        return _Dist.from_string(fn)

    from conda.console import setup_verbose_handlers
    setup_verbose_handlers()
    from conda.gateways.logging import initialize_logging
    initialize_logging()

elif (4, 2) <= CONDA_VERSION_MAJOR_MINOR < (4, 3):
    from conda.lock import Locked
    from conda.exports import get_index
    from conda.exports import subdir
    from conda.exports import MatchSpec
    from conda.exports import Unsatisfiable
    from conda.exports import NoPackagesFound
    from conda.exports import Resolve
    from conda.exports import string_types

    def get_key(dist_or_filename):
        return dist_or_filename.fn