如何在ProbLog中表示指定1占比的二进制向量的p事实/规则
ProbLog下二进制随机向量的正确建模方案
基础定义(p-fact/p-rule 实现)
你最开始写的单向量代码是单个向量的正确实现:
% 单向量场景,N=1000,P=20,每个位为1的概率0.02 0.02::one(X) :- between(1,1000,X).
如果需要处理多个向量,必须增加向量ID参数区分不同向量的独立事件,同时支持参数化P/N,完整写法如下:
% 参数化概率规则:第VID个向量的第Bit位为1的概率 = P/N % 入参说明:VID=向量唯一ID,P=期望1的个数,N=向量总长度,Bit=位索引(1~N) {P/N}::vec_bit(VID, P, N, Bit) :- between(1, N, Bit). % 可选:批量定义向量ID,M替换为你需要的向量总数即可 vector_id(VID) :- between(1, M, VID).
该写法同时兼容cplint,逻辑完全一致。
常用向量运算的建模实现
你需要的各类运算可以直接基于上面的基础规则扩展:
- 两个向量对应位AND运算
% 向量V1和V2的第Bit位AND结果为1 vec_and(V1, V2, P, N, Bit) :- vec_bit(V1, P, N, Bit), vec_bit(V2, P, N, Bit).
- 两个向量对应位OR运算
% 向量V1和V2的第Bit位OR结果为1 vec_or(V1, V2, P, N, Bit) :- vec_bit(V1, P, N, Bit). vec_or(V1, V2, P, N, Bit) :- vec_bit(V2, P, N, Bit).
- 两个向量对应位XOR运算
% 向量V1和V2的第Bit位XOR结果为1 vec_xor(V1, V2, P, N, Bit) :- vec_bit(V1, P, N, Bit), \+ vec_bit(V2, P, N, Bit). vec_xor(V1, V2, P, N, Bit) :- \+ vec_bit(V1, P, N, Bit), vec_bit(V2, P, N, Bit).
- 汉明距离计算
% 两个向量V1、V2的汉明距离为Dist hamming_dist(V1, V2, P, N, Dist) :- findall(1, vec_xor(V1, V2, P, N, _Bit), Ones), length(Ones, Dist).
- 多向量OR运算
% 向量列表[V1,V2,...Vk]的OR结果第Bit位为1 multi_or([V|_Rest], P, N, Bit) :- vec_bit(V, P, N, Bit). multi_or([_V|Rest], P, N, Bit) :- multi_or(Rest, P, N, Bit).
- 重叠计数(两个向量同时为1的位数量)
% 向量V1和V2的重叠1的数量为Cnt overlap_cnt(V1, V2, P, N, Cnt) :- findall(1, vec_and(V1, V2, P, N, _Bit), Ones), length(Ones, Cnt).
典型查询场景示例
以你提到的「10个随机向量做OR运算后,和新随机向量的重叠计数」场景为例,完整实现:
% 定义11个向量,N=1000,P=20(每个位概率20/1000=0.02) vector_id(VID) :- between(1, 11, VID). {P/N}::vec_bit(VID, P, N, Bit) :- between(1, N, Bit), vector_id(VID). % 前10个向量的OR结果的第Bit位为1 or_10(P, N, Bit) :- multi_or([1,2,3,4,5,6,7,8,9,10], P, N, Bit). % OR结果和第11个新向量的重叠计数 or_overlap_cnt(P, N, Cnt) :- findall(1, (or_10(P, N, Bit), vec_bit(11, P, N, Bit)), Ones), length(Ones, Cnt). % 查询:重叠计数为5的概率 query(or_overlap_cnt(20, 1000, 5)). % 查询:重叠计数的期望值 query(expected(or_overlap_cnt(20, 1000, Cnt), Cnt)).
你现有代码的问题修正
你之前参考的代码核心错误是把Bit位设为匿名变量,导致所有位共享同一个随机变量,不是独立事件。修正后的prob_on规则如下:
{P/N}::vec_bit(VID, P, N, Bit) :- between(1, N, Bit). % 检查向量1的位列表List1、向量2的位列表List2中所有位都为1的概率 prob_on(List1, List2, P, N) :- maplist(vec_bit(1, P, N), List1), maplist(vec_bit(2, P, N), List2). % 你的查询示例:输出结果为(2/10)*(2/10)=0.04,符合预期 query(prob_on([1], [1], 2, 10)). query(prob_on([1,2,3,5],[1,6,9,2],2,10)).
内容的提问来源于stack exchange,提问作者sten
相关产品推荐
相关产品推荐

