Adloun

Dans le sac à dos, comparer trois stratégies gloutonnes

Exercice d'entraînement · niveau 3 (difficile) · NSI (première), chapitre 8 — Dichotomie, voisins et gloutons · Gloutons : jusqu'où ?

Énoncé

Dans le sac à dos, comparer trois stratégies gloutonnes : par valeur massique, par valeur seule, par poids croissant. Laquelle échoue le moins souvent ? Laquelle perd le moins ? Les deux questions ont-elles la même réponse ?

Corrigé


def sac_glouton(objets, capacite, cle):
    tries = sorted(objets, key=cle, reverse=True)
    choisis, restant, valeur = [], capacite, 0
    for nom, poids, v in tries:
        if poids <= restant:
            choisis.append(nom); restant -= poids; valeur += v
    assert restant >= 0
    return choisis, valeur

def sac_exhaustif(objets, capacite):
    """Oracle : toutes les combinaisons, pour de PETITES instances."""
    meilleure = 0
    for r in range(len(objets) + 1):
        for combi in itertools.combinations(objets, r):
            if sum(o[1] for o in combi) <= capacite:
                meilleure = max(meilleure, sum(o[2] for o in combi))
    return meilleure

massique = lambda o: o[2] / o[1]
valeur_seule = lambda o: o[2]
poids_leger = lambda o: -o[1]

Sur l'exemple du cours (capacité ; : /, et : /) :


OBJETS = [("A", 6, 30), ("B", 5, 20), ("C", 5, 20)]
assert sac_glouton(OBJETS, 10, massique)[1] == 30
assert sac_glouton(OBJETS, 10, valeur_seule)[1] == 30
assert sac_glouton(OBJETS, 10, poids_leger)[1] == 40    # ici, la meilleure !
assert sac_exhaustif(OBJETS, 10) == 40

Le « plus léger d'abord », qui semblait naïf, trouve l'optimum là où la valeur massique échoue. Mais il suffit de retourner l'exemple pour l'humilier :


AUTRES = [("A", 1, 1), ("B", 5, 50), ("C", 5, 50)]
assert sac_glouton(AUTRES, 10, poids_leger)[1] == 51    # il prend le grain de sable
assert sac_glouton(AUTRES, 10, massique)[1] == 100

La mesure sur instances tirées au hasard (six objets, capacités de à ) :

stratégieéchecs% de l'optimum en moyenne
valeur massique87
valeur seule66
poids croissant237

Non, les deux questions n'ont pas la même réponse — et c'est tout l'intérêt de l'exercice. La valeur massique échoue plus souvent que la valeur seule ( contre ), et pourtant elle rapporte davantage en moyenne. Trier par valeur seule tombe juste plus fréquemment, mais quand il se trompe, il se trompe plus lourdement.

Ce qu'il faut en retenir sur la mesure elle-même. Compter les échecs et mesurer la perte sont deux critères différents, qui peuvent classer les méthodes en sens contraire. Choisir un critère avant de mesurer n'est pas un détail méthodologique : c'est ce qui décide de la conclusion. Aucune des trois stratégies n'est d'ailleurs toujours optimale — c'est bien le propre d'un glouton.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.