python: Bit Operation Algorithm

项目结构:

image

 

 

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:05 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : bfs_combine.py
"""
BFS+位掩码子集遍历,首饰礼盒最优搭配算法
约束:总价上限、总克重上限,找出价值利用率最高组合
职责:纯算法计算,无业务入参校验
"""
from collections import deque
from domain.entity.jewelry import Jewelry

class BfsJewelryCombiner:
    def __init__(self, jewel_list: list[Jewelry], max_weight: float, max_price: float):
        self.jewels = jewel_list
        self.n = len(jewel_list)
        self.max_w = max_weight
        self.max_p = max_price

    def search_best_combine(self) -> tuple[list[str], float, float]:
        """
        返回:选中首饰ID列表、总重量、总价格
        """
        best_mask = 0
        best_value = 0
        queue = deque()
        queue.append((0, 0.0, 0.0))

        while queue:
            mask, cur_w, cur_p = queue.popleft()
            # 计算当前组合价值
            cur_value = cur_p / cur_w if cur_w != 0 else 0
            if cur_value > best_value:
                best_value = cur_value
                best_mask = mask
            # 扩展子集
            for idx in range(self.n):
                if not (mask & (1 << idx)):
                    new_mask = mask | (1 << idx)
                    new_w = cur_w + self.jewels[idx].weight
                    new_p = cur_p + self.jewels[idx].price
                    if new_w <= self.max_w and new_p <= self.max_p:
                        queue.append((new_mask, new_w, new_p))
        # 解析掩码
        select_ids = []
        total_w = 0.0
        total_p = 0.0
        for i in range(self.n):
            if best_mask & (1 << i):
                select_ids.append(self.jewels[i].jewel_id)
                total_w += self.jewels[i].weight
                total_p += self.jewels[i].price
        return select_ids, total_w, total_p


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:05 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : bit_array.py
"""
位图BitArray:极致内存压缩,千万级ID查重、假货黑名单批量过滤
1bit标记一个首饰ID存在状态,1000万数据仅占用约1.2MB内存
"""
class BitArray:
    def __init__(self, size: int):
        self.size = size
        self._array = bytearray((size + 7) // 8)

    def set(self, index: int):
        """
        标记索引为存在
        :param index:
        :return:
        """
        if 0 <= index < self.size:
            pos = index // 8
            bit = index % 8
            self._array[pos] |= (1 << bit)

    def unset(self, index: int):
        """
        标记索引为不存在
        :param index:
        :return:
        """
        if 0 <= index < self.size:
            pos = index // 8
            bit = index % 8
            self._array[pos] &= ~(1 << bit)

    def get(self, index: int) -> bool:
        """
        查询是否存在
        :param index:
        :return:
        """
        if 0 <= index < self.size:
            pos = index // 8
            bit = index % 8
            return (self._array[pos] & (1 << bit)) != 0
        return False

    def batch_check(self, index_list: list[int]) -> list[bool]:
        """
        批量查询
        :param index_list:
        :return:
        """
        return [self.get(idx) for idx in index_list]

    def batch_set(self, index_list: list[int]):
        """
        批量标记
        :param index_list:
        :return:
        """
        for idx in index_list:
            self.set(idx)


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:05 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : gale_shapley.py
"""
Gale-Shapley稳定婚配算法
结合位掩码计算偏好匹配度,用于导购-客户双向稳定匹配
职责:只实现匹配数学逻辑,不介入业务流程编排
"""
from domain.entity.customer import Customer
from domain.entity.guide import Guide

class GaleShapleyMatcher:
    def __init__(self, guide_list: list[Guide], customer_list: list[Customer]):
        self.guides = guide_list
        self.customers = customer_list
        self.guide_dict = {g.guide_id: g for g in guide_list}
        self.customer_dict = {c.customer_id: c for c in customer_list}
        # 匹配缓存
        self.guide_match = dict()
        self.customer_match = dict()
        # 导购待追求客户指针
        self.guide_ptr = {g.guide_id: 0 for g in guide_list}

    def _get_customer_rank(self, guide: Guide, customer_id: str) -> int:
        """
        导购视角客户优先级排序
        :param guide:
        :param customer_id:
        :return:
        """
        return guide.customer_priority.index(customer_id)

    def _get_guide_rank(self, customer: Customer, guide_id: str) -> int:
        """
        客户视角导购优先级:匹配度越高排名越靠前
        :param customer:
        :param guide_id:
        :return:
        """
        guide = self.guide_dict[guide_id]
        score = customer.match_score(guide.skill_mask)
        return -score

    def match(self) -> dict:
        """
        执行稳定匹配,返回{客户ID:导购ID}
        :return:
        """
        free_guides = [g.guide_id for g in self.guides]
        while free_guides:
            g_id = free_guides.pop(0)
            guide = self.guide_dict[g_id]
            ptr = self.guide_ptr[g_id]
            if ptr >= len(guide.customer_priority):
                continue
            c_id = guide.customer_priority[ptr]
            self.guide_ptr[g_id] += 1
            customer = self.customer_dict[c_id]

            # 客户单身,直接配对
            if c_id not in self.customer_match:
                self.guide_match[g_id] = c_id
                self.customer_match[c_id] = g_id
            else:
                old_g_id = self.customer_match[c_id]
                # 对比新旧导购,客户选择更优
                if self._get_guide_rank(customer, g_id) < self._get_guide_rank(customer, old_g_id):
                    self.guide_match[g_id] = c_id
                    self.customer_match[c_id] = g_id
                    del self.guide_match[old_g_id]
                    free_guides.append(old_g_id)
                else:
                    free_guides.append(g_id)
        return self.customer_match


from api.match_api import api_match_guide_customer
from api.combine_api import api_get_jewelry_combine
from api.inventory_filter_api import api_create_filter_service
from domain.entity.customer import Customer
from domain.entity.guide import Guide
from domain.entity.jewelry import Jewelry
from domain.valueobject.bit_mask import PreferenceBitMask
from domain.domain_rule.match_rule import MatchDomainRule

if __name__ == "__main__":
    # ========== 测试1:GS导购客户匹配(规则校验生效) ==========
    # 构造离岗导购
    g1 = Guide("G001", PreferenceBitMask.DIAMOND | PreferenceBitMask.GOLD | MatchDomainRule.GUIDE_OFFLINE_MASK, ["C001", "C002"])
    g2 = Guide("G002", PreferenceBitMask.JADE | PreferenceBitMask.PEARL | (1<<28), ["C002", "C001"])
    c1 = Customer("C001", PreferenceBitMask.DIAMOND | PreferenceBitMask.HIGH_PRICE, ["G001", "G002"])
    c2 = Customer("C002", PreferenceBitMask.JADE, ["G002", "G001"])
    match_result = api_match_guide_customer([g1, g2], [c1, c2])
    print("===导购客户稳定匹配结果(带规则校验)===")
    print(match_result)

    # ========== 测试2:BFS首饰搭配(材质互斥规则校验) ==========
    jewel_data = [
        Jewelry("J001", PreferenceBitMask.GOLD, 2.2, 1280),
        Jewelry("J002", PreferenceBitMask.PLATINUM, 1.5, 2680), # 铂金,和黄金互斥
        Jewelry("J003", PreferenceBitMask.PEARL, 1.1, 890),
        Jewelry("J004", PreferenceBitMask.K_GOLD, 2.8, 1660),
    ]
    combine_res = api_get_jewelry_combine(jewel_data, max_w=5.0, max_p=4000)
    print("\n===首饰最优搭配(互斥规则校验)===")
    print(combine_res)

    # ========== 测试3:位图查重+黑名单过滤 ==========
    filter_service = api_create_filter_service(10000000)
    filter_service.register_jewel_index("J001", 1)
    filter_service.register_jewel_index("J002", 2)
    filter_service.batch_mark_inventory(["J001", "J002"])
    repeat = filter_service.check_repeat(["J001", "J005"])
    filter_service.blacklist.add_fake("J999")
    safe = filter_service.filter_blacklist(["J001", "J999"])
    print("\n===库存查重结果===")
    print(repeat)
    print("===过滤黑名单合法商品===")
    print(safe)


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:35 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : match_rule.py
"""
导购-客户匹配 领域约束规则
DDD定位:领域业务规则,仅负责匹配前置合法性校验、硬性门槛判断
职责:
1. 校验导购/客户实体合法性
2. 匹配准入门槛约束(在岗、会员等级、品类承接限制)
3. 禁止跨约束匹配的判定
无算法实现、无业务流程编排、无存储读写
"""
from domain.entity.customer import Customer
from domain.entity.guide import Guide
from domain.valueobject.bit_mask import PreferenceBitMask

class MatchDomainRule:
    # 全局匹配硬性常量约束
    # 导购离岗标记位
    GUIDE_OFFLINE_MASK = 1 << 30
    # 客户黑名单标记位
    CUSTOMER_BLACK_MASK = 1 << 31
    # 高奢品类必须资深导购承接掩码
    LUXURY_MASK = PreferenceBitMask.HIGH_PRICE | PreferenceBitMask.DIAMOND

    @staticmethod
    def is_guide_valid(guide: Guide) -> tuple[bool, str]:
        """
        校验导购是否可参与匹配
        :return: (是否合法, 不合法原因)
        """
        if not isinstance(guide, Guide):
            return False, "实体类型错误,非导购Guide对象"
        if not guide.guide_id or len(guide.guide_id.strip()) == 0:
            return False, "导购ID不能为空"
        if len(guide.customer_priority) == 0:
            return False, "导购未配置客户接待优先级列表,无法参与匹配"
        # 判定导购离岗
        if (guide.skill_mask & MatchDomainRule.GUIDE_OFFLINE_MASK) != 0:
            return False, f"导购[{guide.guide_id}]当前离岗,禁止分配客户"
        return True, "导购校验通过"

    @staticmethod
    def is_customer_valid(customer: Customer) -> tuple[bool, str]:
        """
        校验客户是否可参与匹配
        :param customer:
        :return:
        """
        if not isinstance(customer, Customer):
            return False, "实体类型错误,非客户Customer对象"
        if not customer.customer_id or len(customer.customer_id.strip()) == 0:
            return False, "客户ID不能为空"
        if len(customer.priority_list) == 0:
            return False, "客户未配置导购偏好优先级,无法参与匹配"
        # 客户黑名单拦截
        if (customer.preference_mask & MatchDomainRule.CUSTOMER_BLACK_MASK) != 0:
            return False, f"客户[{customer.customer_id}]处于黑名单,禁止分配导购接待"
        return True, "客户校验通过"

    @staticmethod
    def check_luxury_match_limit(guide: Guide, customer: Customer) -> tuple[bool, str]:
        """
        高奢业务强制约束:选购钻石/高价奢侈品客户,仅资深导购可承接
        :param guide:
        :param customer:
        :return:
        """
        customer_need_luxury = (customer.preference_mask & MatchDomainRule.LUXURY_MASK) != 0
        if not customer_need_luxury:
            return True, "非高奢需求,无导购等级限制"
        # 用高位bit标记导购资深身份
        senior_tag = 1 << 28
        if (guide.skill_mask & senior_tag) == 0:
            return False, f"客户[{customer.customer_id}]存在高奢需求,导购[{guide.guide_id}]非资深导购,禁止匹配"
        return True, "高奢需求匹配资格校验通过"

    @staticmethod
    def batch_check_match_entrance(guide_list: list[Guide], customer_list: list[Customer]) -> tuple[list[Guide], list[Customer], list[str]]:
        """
        批量准入校验,过滤不合格导购、客户,返回合法集合+异常日志
        :return: 合法导购列表、合法客户列表、异常描述列表
        :param guide_list:
        :param customer_list:
        :return:
        """
        valid_guides = []
        valid_customers = []
        error_logs = []

        for guide in guide_list:
            ok, msg = MatchDomainRule.is_guide_valid(guide)
            if ok:
                valid_guides.append(guide)
            else:
                error_logs.append(f"导购过滤:{msg}")

        for customer in customer_list:
            ok, msg = MatchDomainRule.is_customer_valid(customer)
            if ok:
                valid_customers.append(customer)
            else:
                error_logs.append(f"客户过滤:{msg}")

        return valid_guides, valid_customers, error_logs


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:04 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : blacklist.py
"""
假货黑名单实体:假货编码集合
"""
class BlackList:
    def __init__(self):
        self.fake_ids: set[str] = set()

    def add_fake(self, jewel_id: str):
        self.fake_ids.add(jewel_id)

    def batch_add(self, id_list: list[str]):
        self.fake_ids.update(id_list)


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:04 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : customer.py
"""
客户领域实体:唯一ID、偏好掩码、优先级清单
"""
from domain.valueobject.bit_mask import PreferenceBitMask

class Customer:
    """

    """

    def __init__(self, customer_id: str, preference_mask: int, priority_list: list[str]):
        self.customer_id = customer_id
        self.preference_mask: int = preference_mask  # 位掩码偏好
        self.priority_list: list[str] = priority_list  # 个人偏好优先级(GS算法排序依据)

    def match_score(self, guide_preference_mask: int) -> int:
        """
        计算和导购偏好重合度(重合bit数量)
        :param guide_preference_mask:
        :return:
        """
        same_bits = self.preference_mask & guide_preference_mask
        return bin(same_bits).count("1")

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:04 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : guide.py
"""
导购领域实体:擅长品类掩码、客户接待优先级清单
"""
class Guide:
    def __init__(self, guide_id: str, skill_mask: int, customer_priority: list[str]):
        self.guide_id = guide_id
        self.skill_mask: int = skill_mask
        self.customer_priority: list[str] = customer_priority

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:07 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : jewelry.py
"""
首饰实体:唯一编码、材质掩码、重量、单价、搭配分组标记
"""
class Jewelry:
    def __init__(self, jewel_id: str, mask: int, weight: float, price: float, group_tag: int = 0):
        self.jewel_id = jewel_id
        self.mask = mask
        self.weight = weight
        self.price = price
        self.group_tag = group_tag

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:03 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : bit_mask.py
"""
值对象:首饰品类、材质、风格偏好固定比特定义,全局唯一
1bit=1个偏好标签,64bit支持64类偏好,可无限扩容
"""
class PreferenceBitMask:
    # 材质掩码
    GOLD = 1 << 0
    K_GOLD = 1 << 1
    PLATINUM = 1 << 2
    DIAMOND = 1 << 3
    JADE = 1 << 4
    PEARL = 1 << 5
    RUBY = 1 << 6
    SAPPHIRE = 1 << 7

    # 风格掩码
    LUXURY = 1 << 10
    SIMPLE = 1 << 11
    RETRO = 1 << 12
    MINIMALIST = 1 << 13

    # 价位档位掩码
    LOW_PRICE = 1 << 20
    MID_PRICE = 1 << 21
    HIGH_PRICE = 1 << 22

    @classmethod
    def get_all_masks(cls) -> dict:
        """获取全部掩码字典,用于解码"""
        attr_dict = {}
        for attr in dir(cls):
            if not attr.startswith("__") and isinstance(getattr(cls, attr), int):
                attr_dict[attr] = getattr(cls, attr)
        return attr_dict

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:02 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : bit_helper.py
"""
底层位运算通用工具类,基础设施层,仅提供基础原子操作
职责:位与、或、异或、掩码生成、子集遍历、位判断,无业务逻辑
"""
class BitHelper:
    @staticmethod
    def add_mask(source: int, mask: int) -> int:
        """
        添加标记 或运算
        :param source:
        :param mask:
        :return:
        """
        return source | mask

    @staticmethod
    def remove_mask(source: int, mask: int) -> int:
        """
        移除标记 与取反
        :param source:
        :param mask:
        :return:
        """
        return source & (~mask)

    @staticmethod
    def has_mask(source: int, mask: int) -> bool:
        """
        判断是否包含指定标记
        :param source:
        :param mask:
        :return:
        """
        return (source & mask) == mask

    @staticmethod
    def has_any_mask(source: int, mask_list: list[int]) -> bool:
        """
        包含任意一个掩码
        :param source:
        :param mask_list:
        :return:
        """
        union_mask = 0
        for m in mask_list:
            union_mask |= m
        return (source & union_mask) > 0

    @staticmethod
    def get_all_sub_mask(max_len: int):
        """
        生成0~2^n-1所有子集掩码迭代器
        :param max_len:
        :return:
        """
        for mask in range(0, 1 << max_len):
            yield mask


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:02 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : base_storage.py
"""
仓储顶层抽象,依赖倒置,领域层不依赖具体存储实现
"""
from abc import ABC, abstractmethod

class BaseStorage(ABC):
    @abstractmethod
    def save(self, key, value):
        pass

    @abstractmethod
    def get(self, key):
        pass

    @abstractmethod
    def batch_save(self, data_dict: dict):
        pass

    @abstractmethod
    def batch_exist_check(self, keys: list) -> list[bool]:
        pass

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:03 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : memory_storage.py
from infrastructure.storage.base_storage import BaseStorage

class MemoryStorage(BaseStorage):
    def __init__(self):
        self._data_map = dict()

    def save(self, key, value):
        self._data_map[key] = value

    def get(self, key):
        return self._data_map.get(key, None)

    def batch_save(self, data_dict: dict):
        self._data_map.update(data_dict)

    def batch_exist_check(self, keys: list) -> list[bool]:
        return [k in self._data_map for k in keys]

  

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:08 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : combine_api.py
from application.combine_app_service import JewelryCombineAppService
from domain.entity.jewelry import Jewelry

combine_service = JewelryCombineAppService()

def api_get_jewelry_combine(jewel_list: list[Jewelry], max_w: float, max_p: float):
    """

    :param jewel_list:
    :param max_w:
    :param max_p:
    :return:
    """
    return combine_service.get_best_combine(jewel_list, max_w, max_p)

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:09 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : inventory_filter_api.py
from application.inventory_app_service import InventoryFilterAppService

def api_create_filter_service(max_size: int) -> InventoryFilterAppService:
    """

    :param max_size:
    :return:
    """

    return InventoryFilterAppService(max_size)


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:08 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : match_api.py
from application.match_app_service import GuideCustomerMatchAppService
from domain.entity.customer import Customer
from domain.entity.guide import Guide

match_service = GuideCustomerMatchAppService()

def api_match_guide_customer(guides: list[Guide], customers: list[Customer]) -> dict:
    """

    :param guides:
    :param customers:
    :return:
    """
    return match_service.do_match(guides, customers)

# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:06 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : combine_app_service.py
from domain.algorithm.bfs_combine import BfsJewelryCombiner
from domain.entity.jewelry import Jewelry
from domain.domain_rule.combine_rule import CombineDomainRule

class JewelryCombineAppService:
    """

    """
    def get_best_combine(self, jewel_list: list[Jewelry], max_weight: float, max_price: float):
        """

        :param jewel_list:
        :param max_weight:
        :param max_price:
        :return:
        """
        # 1、领域规则:过滤合法首饰
        valid_jewels, err_log = CombineDomainRule.batch_filter_available_jewels(jewel_list)
        if len(valid_jewels) == 0:
            return {
                "code": -1,
                "msg": "无合法首饰可搭配",
                "error": err_log,
                "select_jewel_ids": [],
                "total_weight": 0,
                "total_price": 0
            }
        # 2、BFS算法计算最优组合
        combiner = BfsJewelryCombiner(valid_jewels, max_weight, max_price)
        ids, w, p = combiner.search_best_combine()

        # 3、组装组合掩码,做最终全量合规校验
        combine_mask = 0
        select_jewel_obj = []
        for j in valid_jewels:
            if j.jewel_id in ids:
                combine_mask |= j.mask
                select_jewel_obj.append(j)
        check_ok, check_msg = CombineDomainRule.full_combine_check(combine_mask, select_jewel_obj, w, p, max_weight, max_price)

        return {
            "code": 0 if check_ok else -2,
            "msg": check_msg if not check_ok else "搭配方案合规",
            "filter_error": err_log,
            "select_jewel_ids": ids,
            "total_weight": round(w, 2),
            "total_price": round(p, 2)
        }


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:08 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : inventory_app_service.py
from domain.algorithm.bit_array import BitArray
from domain.entity.blacklist import BlackList

class InventoryFilterAppService:
    def __init__(self, max_inventory_num: int):
        self.bit_array = BitArray(max_inventory_num)
        self.blacklist = BlackList()
        self.id_index_map = dict()
        self.index_id_map = dict()

    def register_jewel_index(self, jewel_id: str, idx: int):
        """
        首饰ID与位图索引绑定
        :param jewel_id:
        :param idx:
        :return:
        """
        self.id_index_map[jewel_id] = idx
        self.index_id_map[idx] = jewel_id

    def batch_mark_inventory(self, id_list: list[str]):
        """
        批量标记在库首饰
        :param id_list:
        :return:
        """
        idx_list = [self.id_index_map[i] for i in id_list if i in self.id_index_map]
        self.bit_array.batch_set(idx_list)

    def check_repeat(self, check_ids: list[str]) -> list[tuple[str, bool]]:
        """
        查重:True=已存在重复
        :param check_ids:
        :return:
        """
        res = []
        for jid in check_ids:
            idx = self.id_index_map.get(jid, -1)
            exist = self.bit_array.get(idx) if idx != -1 else False
            res.append((jid, exist))
        return res

    def filter_blacklist(self, check_ids: list[str]) -> list[str]:
        """
        过滤黑名单,返回合法首饰ID
        :param check_ids:
        :return:
        """
        safe_list = [jid for jid in check_ids if jid not in self.blacklist.fake_ids]
        return safe_list


# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:06 
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : match_app_service.py
"""
应用服务:编排GS算法、实体组装、参数预处理,不写核心算法
"""

from domain.algorithm.gale_shapley import GaleShapleyMatcher
from domain.entity.customer import Customer
from domain.entity.guide import Guide
from domain.domain_rule.match_rule import MatchDomainRule

class GuideCustomerMatchAppService:
    """

    """
    def do_match(self, guide_list: list[Guide], customer_list: list[Customer]) -> dict:
        """

        :param guide_list:
        :param customer_list:
        :return:
        """
        # 1. 执行领域前置约束校验
        valid_guides, valid_customers, error_logs = MatchDomainRule.batch_check_match_entrance(guide_list, customer_list)
        # 无合法对象直接返回空
        if len(valid_guides) == 0 or len(valid_customers) == 0:
            return {"code": -1, "msg": "无合法导购/客户,匹配终止", "error": error_logs, "match_result": {}}
        # 2. 执行GS算法匹配
        matcher = GaleShapleyMatcher(valid_guides, valid_customers)
        raw_result = matcher.match()
        # 3. 返回结构化结果
        return {
            "code": 0,
            "msg": "匹配成功",
            "error_log": error_logs,
            "match_data": raw_result
        }

  

调用:

# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Bit Operation Algorithm
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/8/4 22:02
# User      :  geovindu
# Product   : PyCharm
# Project   : PyBitOperation
# File      : main.py

from api.match_api import api_match_guide_customer
from api.combine_api import api_get_jewelry_combine
from api.inventory_filter_api import api_create_filter_service
from domain.entity.customer import Customer
from domain.entity.guide import Guide
from domain.entity.jewelry import Jewelry
from domain.valueobject.bit_mask import PreferenceBitMask
from domain.domain_rule.match_rule import MatchDomainRule

if __name__ == "__main__":
    # ========== 测试1:GS导购客户匹配(规则校验生效) ==========
    # 构造离岗导购
    g1 = Guide("G001", PreferenceBitMask.DIAMOND | PreferenceBitMask.GOLD | MatchDomainRule.GUIDE_OFFLINE_MASK, ["C001", "C002"])
    g2 = Guide("G002", PreferenceBitMask.JADE | PreferenceBitMask.PEARL | (1<<28), ["C002", "C001"])
    c1 = Customer("C001", PreferenceBitMask.DIAMOND | PreferenceBitMask.HIGH_PRICE, ["G001", "G002"])
    c2 = Customer("C002", PreferenceBitMask.JADE, ["G002", "G001"])
    match_result = api_match_guide_customer([g1, g2], [c1, c2])
    print("===导购客户稳定匹配结果(带规则校验)===")
    print(match_result)

    # ========== 测试2:BFS首饰搭配(材质互斥规则校验) ==========
    jewel_data = [
        Jewelry("J001", PreferenceBitMask.GOLD, 2.2, 1280),
        Jewelry("J002", PreferenceBitMask.PLATINUM, 1.5, 2680), # 铂金,和黄金互斥
        Jewelry("J003", PreferenceBitMask.PEARL, 1.1, 890),
        Jewelry("J004", PreferenceBitMask.K_GOLD, 2.8, 1660),
    ]
    combine_res = api_get_jewelry_combine(jewel_data, max_w=5.0, max_p=4000)
    print("\n===首饰最优搭配(互斥规则校验)===")
    print(combine_res)

    # ========== 测试3:位图查重+黑名单过滤 ==========
    filter_service = api_create_filter_service(10000000)
    filter_service.register_jewel_index("J001", 1)
    filter_service.register_jewel_index("J002", 2)
    filter_service.batch_mark_inventory(["J001", "J002"])
    repeat = filter_service.check_repeat(["J001", "J005"])
    filter_service.blacklist.add_fake("J999")
    safe = filter_service.filter_blacklist(["J001", "J999"])
    print("\n===库存查重结果===")
    print(repeat)
    print("===过滤黑名单合法商品===")
    print(safe)

  

输出:

image

 

posted @ 2026-08-04 22:45  ®Geovin Du Dream Park™  阅读(2)  评论(0)    收藏  举报