Kai Cai

67 papers A 3C 5Journal 42Unranked 17
YearRankTypeTitle / Venue / Authors
2026 J jnl
Appl. Soft Comput.
Wei Guo, Hongqiang Sang, Ying Liu, Qingzong Li, Kai Cai
2026 J jnl
CoRR
Yingying Liu, Kuma Fuchiwaki, Kai Cai
2026 J jnl
CoRR
Yuhang Wang, Yuling Shi, Mo Yang, Rongrui Zhang, Shilin He, Heng Lian, Yuting Chen, Siyu Ye, Kai Cai, Xiaodong Gu
2025 J jnl
J. Web Eng.
Yanxia Gong, Kai Cai
2025 J jnl
Int. J. Control
Yingying Liu, Lihua Wu, Renyuan Zhang, Zhaojian Cai, Kai Cai
2025 J jnl
Eur. J. Control
Renyuan Zhang, Junhua Gou, Yabo Zhu, Bei Yang, Kai Cai
2025 J jnl
CoRR
Yingying Liu, Zhaojian Cai, Kai Cai
2025 conf
CCTA
Taiwei Li, Norika Arai, Xun Shen, Kazumune Hashimoto, Kai Cai, Xingguo Zhang, Ye Wang, Pongsathorn Raksincharoensak, Shigemasa Takai
2025 conf
CCTA
Fumiya Kudo, Kai Cai
2025 J jnl
CoRR
Yujia Qin, Yining Ye, Junjie Fang, Haoming Wang, Shihao Liang, Shizuo Tian, Junda Zhang, Jiahao Li, Yunxin Li, Shijue Huang, Wanjun Zhong, Kuanye Li, Jiale Yang, Yu Miao, Woyu Lin, Longxiang Liu, Xu Jiang, Qianli Ma, Jingyu Li, Xiaojun Xiao, Kai Cai, Chuang Li, Yaowei Zheng, Chaolin Jin, Chen Li, Xiao Zhou, Minchao Wang, Haoli Chen, Zhaojian Li, Haihua Yang, Haifeng Liu, Feng Lin, Tao Peng, Xin Liu, Guang Shi
2024 J jnl
Int. J. Intell. Robotics Appl.
Quansheng Jiang, Kai Cai, Shilei Wu, Fengyu Xu
2024 J jnl
Autom.
Renyuan Zhang, Jiahao Wang, Zenghui Wang, Kai Cai
2024 J jnl
CoRR
Renyuan Zhang, Jiale Wu, Junhua Gou, Yabo Zhu, Kai Cai
2022 J jnl
Autom.
Kai Cai, Alessandro Giua, Carla Seatzu
2022 J jnl
Int. J. Control
Renyuan Zhang, Kai Cai
2021 conf
CDC
Sasinee Pruekprasert, Kai Cai
2021 J jnl
CoRR
Sasinee Pruekprasert, Kai Cai
2021 conf
CDC
Renyuan Zhang, Zenghui Wang, Kai Cai
2021 J jnl
CoRR
Renyuan Zhang, Zenghui Wang, Kai Cai
2021 J jnl
Syst. Control. Lett.
Takanobu Imae, Kai Cai
2021 J jnl
CoRR
Shoma Matsui, Kai Cai
2021 J jnl
CoRR
Ting Jiao, Renyuan Zhang, Kai Cai
2020 J jnl
Autom.
Satoshi Kawamura, Kai Cai, Masako Kishida
2019 conf
CASE
Kai Cai, Alessandro Giua, Carla Seatzu
2019 J jnl
Autom.
Yingying Liu, Kai Cai, ZhiWu Li
2019 conf
CDC
Satoshi Kawamura, Kai Cai, Masako Kishida
2019 conf
CDC
Shoma Matsui, Kai Cai
2019 J jnl
CoRR
Shoma Matsui, Kai Cai
2018 J jnl
CoRR
Satoshi Kawamura, Kai Cai
2017 J jnl
CoRR
Yingying Liu, Kai Cai, ZhiWu Li
2017 J jnl
CoRR
Renyuan Zhang, Kai Cai
2017 J jnl
CoRR
Renyuan Zhang, Kai Cai
2017 J jnl
CoRR
Takatoshi Motoyama, Kai Cai
2016 J jnl
CoRR
Kai Cai
2016 J jnl
CoRR
Renyuan Zhang, Kai Cai
2015 J jnl
CoRR
Renyuan Zhang, Kai Cai
2014 J jnl
Electron. Commer. Res. Appl.
Kai Cai, Jinzhong Niu, Simon Parsons
2013 J jnl
CoRR
Kai Cai, Hideaki Ishii
2012 J jnl
Electron. Commer. Res. Appl.
Jinzhong Niu, Kai Cai, Simon Parsons, Maria Fasli, Xin Yao
2012 J jnl
CoRR
Kai Cai, Hideaki Ishii
2012 C conf
ACC
Kai Cai, Hideaki Ishii
2012 J jnl
J. Log. Comput.
Yuqing Tang, Kai Cai, Peter McBurney, Elizabeth Sklar, Simon Parsons
2011 A conf
AAMAS
Simon Parsons, Yuqing Tang, Elizabeth Sklar, Peter McBurney, Kai Cai
2011 J jnl
CoRR
Kai Cai, Hideaki Ishii
2011 C conf
AICCSA
Xiangtao Liu, Kai Cai, Yang Li
2011 conf
CLIMA
Simon Parsons, Yuqing Tang, Kai Cai, Elizabeth Sklar, Peter McBurney
2010 J jnl
CoRR
Jinzhong Niu, Kai Cai, Simon Parsons
2010 conf
AMEC/TADA
Jinzhong Niu, Kai Cai, Simon Parsons
2010 A conf
AAMAS
Jinzhong Niu, Kai Cai, Simon Parsons
2010 J jnl
Wirel. Commun. Mob. Comput.
Chen Chen, Lin Bai, Kai Cai, Jianhua He, Haige Xiang
2010 J jnl
IEEE Trans. Inf. Theory
Kai Cai, Guobiao Weng, Xueqi Cheng
2010 C conf
ACC
Kai Cai, Hideaki Ishii
2010 conf
AMEC/TADA
Kai Cai, Jinzhong Niu, Simon Parsons
2010 C conf
PDCAT
Xiangtao Liu, Tao Meng, Kai Cai, Xueqi Cheng
2010 J jnl
Auton. Agents Multi Agent Syst.
Jinzhong Niu, Kai Cai, Simon Parsons, Peter McBurney, Enrico H. Gerding
2009 J jnl
CoRR
Kai Cai
2008 conf
IAT
Jinzhong Niu, Kai Cai, Peter McBurney, Simon Parsons
2008 conf
AAMAS (2)
Jinzhong Niu, Kai Cai, Simon Parsons, Enrico H. Gerding, Peter McBurney
2008 J jnl
CoRR
Huawei Shen, Xueqi Cheng, Kai Cai, Mao-Bin Hu
2008 conf
AAMAS (Demos)
Jinzhong Niu, Kai Cai, Simon Parsons, Enrico H. Gerding, Peter McBurney, Thierry Moyaux, Steve Phelps, David Shield
2008 conf
AMEC/TADA
Kai Cai, Jinzhong Niu, Simon Parsons
2008 J jnl
EURASIP J. Wirel. Commun. Netw.
Chen Chen, Kai Cai, Haige Xiang
2008 C conf
CSCWD
Weili Kou, Peng Gong, Kai Cai, Jing Wang
2007 conf
Adaptive Agents and Multi-Agents Systems
Steve Phelps, Kai Cai, Peter McBurney, Jinzhong Niu, Simon Parsons, Elizabeth Sklar
2007 conf
AMEC/TADA
Jinzhong Niu, Kai Cai, Simon Parsons, Elizabeth Sklar
2007 conf
Adaptive Agents and Multi-Agents Systems
Kai Cai, Jinzhong Niu, Simon Parsons
2006 A conf
AAMAS
Jinzhong Niu, Kai Cai, Simon Parsons, Elizabeth Sklar
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