From: Michael Schroeder Date: Thu, 15 Dec 2022 10:02:06 +0000 (+0100) Subject: Move alternatives introspection code into decision.c X-Git-Tag: 0.7.24~20 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=e31dfa02ede7f65d65019b5260f82dbc73230501;p=thirdparty%2Flibsolv.git Move alternatives introspection code into decision.c --- diff --git a/src/decision.c b/src/decision.c index d364f7ea..97d86890 100644 --- a/src/decision.c +++ b/src/decision.c @@ -8,7 +8,7 @@ /* * decision.c * - * solver decision introspection code + * solver decision and alternative introspection code */ #include @@ -1008,3 +1008,190 @@ solver_decisioninfo2str(Solver *solv, int bits, int type, Id from, Id to, Id dep return "unsupported decision merge?"; return solver_ruleinfo2str(solv, type, from, to, dep); } + +int +solver_alternatives_count(Solver *solv) +{ + Id *elements = solv->branches.elements; + int res, count; + for (res = 0, count = solv->branches.count; count; res++) + count -= elements[count - 2]; + return res; +} + +int +solver_get_alternative(Solver *solv, Id alternative, Id *idp, Id *fromp, Id *chosenp, Queue *choices, int *levelp) +{ + int cnt = solver_alternatives_count(solv); + int count = solv->branches.count; + Id *elements = solv->branches.elements; + if (choices) + queue_empty(choices); + if (alternative <= 0 || alternative > cnt) + return 0; + elements += count; + for (; cnt > alternative; cnt--) + elements -= elements[-2]; + if (levelp) + *levelp = elements[-1]; + if (fromp) + *fromp = elements[-4]; + if (idp) + *idp = elements[-3]; + if (chosenp) + { + int i; + *chosenp = 0; + for (i = elements[-2]; i > 4; i--) + { + Id p = -elements[-i]; + if (p > 0 && solv->decisionmap[p] == elements[-1] + 1) + { + *chosenp = p; + break; + } + } + } + if (choices) + queue_insertn(choices, 0, elements[-2] - 4, elements - elements[-2]); + return elements[-4] ? SOLVER_ALTERNATIVE_TYPE_RECOMMENDS : SOLVER_ALTERNATIVE_TYPE_RULE; +} + +static int +find_alternative_rule_from_learnt_rec(Solver *solv, int rid, Map *m, int cnt) +{ + Pool *pool = solv->pool; + int why = solv->learnt_why.elements[rid - solv->learntrules]; + while ((rid = solv->learnt_pool.elements[why++]) != 0) + { + Rule *r = solv->rules + rid; + Id p, pp; + int c; + if (rid >= solv->learntrules) + { + if ((rid = find_alternative_rule_from_learnt_rec(solv, rid, m, cnt))) + return rid; + continue; + } + c = 0; + FOR_RULELITERALS(p, pp, r) + if (p > 0 && MAPTST(m, p)) + c++; + if (c == cnt) /* all bits hit */ + return rid; + } + return 0; +} + +static int +find_alternative_rule_from_learnt(Solver *solv, int rid) +{ + Pool *pool = solv->pool; + Map m; + int i, count, cnt; + Id *elements = solv->branches.elements; + + /* find alternative by rule id */ + for (count = solv->branches.count; count; count -= elements[count - 2]) + if (elements[count - 4] == 0 && elements[count - 3] == rid) + break; + if (!count) + return 0; + map_init(&m, pool->nsolvables); + cnt = 0; + for (i = count - elements[count - 2]; i < count - 4; i++) + if (elements[i] > 0) + { + MAPSET(&m, elements[i]); + cnt++; + } + rid = find_alternative_rule_from_learnt_rec(solv, rid, &m, cnt); + map_free(&m); + return rid; +} + +int +solver_alternativeinfo(Solver *solv, int type, Id id, Id from, Id *fromp, Id *top, Id *depp) +{ + if (fromp) + *fromp = 0; + if (top) + *top = 0; + if (depp) + *depp = 0; + if (type == SOLVER_ALTERNATIVE_TYPE_RECOMMENDS) + { + if (fromp) + *fromp = from; + if (depp) + *depp = id; + return SOLVER_RULE_PKG_RECOMMENDS; + } + else if (type == SOLVER_ALTERNATIVE_TYPE_RULE) + { + int rclass = solver_ruleclass(solv, id); + if (rclass == SOLVER_RULE_LEARNT) + { + id = find_alternative_rule_from_learnt(solv, id); + if (!id) + return SOLVER_RULE_LEARNT; + rclass = solver_ruleclass(solv, id); + } + if (rclass == SOLVER_RULE_CHOICE || rclass == SOLVER_RULE_RECOMMENDS) + id = solver_rule2pkgrule(solv, id); + else if (rclass == SOLVER_RULE_BEST) + { + Id info = solv->bestrules_info[id - solv->bestrules]; + if (info > 0) + { + /* best update */ + if (fromp) + *fromp = info; + return SOLVER_RULE_UPDATE; + } + id = -info; /* best job, delegate to job rule */ + } + return solver_ruleinfo(solv, id, fromp, top, depp); + } + return 0; +} + +const char * +solver_alternative2str(Solver *solv, int type, Id id, Id from) +{ + const char *s; + Pool *pool = solv->pool; + Id to, dep; + type = solver_alternativeinfo(solv, type, id, from, &from, &to, &dep); + switch (type) + { + case SOLVER_RULE_PKG_RECOMMENDS: + s = pool_dep2str(pool, dep); + if (from) + s = pool_tmpappend(pool, s, ", recommended by ", pool_solvid2str(pool, from)); + return s; + case SOLVER_RULE_PKG_REQUIRES: + s = pool_dep2str(pool, dep); + if (from) + s = pool_tmpappend(pool, s, ", required by ", pool_solvid2str(pool, from)); + return s; + case SOLVER_RULE_PKG_CONFLICTS: + s = pool_dep2str(pool, dep); + if (from) + s = pool_tmpappend(pool, s, ", conflicted by ", pool_solvid2str(pool, from)); + return s; + case SOLVER_RULE_YUMOBS: + return pool_tmpjoin(pool, pool_id2str(pool, pool->solvables[to].name), ", obsoleting ", pool_dep2str(pool, dep));; + case SOLVER_RULE_JOB: + if ((to & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_PROVIDES || (to & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_NAME) + return pool_dep2str(pool, dep); + return solver_select2str(pool, to & SOLVER_SELECTMASK, dep); + case SOLVER_RULE_UPDATE: + case SOLVER_RULE_FEATURE: + return pool_solvid2str(pool, from); + default: + break; + } + return solver_ruleinfo2str(solv, type, from, to, dep); +} + diff --git a/src/rules.c b/src/rules.c index 9be4559f..f51a8d38 100644 --- a/src/rules.c +++ b/src/rules.c @@ -4111,7 +4111,7 @@ for (j = 0; j < qq.count; j++) if (!qq.count) continue; - /* at least two goups, build rules */ + /* at least two groups, build rules */ group = 0; for (j = 0; j < qq.count; j++) { diff --git a/src/solver.c b/src/solver.c index 0ba69fec..b012a3a8 100644 --- a/src/solver.c +++ b/src/solver.c @@ -4660,153 +4660,6 @@ pool_isemptyupdatejob(Pool *pool, Id how, Id what) return 1; } -int -solver_alternatives_count(Solver *solv) -{ - Id *elements = solv->branches.elements; - int res, count; - for (res = 0, count = solv->branches.count; count; res++) - count -= elements[count - 2]; - return res; -} - -int -solver_get_alternative(Solver *solv, Id alternative, Id *idp, Id *fromp, Id *chosenp, Queue *choices, int *levelp) -{ - int cnt = solver_alternatives_count(solv); - int count = solv->branches.count; - Id *elements = solv->branches.elements; - if (choices) - queue_empty(choices); - if (alternative <= 0 || alternative > cnt) - return 0; - elements += count; - for (; cnt > alternative; cnt--) - elements -= elements[-2]; - if (levelp) - *levelp = elements[-1]; - if (fromp) - *fromp = elements[-4]; - if (idp) - *idp = elements[-3]; - if (chosenp) - { - int i; - *chosenp = 0; - for (i = elements[-2]; i > 4; i--) - { - Id p = -elements[-i]; - if (p > 0 && solv->decisionmap[p] == elements[-1] + 1) - { - *chosenp = p; - break; - } - } - } - if (choices) - queue_insertn(choices, 0, elements[-2] - 4, elements - elements[-2]); - return elements[-4] ? SOLVER_ALTERNATIVE_TYPE_RECOMMENDS : SOLVER_ALTERNATIVE_TYPE_RULE; -} - -static int -find_alternative_rule_from_learnt_rec(Solver *solv, int rid, Map *m, int cnt) -{ - Pool *pool = solv->pool; - int why = solv->learnt_why.elements[rid - solv->learntrules]; - while ((rid = solv->learnt_pool.elements[why++]) != 0) - { - Rule *r = solv->rules + rid; - Id p, pp; - int c; - if (rid >= solv->learntrules) - { - if ((rid = find_alternative_rule_from_learnt_rec(solv, rid, m, cnt))) - return rid; - continue; - } - c = 0; - FOR_RULELITERALS(p, pp, r) - if (p > 0 && MAPTST(m, p)) - c++; - if (c == cnt) /* all bits hit */ - return rid; - } - return 0; -} - -static int -find_alternative_rule_from_learnt(Solver *solv, int rid) -{ - Pool *pool = solv->pool; - Map m; - int i, count, cnt; - Id *elements = solv->branches.elements; - - /* find alternative by rule id */ - for (count = solv->branches.count; count; count -= elements[count - 2]) - if (elements[count - 4] == 0 && elements[count - 3] == rid) - break; - if (!count) - return 0; - map_init(&m, pool->nsolvables); - cnt = 0; - for (i = count - elements[count - 2]; i < count - 4; i++) - if (elements[i] > 0) - { - MAPSET(&m, elements[i]); - cnt++; - } - rid = find_alternative_rule_from_learnt_rec(solv, rid, &m, cnt); - map_free(&m); - return rid; -} - -int -solver_alternativeinfo(Solver *solv, int type, Id id, Id from, Id *fromp, Id *top, Id *depp) -{ - if (fromp) - *fromp = 0; - if (top) - *top = 0; - if (depp) - *depp = 0; - if (type == SOLVER_ALTERNATIVE_TYPE_RECOMMENDS) - { - if (fromp) - *fromp = from; - if (depp) - *depp = id; - return SOLVER_RULE_PKG_RECOMMENDS; - } - else if (type == SOLVER_ALTERNATIVE_TYPE_RULE) - { - int rclass = solver_ruleclass(solv, id); - if (rclass == SOLVER_RULE_LEARNT) - { - id = find_alternative_rule_from_learnt(solv, id); - if (!id) - return SOLVER_RULE_LEARNT; - rclass = solver_ruleclass(solv, id); - } - if (rclass == SOLVER_RULE_CHOICE || rclass == SOLVER_RULE_RECOMMENDS) - id = solver_rule2pkgrule(solv, id); - else if (rclass == SOLVER_RULE_BEST) - { - Id info = solv->bestrules_info[id - solv->bestrules]; - if (info > 0) - { - /* best update */ - if (fromp) - *fromp = info; - return SOLVER_RULE_UPDATE; - } - id = -info; /* best job, delegate to job rule */ - } - return solver_ruleinfo(solv, id, fromp, top, depp); - } - return 0; -} - const char * solver_select2str(Pool *pool, Id select, Id what) { @@ -4958,35 +4811,3 @@ pool_job2str(Pool *pool, Id how, Id what, Id flagmask) return pool_tmpappend(pool, s, "]", 0); } -const char * -solver_alternative2str(Solver *solv, int type, Id id, Id from) -{ - const char *s; - Pool *pool = solv->pool; - Id to, dep; - type = solver_alternativeinfo(solv, type, id, from, &from, &to, &dep); - switch (type) - { - case SOLVER_RULE_PKG_RECOMMENDS: - s = pool_dep2str(pool, dep); - if (from) - s = pool_tmpappend(pool, s, ", recommended by ", pool_solvid2str(pool, from)); - return s; - case SOLVER_RULE_PKG_REQUIRES: - s = pool_dep2str(pool, dep); - if (from) - s = pool_tmpappend(pool, s, ", required by ", pool_solvid2str(pool, from)); - return s; - case SOLVER_RULE_JOB: - if ((to & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_PROVIDES) - return pool_dep2str(pool, dep); - return solver_select2str(pool, to & SOLVER_SELECTMASK, dep); - case SOLVER_RULE_UPDATE: - case SOLVER_RULE_FEATURE: - return pool_solvid2str(pool, from); - default: - break; - } - return solver_ruleinfo2str(solv, type, from, to, dep); -} -