python3 - <<'PY' import math,random ln2=math.log(2) def f(x): return 0.0 if x<=0 else -x*math.log(x)/ln2 def H(x): return f(x)+f(1-x) target=(3,0.8957,0.5896,0.1762) def obj(v,K): ps=list(v[:K]); ps=[max(x,0) for x in ps]; ss=sum(ps) if ss<1e-9: return -1e9 ps=[x/ss for x in ps] b=[0,0,0,0]; ent=0 for i in range(K): al=min(max(v[K+2*i],0.0001),0.9999); be=min(max(v[K+2*i+1],0.0001),0.9999) ent+=ps[i]*(H(al)+H(be)) b[0]+=ps[i]*al*be; b[1]+=ps[i]*al*(1-be); b[2]+=ps[i]*(1-al)*be; b[3]+=ps[i]*(1-al)*(1-be) err=sum((b[j]-target[j])**2 for j in range(4)) return ent-1000*err def golden(fun,a,b,tol=1e-8): g=(math.sqrt(5)-1)/2 c=b-g*(b-a); d=a+g*(b-a); fc=fun(c); fd=fun(d) while b-a>tol: if fc>fd: b,d,fd=d,c,fc; c=b-g*(b-a); fc=fun(c) else: a,c,fc=c,d,fd; d=a+g*(b-a); fd=fun(d) return (a+b)/2 for K in (2,3): best=None random.seed(2) for st in range(30): v=[random.random() for _ in range(K)]+[random.uniform(.05,.95) for _ in range(2*K)] for it in range(30): for j in range(len(v)): def g(x,j=j): vv=v.copy(); vv[j]=x; return obj(vv,K) v[j]=golden(g,max(0.0001,v[j]-0.5),min(0.9999,v[j]+0.5)) val=obj(v,K) if best is None or val>best[0]: best=(val,v) print(K,best) PY