Han Hoogeveen

51 papers A 3B 6C 8Journal 32Unranked 1
YearRankTypeTitle / Venue / Authors
2026 J jnl
Public Transp.
Wouter ten Bosch, Han Hoogeveen, Marcel E. van Kooten Niekerk, Philip de Bruin
2025 J jnl
J. Sched.
Roel J. J. Brouwer, Marjan van den Akker, Han Hoogeveen
2025 J jnl
J. Heuristics
Guido Passage, Marjan van den Akker, Han Hoogeveen
2023 J jnl
Oper. Res. Lett.
Steven J. M. den Hartog, Han Hoogeveen, Tom C. van der Zanden
2023 C conf
ATMOS
Philip de Bruin, Marjan van den Akker, Han Hoogeveen, Marcel E. van Kooten Niekerk
2023 C conf
ICORES
Han Hoogeveen
2022 J jnl
Transp. Sci.
Roel van den Broek, Han Hoogeveen, Marjan van den Akker, Bob Huisman
2021 J jnl
Comput. Oper. Res.
René van Twist, Marjan van den Akker, Han Hoogeveen
2021 A conf
AAMAS
Jacobus G. M. van der Linden, Jesse Mulderij, Bob Huisman, Joris W. den Ouden, Marjan van den Akker, Han Hoogeveen, Mathijs Michiel de Weerdt
2020 C conf
ATMOS
Roel van den Broek, Han Hoogeveen, Marjan van den Akker
2019 J jnl
OR Spectr.
Jason A. D. Atkin, Han Hoogeveen, Raik Stolletz
2019 J jnl
Comput. Ind. Eng.
Han Hoogeveen, Jakub Tomczyk, Tom C. van der Zanden
2018 J jnl
J. Sched.
Marjan van den Akker, Han Hoogeveen, Judith Stoef
2018 C conf
ATMOS
Roel van den Broek, Han Hoogeveen, Marjan van den Akker
2016 C conf
COCOA
Arne Hillebrand, Marjan van den Akker, Roland Geraerts, Han Hoogeveen
2016 B conf
SOFSEM
Marjan van den Akker, Hans L. Bodlaender, Thomas C. van Dijk, Han Hoogeveen, Erik van Ommeren
2016 C conf
MIG
Arne Hillebrand, Marjan van den Akker, Roland Geraerts, Han Hoogeveen
2013 B conf
SEA
Marjan van den Akker, Kevin van Blokland, Han Hoogeveen
2012 J jnl
Oper. Res. Lett.
Han Hoogeveen, Vincent T'kindt
2012 J jnl
Eur. J. Oper. Res.
Han Hoogeveen, Christophe Lenté, Vincent T'kindt
2011 J jnl
Comput. Oper. Res.
Marnix Kammer, Marjan van den Akker, Han Hoogeveen
2010 C conf
MIG
Marjan van den Akker, Roland Geraerts, Han Hoogeveen, Corien Prins
2008 C conf
ATMOS
Guido Diepen, Marjan van den Akker, Han Hoogeveen
2008 J jnl
J. Sched.
Marjan van den Akker, Han Hoogeveen
2006 J jnl
J. Sched.
Han Hoogeveen, Linda van Norden, Steef L. van de Velde
2006 J jnl
Oper. Res. Lett.
T. C. Edwin Cheng, Yong He, Han Hoogeveen, Min Ji, Gerhard J. Woeginger
2005 conf
Algorithms for Optimization with Incomplete Information
Han Hoogeveen, Marjan van den Akker
2005 J jnl
INFORMS J. Comput.
Ann Vandevelde, Han Hoogeveen, Cor A. J. Hurkens, Jan Karel Lenstra
2005 J jnl
Eur. J. Oper. Res.
Han Hoogeveen
2004 J jnl
J. Sched.
Han Hoogeveen
2004 J jnl
J. Sched.
Wenci Yu, Han Hoogeveen, Jan Karel Lenstra
2004 ch.
Handbook of Scheduling
Marjan van den Akker, Han Hoogeveen
2003 J jnl
Math. Program.
Han Hoogeveen, Martin Skutella, Gerhard J. Woeginger
2003 J jnl
Oper. Res. Lett.
Sixiang Hou, Han Hoogeveen
2003 J jnl
Oper. Res. Lett.
Marjan van den Akker, Han Hoogeveen, Gerhard J. Woeginger
2002 J jnl
INFORMS J. Comput.
Marjan van den Akker, Han Hoogeveen, Steef L. van de Velde
2002 J jnl
Computing
Han Hoogeveen, Gerhard J. Woeginger
2001 J jnl
Oper. Res. Lett.
Han Hoogeveen, Gerhard J. Woeginger
2001 J jnl
INFORMS J. Comput.
Han Hoogeveen, Petra Schuurman, Gerhard J. Woeginger
2000 J jnl
SIAM J. Discret. Math.
Han Hoogeveen, Arjen P. A. Vestjens
2000 J jnl
Oper. Res. Lett.
Han Hoogeveen, Chris N. Potts, Gerhard J. Woeginger
2000 A conf
ESA
Han Hoogeveen, Martin Skutella, Gerhard J. Woeginger
2000 A conf
ESA
Marjan van den Akker, Han Hoogeveen, Nodari Vakhania
1998 B conf
IPCO
Han Hoogeveen, Petra Schuurman, Gerhard J. Woeginger
1998 J jnl
Math. Program.
Han Hoogeveen, Steef L. van de Velde
1997 J jnl
INFORMS J. Comput.
Han Hoogeveen, Steef L. van de Velde
1996 B conf
IPCO
Han Hoogeveen, Tsuyoshi Kawaguchi
1996 B conf
IPCO
Han Hoogeveen, Arjen P. A. Vestjens
1996 J jnl
J. Algorithms
Han Hoogeveen
1995 B conf
IPCO
Han Hoogeveen, Steef L. van de Velde
1991 J jnl
J. Graph Theory
Gerard Sierksma, Han Hoogeveen
tests/unit/test_decompile_similarity.py
← Index tests/unit/test_decompile_similarity.py python
"""Unit tests for similarity modules:
- bninja/similarity/minhashcustom.py
- bninja/similarity/minhasher.py
"""
import numpy as np
import pytest

from redb.extractors.decompiler.bninja.similarity.minhashcustom import MinHashCustom
from redb.extractors.decompiler.bninja.analysis.low_level_normalization import LowLevelNormalization


# ============================================================================
# 2a. MinHashCustom
# ============================================================================

class TestMinHashCustomInit:
    def test_init_empty(self):
        mh = MinHashCustom()
        assert not mh.hasMinHash()
        assert mh.minhash == b""
        assert mh.minhash_int == []

    def test_init_from_signature(self):
        sig = [10, 20, 30, 40]
        mh = MinHashCustom(minhash_signature=sig)
        assert mh.hasMinHash()
        assert mh.minhash_int == sig

    def test_init_from_bytes_uint32(self):
        """Verify round-trip: ints -> bytes -> MinHashCustom -> ints."""
        sig = [100, 200, 300]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        # np.frombuffer returns numpy scalars; setMinHash does % 2**32 which
        # overflows numpy uint32, so verify the raw bytes round-trip instead.
        raw_arr = np.frombuffer(packed, dtype=np.uint32)
        assert list(raw_arr) == sig

    def test_init_from_bytes_uint8(self):
        """Verify round-trip: ints -> bytes -> back."""
        sig = [10, 20, 30]
        packed = np.array(sig, dtype=np.uint8).tobytes()
        raw_arr = np.frombuffer(packed, dtype=np.uint8)
        assert list(raw_arr) == sig

    def test_init_both_raises(self):
        sig = [1, 2, 3]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        with pytest.raises(ValueError, match="only one"):
            MinHashCustom(minhash_bytes=packed, minhash_signature=sig)


class TestMinHashCustomSetGet:
    def test_set_and_get_minhash(self):
        mh = MinHashCustom()
        sig = [5, 10, 15]
        mh.setMinHash(sig)
        raw = mh.getMinHash()
        assert raw == np.array(sig, dtype=np.uint32).tobytes()
        assert mh.getMinHashInt() == sig

    def test_minhash_int_truncation(self):
        mh = MinHashCustom(minhash_bits=8)
        # Values > 256 should be truncated mod 2^8
        mh.setMinHash([300, 500, 256])
        for val in mh.minhash_int:
            assert 0 <= val < 256


class TestMinHashCustomHashData:
    def test_hash_data_string(self):
        result = MinHashCustom.hashData("hello", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_bytes(self):
        result = MinHashCustom.hashData(b"bytes", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_list(self):
        result = MinHashCustom.hashData([1, 2, 3], 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_unsupported_type(self):
        with pytest.raises(NotImplementedError, match="Type not supported"):
            MinHashCustom.hashData(123, 42)

    def test_hash_data_deterministic(self):
        assert MinHashCustom.hashData("test", 7) == MinHashCustom.hashData("test", 7)


class TestMinHashCustomScore:
    def test_score_identical(self):
        sig = [1, 2, 3, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig)
        mh2 = MinHashCustom(minhash_signature=sig)
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score == 100.0

    def test_score_different(self):
        mh1 = MinHashCustom(minhash_signature=[1, 2, 3, 4, 5])
        mh2 = MinHashCustom(minhash_signature=[6, 7, 8, 9, 10])
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score < 100.0

    def test_score_against(self):
        sig1 = [1, 2, 3, 4, 5]
        sig2 = [1, 2, 99, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig1)
        mh2 = MinHashCustom(minhash_signature=sig2)
        instance_score = mh1.scoreAgainst(mh2)
        static_score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert instance_score == static_score


class TestMinHashCustomBitModes:
    def test_8bit_mode(self):
        mh = MinHashCustom(minhash_bits=8)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint8)
        assert list(arr) == [10, 20, 30]

    def test_32bit_mode(self):
        mh = MinHashCustom(minhash_bits=32)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint32)
        assert list(arr) == [10, 20, 30]


# ============================================================================
# 2b. MinHasher
# ============================================================================


class MockILNode:
    """Mock IL node with operation and operands for normalization."""
    def __init__(self, operation, operands=None):
        self.operation = operation
        self.operands = operands or []


class MockLLILBasicBlock:
    """Mock LLIL basic block that yields IL instructions."""
    def __init__(self, instructions):
        self._instructions = instructions

    def __iter__(self):
        return iter(self._instructions)


class MockLLILFunction:
    """Mock LLIL function with basic blocks."""
    def __init__(self, basic_blocks):
        self.basic_blocks = basic_blocks


# Import MinHasher after we know the module can handle the import
from redb.extractors.decompiler.bninja.similarity.minhasher import (
    MinHasher,
    MINHASH_SIGNATURE_LENGTH,
    MINHASH_SIGNATURE_BITS,
)


class TestMinHasherMakeNgrams:
    def setup_method(self):
        # Create a minimal minhasher with a mock LLIL function
        empty_func = MockLLILFunction([])
        self.hasher = MinHasher(seed=42, il_function=empty_func)

    def test_make_ngrams_basic(self):
        result = self.hasher.make_ngrams(["a", "b", "c", "d"], n=3)
        assert result == [("a", "b", "c"), ("b", "c", "d")]

    def test_make_ngrams_short_input(self):
        result = self.hasher.make_ngrams(["a", "b"], n=3)
        assert result == []

    def test_make_ngrams_exact_n(self):
        result = self.hasher.make_ngrams(["a", "b", "c"], n=3)
        assert result == [("a", "b", "c")]


class TestMinHasherCalculate:
    def _make_llil_function(self, num_instructions=10):
        """Create a mock LLIL function with enough instructions."""
        instructions = [
            MockILNode(operation=i % 20) for i in range(num_instructions)
        ]
        bb = MockLLILBasicBlock(instructions)
        return MockLLILFunction([bb])

    def test_calculate_minhash_empty_function(self):
        # Function with < 3 LLIL instructions -> empty list
        func = self._make_llil_function(num_instructions=2)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert result == []

    def test_calculate_minhash_deterministic(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=42, il_function=func)
        h2 = MinHasher(seed=42, il_function=func)
        assert h1.calculateMinHash() == h2.calculateMinHash()

    def test_calculate_minhash_length(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert len(result) == MINHASH_SIGNATURE_LENGTH

    def test_calculate_minhash_value_range(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        for val in result:
            assert 0 <= val < 2 ** MINHASH_SIGNATURE_BITS

    def test_shingle_hash_deterministic(self):
        func = self._make_llil_function(num_instructions=5)
        hasher = MinHasher(seed=42, il_function=func)
        shingle = ([1, 2], [3, 4], [5, 6])
        assert hasher.shingle_hash(shingle, 99) == hasher.shingle_hash(shingle, 99)

    def test_seed_reproducibility(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=1, il_function=func)
        h2 = MinHasher(seed=2, il_function=func)
        r1 = h1.calculateMinHash()
        r2 = h2.calculateMinHash()
        # Different seeds should (very likely) produce different results
        assert r1 != r2