# -*- coding: utf-8 -*-r""".. _docs-manifold:Manifold========We define an abstract bounded, connected and contractiblecomputational domain (manifold) by calling ``ph.manifold`` method, .. autofunction:: src.manifold.manifoldA common call is>>> manifold = ph.manifold(2)The output, ``manifold``, is an instance of :class:`Manifold`. It is abstract at this stage because we do notspecify any exact parameters, for example size and shape, of it. .. autoclass:: src.manifold.Manifold :members: m, n"""importsysif'./'notinsys.path:sys.path.append('./')fromtools.frozenimportFrozenfromsrc.configimportget_embedding_space_dimfromsrc.configimport_manifold_default_sym_reprfromsrc.configimport_check_sym_reprfromsrc.configimport_parse_lin_reprfromsrc.configimport_manifold_default_lin_reprfromsrc.configimport_manifold_partition_lin_repr_global_manifolds=dict()# all manifolds are cached, and all sym_repr and lin_repr are different.
[docs]defmanifold(ndim,sym_repr=None,lin_repr=None,periodic=False):r"""Generate an abstract manifold. It is actually a wrapper of the ``__init__`` method of :class:`Manifold`. Parameters ---------- ndim : int The dimensions of the manifold. It must be lower than or equal to dimensions of the embedding space. sym_repr : {None, str}, optional The symbolic representation of the manifold. If it is ``None``, we will use a pre-set symbolic representation. The default is ``None``. lin_repr : {None, str}, optional The linguistic representation of the manifold. If it is ``None``, we will use a pre-set linguistic representation. The default is ``None``. periodic : bool, optional If this is set to ``True``, the manifold is a periodic. Otherwise, it is not periodic. The default is ``True``. Returns ------- manifold : :class:`Manifold` The abstract manifold instance. """returnManifold(ndim,sym_repr=sym_repr,lin_repr=lin_repr,periodic=periodic)
[docs]classManifold(Frozen):def__init__(self,ndim,sym_repr=None,lin_repr=None,periodic=False,# means fully periodic# add other representations here.):r""""""embedding_space_ndim=get_embedding_space_dim()assertndim%1==0and0<=ndim<=embedding_space_ndim, \
f"manifold ndim={ndim} is wrong. Is should be an integer and be in range [0, {embedding_space_ndim}]. " \
f"You change change the dimensions of the embedding space using function 'config.set_embedding_space_dim'."self._ndim=ndimifsym_reprisNone:base_repr=_manifold_default_sym_reprnumber_existing_manifolds=len(_global_manifolds)ifnumber_existing_manifolds==0:sym_repr=base_reprelse:sym_repr=base_repr+r'_{'+str(number_existing_manifolds)+'}'else:passsym_repr=_check_sym_repr(sym_repr)iflin_reprisNone:base_repr=_manifold_default_lin_reprnumber_existing_manifolds=len(_global_manifolds)ifnumber_existing_manifolds==0:lin_repr=base_reprelse:lin_repr=base_repr+str(number_existing_manifolds)assertsym_reprnotin_global_manifolds, \
f"Manifold symbolic representation is illegal, pls specify a symbolic representation other than " \
f"{set(_global_manifolds.keys())}"for_in_global_manifolds:_m=_global_manifolds[_]assertlin_repr!=_m._lin_reprlin_repr,pure_lin_repr=_parse_lin_repr('manifold',lin_repr)self._sym_repr=sym_reprself._lin_repr=lin_reprself._pure_lin_repr=pure_lin_repr_global_manifolds[sym_repr]=selfassertisinstance(periodic,bool),f"is_periodic must be bool type."self._is_periodic=periodicself._udg=None# if it has an udg_repr representation.self._boundary=Noneself._inclusion=None# not None for boundary manifold. Will be set when initialize a boundary manifold.self._sub_manifolds={# the sub-manifolds of the same dimensions. Using sym_repr as cache key.self._sym_repr:self}self._partitions={'0':(self,)}self._covered_by_mesh=None# if we have generated an abstract mesh for it, return the meshself._freeze()@propertydefesd(self):r""""""returnget_embedding_space_dim()@propertydefm(self):r"""The dimensions of the embedding space."""returnself.esd@propertydefndim(self):r""""""returnself._ndim@propertydefn(self):r"""The dimensions of the manifold."""returnself.ndim@propertydefudg(self):r""""""returnself._udgdefis_periodic(self):r""""""returnself._is_periodicdef__repr__(self):r""""""super_repr=super().__repr__().split('object')[-1]returnf'<Manifold {self._sym_repr}'+super_repr# this must be unique.defboundary(self,sym_repr=None):r""""""ifself._boundaryisNone:ifself.ndim==0:returnNullManifold('Null')elifself.is_periodic():returnNullManifold(self.ndim-1)else:ifsym_reprisNone:sym_repr=r'\partial'+self._sym_reprself._boundary=Manifold(self.ndim-1,sym_repr=sym_repr,lin_repr=f'boundary-of-{self._pure_lin_repr}',periodic=True,)self._boundary._inclusion=selfreturnself._boundarydefinclusion(self):r""""""returnself._inclusiondefcap(self,other,sym_repr=None):r""""""raiseNotImplementedError()definterface(self,other,sym_repr=None):r""""""raiseNotImplementedError()defpartition(self,*submanifolds_sym_repr,config_name=None):r"""partition of the manifold."""forsym_reprinsubmanifolds_sym_repr:assertisinstance(sym_repr,str),f"please put sym_repr of partitions in str."num_of_partitions=len(submanifolds_sym_repr)assertnum_of_partitions>=2andnum_of_partitions%2==0,f"I need a integer >= 2."partitions=tuple()foriinrange(num_of_partitions):sym_repr=submanifolds_sym_repr[i]ifsym_reprinself._sub_manifolds:passelse:j=len(self._sub_manifolds)while1:lin_repr=self._pure_lin_repr+_manifold_partition_lin_repr+f'{str(j)}'occupied=Falsefor_sub_sym_reprinself._sub_manifolds:iflin_repr==self._sub_manifolds[_sub_sym_repr]:occupied=Trueelse:passifoccupied:j+=1else:breakself._sub_manifolds[sym_repr]=Manifold(self.ndim,sym_repr=sym_repr,lin_repr=lin_repr,)partitions+=(self._sub_manifolds[sym_repr],)ifconfig_nameisNone:i=len(self._partitions)while1:ifstr(i)notinself._partitions:breakelse:i+=1config_name=str(i)else:passpartitions_set=set(partitions)existing=Falseexisting_config=Noneforexisting_configinself._partitions:existing_partitions=set(self._partitions[existing_config])ifpartitions_set==existing_partitions:existing=Truebreakifexisting:returnself._partitions[existing_config]else:self._partitions[config_name]=partitionsreturnpartitionsdef_manifold_text(self):r"""generate text for printing representations."""returnrf'In ${self._sym_repr}\subset\mathbb'+'{R}^{'+str(get_embedding_space_dim())+'}$, '