Shared Memory Managers for F-Symbol Attributes¶
This module provides an implementation for shared dictionary like state attributes required by the orthogonal F-matrix solver.
Currently, the attributes only work when the base field of the
FMatrix factory is a cyclotomic field.
- class sage.algebras.fusion_rings.shm_managers.FvarsHandler[source]¶
- Bases: - object- A shared memory backed dict-like structure to manage the - _fvarsattribute of an F-matrix.- This structure implements a representation of the F-symbols dictionary using a structured NumPy array backed by a contiguous shared memory object. - The monomial data is stored in the - exp_datastructure. Monomial exponent data is stored contiguously and- ticksare used to indicate different monomials.- Coefficient data is stored in the - coeff_numsand- coeff_denomarrays. The- coeff_denomarray stores the value- d = coeff.denominator()for each cyclotomic coefficient. The- coeff_numsarray stores the values- c.numerator() * d for c in coeff._coefficients(), the abridged list representation of the cyclotomic coefficient- coeff.- Each entry also has a boolean - modifiedattribute, indicating whether it has been modified by the parent process. Entry retrieval is cached in each process, so each process must check whether entries have been modified before attempting retrieval.- The parent process should construct this object without a - nameattribute. Children processes use the- nameattribute, accessed via- self.shm.nameto attach to the shared memory block.- INPUT: - n_slots– number of generators of the underlying polynomial ring
- field– base field for polynomial ring
- idx_to_sextuple– map relating a single integer index to a sextuple of- FusionRingelements
- init_data– dictionary or- FvarsHandlerobject containing known squares for initialization, e.g., from a solver checkpoint
- use_mp– integer indicating the number of child processes used for multiprocessing; if running serially, use 0
- pids_name– the name of a- ShareableListcontaining the process- pid’s for every process in the pool (including the parent process)
- name– the name of a shared memory object (used by child processes for attaching)
- max_terms– maximum number of terms in each entry; since we use contiguous C-style memory blocks, the size of the block must be known in advance
- n_bytes– the number of bytes that should be allocated for each numerator and each denominator stored by the structure
 - Note - To properly dispose of shared memory resources, - self.shm.unlink()must be called before exiting.- Note - If you ever encounter an - OverflowErrorwhen running the- FMatrix.find_orthogonal_solution()solver, consider increasing the parameter- n_bytes.- Warning - The current data structure supports up to \(2^16\) entries, with each monomial in each entry having at most 254 nonzero terms. On average, each of the - max_termsmonomials can have at most 30 terms.- EXAMPLES: - sage: from sage.algebras.fusion_rings.shm_managers import FvarsHandler sage: # Create shared data structure sage: f = FusionRing("A2", 1).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx8 Defining fx0, fx1, fx2, fx3, fx4, fx5, fx6, fx7 sage: f.start_worker_pool() sage: n_proc = f.pool._processes sage: pids_name = f._pid_list.shm.name sage: fvars = FvarsHandler(8, f._field, f._idx_to_sextuple, use_mp=n_proc, pids_name=pids_name) sage: # In the same shell or in a different shell, attach to fvars sage: name = fvars.shm.name sage: fvars2 = FvarsHandler(8, f._field, f._idx_to_sextuple, name=name , use_mp=n_proc, pids_name=pids_name) sage: from sage.algebras.fusion_rings.poly_tup_engine import poly_to_tup sage: rhs = tuple((exp, tuple(c._coefficients())) for exp, c in poly_to_tup(fx5**5)) sage: fvars[f2, f1, f2, f2, f0, f0] = rhs sage: f._tup_to_fpoly(fvars2[f2, f1, f2, f2, f0, f0]) fx5^5 sage: fvars.shm.unlink() sage: f.shutdown_worker_pool() - >>> from sage.all import * >>> from sage.algebras.fusion_rings.shm_managers import FvarsHandler >>> # Create shared data structure >>> f = FusionRing("A2", Integer(1)).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx8 Defining fx0, fx1, fx2, fx3, fx4, fx5, fx6, fx7 >>> f.start_worker_pool() >>> n_proc = f.pool._processes >>> pids_name = f._pid_list.shm.name >>> fvars = FvarsHandler(Integer(8), f._field, f._idx_to_sextuple, use_mp=n_proc, pids_name=pids_name) >>> # In the same shell or in a different shell, attach to fvars >>> name = fvars.shm.name >>> fvars2 = FvarsHandler(Integer(8), f._field, f._idx_to_sextuple, name=name , use_mp=n_proc, pids_name=pids_name) >>> from sage.algebras.fusion_rings.poly_tup_engine import poly_to_tup >>> rhs = tuple((exp, tuple(c._coefficients())) for exp, c in poly_to_tup(fx5**Integer(5))) >>> fvars[f2, f1, f2, f2, f0, f0] = rhs >>> f._tup_to_fpoly(fvars2[f2, f1, f2, f2, f0, f0]) fx5^5 >>> fvars.shm.unlink() >>> f.shutdown_worker_pool() - items()[source]¶
- Iterate through key-value pairs in the data structure as if it were a Python dict. - As in a Python dict, the key-value pairs are yielded in no particular order. - EXAMPLES: - sage: f = FusionRing("G2", 1).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx5 Defining fx0, fx1, fx2, fx3, fx4 sage: from sage.algebras.fusion_rings.shm_managers import FvarsHandler sage: shared_fvars = FvarsHandler(5, f._field, f._idx_to_sextuple, init_data=f._fvars) sage: for sextuple, fvar in shared_fvars.items(): ....: if sextuple == (f1, f1, f1, f1, f1, f1): ....: f._tup_to_fpoly(fvar) ....: fx4 - >>> from sage.all import * >>> f = FusionRing("G2", Integer(1)).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx5 Defining fx0, fx1, fx2, fx3, fx4 >>> from sage.algebras.fusion_rings.shm_managers import FvarsHandler >>> shared_fvars = FvarsHandler(Integer(5), f._field, f._idx_to_sextuple, init_data=f._fvars) >>> for sextuple, fvar in shared_fvars.items(): ... if sextuple == (f1, f1, f1, f1, f1, f1): ... f._tup_to_fpoly(fvar) ....: fx4 
 
- class sage.algebras.fusion_rings.shm_managers.KSHandler[source]¶
- Bases: - object- A shared memory backed dict-like structure to manage the - _ksattribute of an F-matrix.- This structure implements a representation of the known squares dictionary using a structured NumPy array backed by a contiguous shared memory object. - The structure mimics a dictionary of - (idx, known_sq)pairs. Each integer index corresponds to a variable and each- known_sqis an element of the F-matrix factory’s base cyclotomic field.- Each cyclotomic coefficient is stored as a list of numerators and a list of denominators representing the rational coefficients. The structured array also maintains - knownattribute that indicates whether the structure contains an entry corresponding to the given index.- The parent process should construct this object without a - nameattribute. Children processes use the- nameattribute, accessed via- self.shm.nameto attach to the shared memory block.- INPUT: - n_slots– the total number of F-symbols
- field– F-matrix’s base cyclotomic field
- use_mp– boolean indicating whether to construct a shared memory block to back- self
- init_data– dictionary or- KSHandlerobject containing known squares for initialization, e.g., from a solver checkpoint
- name– the name of a shared memory object (used by child processes
- for attaching) 
 
 - Note - To properly dispose of shared memory resources, - self.shm.unlink()must be called before exiting.- Warning - This structure cannot modify an entry that has already been set. - EXAMPLES: - sage: from sage.algebras.fusion_rings.shm_managers import KSHandler sage: # Create shared data structure sage: f = FusionRing("A1", 2).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx14 Defining fx0, fx1, fx2, fx3, fx4, fx5, fx6, fx7, fx8, fx9, fx10, fx11, fx12, fx13 sage: n = f._poly_ring.ngens() sage: f.start_worker_pool() sage: ks = KSHandler(n, f._field, use_mp=True) sage: # In the same shell or in a different shell, attach to fvars sage: name = ks.shm.name sage: ks2 = KSHandler(n, f._field, name=name, use_mp=True) sage: from sage.algebras.fusion_rings.poly_tup_engine import poly_to_tup sage: eqns = [fx1**2 - 4, fx3**2 + f._field.gen()**4 - 1/19*f._field.gen()**2] sage: ks.update([poly_to_tup(p) for p in eqns]) sage: for idx, sq in ks.items(): ....: print("Index: {}, square: {}".format(idx, sq)) ....: Index: 1, square: 4 Index: 3, square: -zeta32^4 + 1/19*zeta32^2 sage: ks.shm.unlink() sage: f.shutdown_worker_pool() - >>> from sage.all import * >>> from sage.algebras.fusion_rings.shm_managers import KSHandler >>> # Create shared data structure >>> f = FusionRing("A1", Integer(2)).get_fmatrix(inject_variables=True, new=True) creating variables fx1..fx14 Defining fx0, fx1, fx2, fx3, fx4, fx5, fx6, fx7, fx8, fx9, fx10, fx11, fx12, fx13 >>> n = f._poly_ring.ngens() >>> f.start_worker_pool() >>> ks = KSHandler(n, f._field, use_mp=True) >>> # In the same shell or in a different shell, attach to fvars >>> name = ks.shm.name >>> ks2 = KSHandler(n, f._field, name=name, use_mp=True) >>> from sage.algebras.fusion_rings.poly_tup_engine import poly_to_tup >>> eqns = [fx1**Integer(2) - Integer(4), fx3**Integer(2) + f._field.gen()**Integer(4) - Integer(1)/Integer(19)*f._field.gen()**Integer(2)] >>> ks.update([poly_to_tup(p) for p in eqns]) >>> for idx, sq in ks.items(): ... print("Index: {}, square: {}".format(idx, sq)) ....: Index: 1, square: 4 Index: 3, square: -zeta32^4 + 1/19*zeta32^2 >>> ks.shm.unlink() >>> f.shutdown_worker_pool() - items()[source]¶
- Iterate through existing entries using Python dict-style syntax. - EXAMPLES: - sage: f = FusionRing("A3", 1).get_fmatrix() sage: f._reset_solver_state() sage: f.get_orthogonality_constraints(output=False) sage: f._ks.update(f.ideal_basis) sage: for idx, sq in f._ks.items(): ....: print("Index: {}, sq: {}".format(idx, sq)) ....: Index: 0, sq: 1 Index: 1, sq: 1 Index: 2, sq: 1 Index: 3, sq: 1 Index: 4, sq: 1 ... Index: 25, sq: 1 Index: 26, sq: 1 - >>> from sage.all import * >>> f = FusionRing("A3", Integer(1)).get_fmatrix() >>> f._reset_solver_state() >>> f.get_orthogonality_constraints(output=False) >>> f._ks.update(f.ideal_basis) >>> for idx, sq in f._ks.items(): ... print("Index: {}, sq: {}".format(idx, sq)) ....: Index: 0, sq: 1 Index: 1, sq: 1 Index: 2, sq: 1 Index: 3, sq: 1 Index: 4, sq: 1 ... Index: 25, sq: 1 Index: 26, sq: 1 
 - update(eqns)[source]¶
- Update - self’s- shared_memory-backed dictionary of known squares. Keys are variable indices and corresponding values are the squares.- EXAMPLES: - sage: f = FusionRing("B5", 1).get_fmatrix() sage: f._reset_solver_state() sage: for idx, sq in f._ks.items(): ....: k ....: sage: f.get_orthogonality_constraints() [fx0^2 - 1, fx1^2 - 1, fx2^2 - 1, fx3^2 - 1, fx4^2 - 1, fx5^2 - 1, fx6^2 - 1, fx7^2 - 1, fx8^2 - 1, fx9^2 - 1, fx10^2 + fx12^2 - 1, fx10*fx11 + fx12*fx13, fx10*fx11 + fx12*fx13, fx11^2 + fx13^2 - 1] sage: f.get_orthogonality_constraints(output=False) sage: f._ks.update(f.ideal_basis) sage: for idx, sq in f._ks.items(): ....: print(idx, "-->", sq) ....: 0 --> 1 1 --> 1 2 --> 1 3 --> 1 4 --> 1 5 --> 1 6 --> 1 7 --> 1 8 --> 1 9 --> 1 - >>> from sage.all import * >>> f = FusionRing("B5", Integer(1)).get_fmatrix() >>> f._reset_solver_state() >>> for idx, sq in f._ks.items(): ... k ....: >>> f.get_orthogonality_constraints() [fx0^2 - 1, fx1^2 - 1, fx2^2 - 1, fx3^2 - 1, fx4^2 - 1, fx5^2 - 1, fx6^2 - 1, fx7^2 - 1, fx8^2 - 1, fx9^2 - 1, fx10^2 + fx12^2 - 1, fx10*fx11 + fx12*fx13, fx10*fx11 + fx12*fx13, fx11^2 + fx13^2 - 1] >>> f.get_orthogonality_constraints(output=False) >>> f._ks.update(f.ideal_basis) >>> for idx, sq in f._ks.items(): ... print(idx, "-->", sq) ....: 0 --> 1 1 --> 1 2 --> 1 3 --> 1 4 --> 1 5 --> 1 6 --> 1 7 --> 1 8 --> 1 9 --> 1 - Warning - This method assumes every polynomial in - eqnsis monic.
 
- sage.algebras.fusion_rings.shm_managers.make_FvarsHandler(n, field, idx_map, init_data)[source]¶
- Provide pickling / unpickling support for - FvarsHandler.