# entanglement in that state and BOUND/BOUND_PPT is the lower bound on the GNM
# that can be achieved using NMIN/NMIN_PPT measurements.
# The difference between (NMIN, BOUND) and (NMIN, BOUNT_PPT) is that in the first
# fully decomposable witnesses are constructed, wheras in the second one fully
# PPT witnesses are used.

import gmntools, numpy
from gmntools import gmn, randomstates, randomlocalmeas

# number of runs
n = 100
subsystems = [2, 2]

# initialize necesarry classes
locmeas = randomlocalmeas(subsystems)
rho = randomstates(subsystems)
GMN = gmn(subsystems)
dim = numpy.prod(numpy.array(subsystems))

for i in range(n):
    GMN.setdensitymatrix(rho.random())
    genneg = rho.negativity([0])
    if genneg > 0:
        meas = []
        for j in range(dim ** 2):
            expvalue = numpy.trace(numpy.dot(rho.matrix, locmeas.random())).real
            meas += [(locmeas.matrix, expvalue)]
        xlow = 0
        xhigh = dim ** 2
        while True:
            x = (xhigh + xlow) / 2
# where GNM is the genuine multipartice negativity of the random state, NMIN is
# the minimal number of measurements necessary to detect genuine multiparticle 
# entanglement in that state and BOUND is the lower bound on the GNM that
# can be achieved using NMIN measurements.

import gmntools, numpy
from gmntools import gmn, randomstates, randomlocalmeas

#number of runs
n = 100
subsystems = [2,2,2]
weight = 0.5 #the maximal weight the mixed state can have in the mixture with the pure one

# initialize necesarry classes
locmeas = randomlocalmeas(subsystems)
rhomixed = randomstates(subsystems)
GMN = gmn(subsystems)
dim = numpy.prod(numpy.array(subsystems))

def randstate(minweight):
	psi = numpy.random.randn(dim) + 1.j*numpy.random.randn(dim)
	p = minweight*numpy.random.rand(1)
	rhopure = numpy.outer(psi.conjugate(),psi)
	rhopure /= numpy.trace(rhopure)
	return (1-p)*rhopure + p*rhomixed.random()

for i in range(n):
	rho = randstate(weight)
	GMN.setdensitymatrix(rho)
	genneg = GMN.gmn(altsolver='dsdp')
	if genneg > 0: