ipet icon indicating copy to clipboard operation
ipet copied to clipboard

Support HiGHS solver

Open rschwarz opened this issue 1 year ago • 1 comments

HiGHS currently doesn't have an implementation of Solver in ipet.parsing.Solver.

rschwarz avatar Dec 04 '24 15:12 rschwarz

I've added this on my own fork, but I was only interested in the primal bound history, so my implementation is very partial:

class HiGHSSolver(Solver):
    """Solver class for HiGHS"""

    # Add some things that we might not actually need
    solverId = "HiGHS"
    recognition_expr = re.compile(r"^Running HiGHS ")
    primalbound_expr = re.compile(r"^  Primal bound      (\S+)")
    dualbound_expr = re.compile(r"^  Dual bound        (\S+)")
    solvingtime_expr = re.compile(r"^  Timing            (\S+)")

    # Implement the single relevant method:

    def extractPrimalboundHistory(self, line: str):
        """Extract the sequence of primal bounds.

        Need to figure out if we have a relevant line, then extract the time and
        new bound.

        Example log output:
        ^        Nodes      |    B&B Tree     |            Objective Bounds              |  Dynamic Constraints |       Work      $
        ^Src  Proc. InQueue |  Leaves   Expl. | BestBound       BestSol              Gap |   Cuts   InLp Confl. | LpIters     Time$
        ^$
        ^         0       0         0   0.00%   0               inf                  inf        0      0      0         0     0.0s$
        ^ R       0       0         0   0.00%   0.00834127713   413.8153493      100.00%        0      0      0     13574     1.5s$
        ^ L       0       0         0   0.00%   0.00834127713   156.3167274       99.99%      120     20      0     13963     7.1s$
        """

        # Table lines with new solutions are marked by a single character in the
        # 2nd position, which indicates the source of the solution.
        #
        # We can then extract the bound and time by the column index.

        good_line = re.compile(r"^ \w ")
        if good_line.match(line) is None:
            return

        # col:  1   2    3    4    5    6    7!     8    9    10   11   12   13!
        pattern = re.compile(
            r"^ \w +\S+ +\S+ +\S+ +\S+ +\S+ +(\S+) +\S+ +\S+ +\S+ +\S+ +\S+ +(\S+)s$"
        )
        m = pattern.match(line)
        if m is None:
            raise ValueError(f"Unexpected table line: {line.rstrip()}")
        primal_bound, time = m.groups()
        self.addHistoryData(Key.PrimalBoundHistory, time, primal_bound)

rschwarz avatar Dec 04 '24 15:12 rschwarz