File wellmet/convex_hull.py changed (mode: 100644) (index a48c4d2..e8774b9) |
... |
... |
class QHull: |
1221 |
1221 |
) |
) |
1222 |
1222 |
|
|
1223 |
1223 |
|
|
|
1224 |
|
class QHullCubature(QHull): |
|
1225 |
|
|
|
1226 |
|
def get_chi_outside(hull): |
|
1227 |
|
hull._update() |
|
1228 |
|
|
|
1229 |
|
if hull.space != 'G': |
|
1230 |
|
raise |
|
1231 |
|
|
|
1232 |
|
|
|
1233 |
|
integrals = 0 |
|
1234 |
|
# if first time runned |
|
1235 |
|
if 'facets' not in dir(hull): |
|
1236 |
|
hull.facets = facets = dict() |
|
1237 |
|
ncubature = len(hull.tn_scheme.weights) |
|
1238 |
|
hull._x = np.empty((hull.sample.nvar, ncubature)) |
|
1239 |
|
hull._r = np.empty(ncubature) |
|
1240 |
|
hull._result = np.empty(ncubature) |
|
1241 |
|
for indices, normal in zip(hull.simplices, hull.A): |
|
1242 |
|
facet_integral = hull.get_facet_outside(indices, normal) |
|
1243 |
|
facets[indices.tobytes()] = facet_integral |
|
1244 |
|
integrals += facet_integral |
|
1245 |
|
|
|
1246 |
|
return integrals / hull.nsphere_surface_area |
|
1247 |
|
|
|
1248 |
|
facets = hull.facets |
|
1249 |
|
new_facet_dict = dict() |
|
1250 |
|
for indices, normal in zip(hull.simplices, hull.A): |
|
1251 |
|
key = indices.tobytes() |
|
1252 |
|
if key in facets: |
|
1253 |
|
facet_integral = facets[key] |
|
1254 |
|
else: |
|
1255 |
|
facet_integral = hull.get_facet_outside(indices, normal) |
|
1256 |
|
new_facet_dict[key] = facet_integral |
|
1257 |
|
integrals += facet_integral |
|
1258 |
|
|
|
1259 |
|
hull.facets = new_facet_dict |
|
1260 |
|
return integrals / hull.nsphere_surface_area |
|
1261 |
|
|
|
1262 |
|
|
|
1263 |
|
|
|
1264 |
|
|
|
1265 |
|
def get_facet_outside(hull, indices, normal): |
|
1266 |
|
vertices_model = hull.points[indices] |
|
1267 |
|
|
|
1268 |
|
vol = quadpy.tn.get_vol(vertices_model) |
|
1269 |
|
if not np.isfinite(vol): |
|
1270 |
|
print("QHull: Incorrect area has occured in facet %s" % indices) |
|
1271 |
|
return 0 |
|
1272 |
|
|
|
1273 |
|
nvar = len(normal) |
|
1274 |
|
x = hull._x |
|
1275 |
|
r_nvar = hull._r |
|
1276 |
|
result = hull._result |
|
1277 |
|
|
|
1278 |
|
# nvar x n_integration_nodes |
|
1279 |
|
# Transform the points `xi` from the reference simplex onto `simplex`. |
|
1280 |
|
# same as quadpy.tn.transform(hull.tn_scheme.points, vertices_model.T) |
|
1281 |
|
#np.dot(simplex, points) |
|
1282 |
|
np.matmul(vertices_model.T, hull.tn_scheme.points, out=x) |
|
1283 |
|
|
|
1284 |
|
np.einsum('ij,ij->j', x, x, out=result) # r**2 |
|
1285 |
|
np.power(result, nvar/2, out=r_nvar) # r**(nvar-1) (chi) * r (to normalize) |
|
1286 |
|
|
|
1287 |
|
np.divide(result, 2, out=result) # r**2 / 2 |
|
1288 |
|
special.gammaincc(nvar / 2, result, out=result) # F |
|
1289 |
|
|
|
1290 |
|
#č normalizujeme normály. Jenže normály samotné dodáme později |
|
1291 |
|
result /= r_nvar |
|
1292 |
|
|
|
1293 |
|
#č normála |
|
1294 |
|
np.dot(normal, x, out=r_nvar) |
|
1295 |
|
result *= r_nvar |
|
1296 |
|
|
|
1297 |
|
# facet_outside = integral / unit_ball_surface_area |
|
1298 |
|
integral = vol * np.inner(result, hull.tn_scheme.weights) |
|
1299 |
|
if integral > 0: |
|
1300 |
|
return integral |
|
1301 |
|
else: |
|
1302 |
|
print("QHull: Negative value has appeared in facet %s during integration" % indices) |
|
1303 |
|
return 0 |
1224 |
1304 |
|
|
1225 |
1305 |
|
|
1226 |
1306 |
|
|
|
... |
... |
class Grick: |
1460 |
1540 |
|
|
1461 |
1541 |
|
|
1462 |
1542 |
|
|
1463 |
|
QHullCubatureEstimation = namedtuple('QHullCubatureEstimation', ( |
|
1464 |
|
'nvar', |
|
1465 |
|
'nsim', |
|
1466 |
|
'r', 'R', |
|
1467 |
|
'nfacets', |
|
1468 |
|
#'tn_scheme', |
|
1469 |
|
'tn_scheme_points', |
|
1470 |
|
'inside', |
|
1471 |
|
'outside' |
|
1472 |
|
)) |
|
1473 |
|
|
|
1474 |
|
|
|
1475 |
|
class QHullCubature(QHull): |
|
1476 |
|
|
|
1477 |
|
def __init__(hull, sample, tn_scheme, space='G', incremental=True, auto_update=True): |
|
1478 |
|
|
|
1479 |
|
# for now |
|
1480 |
|
#č jednotka dočasnosti - jeden furt |
|
1481 |
|
assert space == 'G' |
|
1482 |
|
|
|
1483 |
|
hull.tn_scheme = tn_scheme |
|
1484 |
|
super().__init__(sample, space, incremental, auto_update) |
|
1485 |
|
|
|
1486 |
|
|
|
1487 |
|
def regen(self): |
|
1488 |
|
points = getattr(self.sample, self.space) |
|
1489 |
|
self.convex_hull = spatial.ConvexHull(points, incremental=self.incremental) |
|
1490 |
|
self.facets = dict() |
|
1491 |
|
|
|
1492 |
|
self.newly_estimated = 0 |
|
1493 |
|
self.newly_invalidated = 0 |
|
1494 |
|
|
|
1495 |
|
simplices = self.convex_hull.simplices |
|
1496 |
|
x_normals = self.convex_hull.equations[:,0] |
|
1497 |
|
|
|
1498 |
|
for indices, normal_x in zip(simplices, x_normals): |
|
1499 |
|
facet = tuple(indices) |
|
1500 |
|
self._integrate_facet(facet, indices, normal_x) |
|
1501 |
|
|
|
1502 |
|
def update(self): |
|
1503 |
|
if self.enough_points and (self.convex_hull.npoints < self.sample.nsim): |
|
1504 |
|
if self.incremental: |
|
1505 |
|
self.__update() |
|
1506 |
|
else: |
|
1507 |
|
self.regen() |
|
1508 |
|
|
|
1509 |
|
|
|
1510 |
|
def get_inside(hull): |
|
1511 |
|
hull._update() |
|
1512 |
|
if hull.enough_points: |
|
1513 |
|
p_inside = mpmath.mpf(0) |
|
1514 |
|
for p_facet in hull.facets.values(): |
|
1515 |
|
p_inside += p_facet |
|
1516 |
|
return p_inside |
|
1517 |
|
else: |
|
1518 |
|
return 0 |
|
1519 |
|
|
|
1520 |
|
|
|
1521 |
|
|
|
1522 |
|
def __update(hull): |
|
1523 |
|
|
|
1524 |
|
hull._hull_update() #č jako vždy, chyby nechytáme |
|
1525 |
|
|
|
1526 |
|
#č podstata problému byla a je v tom, |
|
1527 |
|
#č že numpy neumí pracovat s věktory, případně s submaticemi |
|
1528 |
|
#č jako s celky. Má routiny pouze pro 1D množiny. |
|
1529 |
|
#č Navíc, numpy vektory nejsou hashable, nejde je přímo hodit |
|
1530 |
|
#č ani do setů, ani do slovníků |
|
1531 |
|
#č Nezbyvá nám nic jineho, než prévest ndarray na množinu n-tic. |
|
1532 |
|
|
|
1533 |
|
#č na rozdil od triangulace, zde potřebujeme i normály, aspoň první složku |
|
1534 |
|
#č jenomže výtahnout ji z numpy equations později na zakladě indexů by bylo velmi dráho. |
|
1535 |
|
new_facets = dict(zip((tuple(simplex) for simplex in hull.simplices), hull.equations[:,0])) |
|
1536 |
|
|
|
1537 |
|
# possible naive implementation |
|
1538 |
|
#to_invalidate = sx.simplices_set - new_simplices_set |
|
1539 |
|
#to_estimate = new_simplices_set - sx.simplices_set |
|
1540 |
|
|
|
1541 |
|
facets = hull.facets # dict |
|
1542 |
|
#č vymejšlím, jak by se mohlo ušetřit, |
|
1543 |
|
#č aby se neprobíhala smyčka přes obrovský set na dvakrat |
|
1544 |
|
# Update the set, keeping only elements found in either set, but not in both |
|
1545 |
|
either_facets = new_facets.keys() ^ facets.keys() # set |
|
1546 |
|
to_estimate = either_facets - facets.keys() # set |
|
1547 |
|
to_invalidate = either_facets - to_estimate # set |
|
1548 |
|
|
|
1549 |
|
hull.newly_estimated = len(to_estimate) |
|
1550 |
|
hull.newly_invalidated = len(to_invalidate) |
|
1551 |
|
|
|
1552 |
|
#č invalidace |
|
1553 |
|
for key in to_invalidate: |
|
1554 |
|
del facets[key] |
|
1555 |
|
|
|
1556 |
|
|
|
1557 |
|
for facet in to_estimate: |
|
1558 |
|
indices = np.array(facet) |
|
1559 |
|
normal_x = new_facets[facet] |
|
1560 |
|
hull._integrate_facet(facet, indices, normal_x) |
|
1561 |
|
|
|
1562 |
|
|
|
1563 |
|
|
|
1564 |
|
def _hull_update(self): |
|
1565 |
|
points = getattr(self.sample, self.space) |
|
1566 |
|
self.convex_hull.add_points(points[self.convex_hull.npoints:]) |
|
1567 |
|
|
|
1568 |
|
|
|
1569 |
|
|
|
1570 |
|
def get_convex_hull_estimation(hull): |
|
1571 |
|
inside = hull.get_inside() |
|
1572 |
|
return QHullCubatureEstimation( |
|
1573 |
|
hull.sample.nvar, |
|
1574 |
|
hull.npoints, |
|
1575 |
|
hull.get_r(), hull.get_R(), |
|
1576 |
|
hull.nsimplex, |
|
1577 |
|
#'tn_scheme', |
|
1578 |
|
hull.tn_scheme.points.shape[1], |
|
1579 |
|
float(inside), |
|
1580 |
|
float(1 - inside) |
|
1581 |
|
) |
|
1582 |
|
|
|
1583 |
|
|
|
1584 |
|
def _integrate_facet(hull, facet, indices, normal_x): |
|
1585 |
|
|
|
1586 |
|
|
|
1587 |
|
vertices_model = hull.points[indices] |
|
1588 |
|
|
|
1589 |
|
# nvar x n_integration_nodes |
|
1590 |
|
x = quadpy.tn.transform(hull.tn_scheme.points, vertices_model.T) |
|
1591 |
|
vol = quadpy.tn.get_vol(vertices_model) |
|
1592 |
|
|
|
1593 |
|
if not np.isfinite(vol): |
|
1594 |
|
print("Incorrect volume has occured in simplex %s" % indices) |
|
1595 |
|
hull.facets[facet] = 0 |
|
1596 |
|
return |
|
1597 |
|
|
|
1598 |
|
nvar = hull.sample.nvar |
|
1599 |
|
store = mpmath.mpf(0) |
|
1600 |
|
|
|
1601 |
|
for node, weight in zip(x.T, hull.tn_scheme.weights): |
|
1602 |
|
node_iterator = iter(node) |
|
1603 |
|
node_store = mpmath.ncdf(next(node_iterator)) |
|
1604 |
|
for __ in range(nvar - 1): |
|
1605 |
|
node_store *= mpmath.npdf(next(node_iterator)) |
|
1606 |
|
|
|
1607 |
|
store += node_store * weight |
|
1608 |
|
|
|
1609 |
|
|
|
1610 |
|
if store < 0: |
|
1611 |
|
print("Negative measure has occured in facet %s" % indices) |
|
1612 |
|
hull.facets[facet] = 0 |
|
1613 |
|
return |
|
1614 |
|
|
|
1615 |
|
hull.facets[facet] = store * normal_x * vol |
|
1616 |
|
|
|
1617 |
|
|
|
1618 |
|
|
|
1619 |
|
|
|
1620 |
|
|
|
1621 |
|
|
|
1622 |
|
|
|
1623 |
|
|
|
1624 |
|
|
|
1625 |
1543 |
|
|
|
1544 |
|
|
1626 |
1545 |
|
|
1627 |
1546 |
|
|
File wellmet/dicebox/circumtri.py changed (mode: 100644) (index d633298..f357382) |
... |
... |
class CirQTri(_CircumTri): |
378 |
378 |
|
|
379 |
379 |
def _regen_outside(bx): |
def _regen_outside(bx): |
380 |
380 |
facet_scheme = quadpy.tn.grundmann_moeller(bx.nvar - 1, bx.convex_hull_degree) |
facet_scheme = quadpy.tn.grundmann_moeller(bx.nvar - 1, bx.convex_hull_degree) |
381 |
|
bx.convex_hull = khull.QHull(bx.f_model, space='G', incremental=True, |
|
|
381 |
|
bx.convex_hull = khull.QHullCubature(bx.f_model, space='G', incremental=True, |
382 |
382 |
auto_update=False, tn_scheme=facet_scheme) |
auto_update=False, tn_scheme=facet_scheme) |
383 |
383 |
|
|
384 |
384 |
#č konečně mám pořádnou stejtful třídu |
#č konečně mám pořádnou stejtful třídu |
|
... |
... |
class QTri(_CircumTri, _PsiTri): |
940 |
940 |
|
|
941 |
941 |
def _regen_outside(bx): |
def _regen_outside(bx): |
942 |
942 |
facet_scheme = quadpy.tn.grundmann_moeller(bx.nvar - 1, bx.convex_hull_degree) |
facet_scheme = quadpy.tn.grundmann_moeller(bx.nvar - 1, bx.convex_hull_degree) |
943 |
|
bx.convex_hull = khull.QHull(bx.f_model, space='G', incremental=True, |
|
|
943 |
|
bx.convex_hull = khull.QHullCubature(bx.f_model, space='G', incremental=True, |
944 |
944 |
auto_update=False, tn_scheme=facet_scheme) |
auto_update=False, tn_scheme=facet_scheme) |
945 |
945 |
|
|
946 |
946 |
#č konečně mám pořádnou stejtful třídu |
#č konečně mám pořádnou stejtful třídu |