def export_csv(absolute_clan_or_multiclan, file_or_path, ordered_lefts=None, sort_key=None): r"""Export an absolute clan or absolute multiclan as CSV file with header row. The :term:`left component`\s of the :term:`clan` or term:`multiclan` are interpreted as column names and are exported as header row. Every :term:`relation` in the input becomes a data row in the CSV file. :param absolute_clan_or_multiclan: An :term:`absolute clan` or term:`absolute multiclan`. If it is not :term:`regular`, ``ordered_lefts`` must be given. :param file_or_path: Either a file path (in this case the CSV data is written to a file at this location) or a file object (in this case the CSV data is written to its ``.write()`` function). :param ordered_lefts: (Optional) A ``Sequence`` of :term:`left`\s that are exported in the given order. Default is the sequence that is the lexically sorted :term:`left set` of the (multi)clan. This parameter is required if ``absolute_clan_or_multiclan`` is not term:`regular`. :param sort_key: (Optional) A function that compares two row-:term:`relation`\s and provides an order (for use with :func:`sorted`). The output is not sorted if ``sort_key`` is missing. :return: ``True`` if the CSV export succeeded, ``False`` if not. """ if not _clans.is_absolute_member(absolute_clan_or_multiclan) \ and not _multiclans.is_absolute_member(absolute_clan_or_multiclan): return False regular_clan = _clans.is_member(absolute_clan_or_multiclan) \ and _clans.is_regular(absolute_clan_or_multiclan) regular_mclan = _multiclans.is_member(absolute_clan_or_multiclan) \ and _multiclans.is_regular(absolute_clan_or_multiclan) if ordered_lefts is None and not (regular_clan or regular_mclan): return False if ordered_lefts is None: # Since this clan is regular, get first relation to acquire left set. rel = next(iter(absolute_clan_or_multiclan)) # left_set is sorted to guarantee consistent iterations ordered_lefts = sorted([left.value for left in rel.get_left_set()]) # Generate dictionaries that associates left components with their right components for each # relation. clan_as_list_of_dicts = _convert_clan_to_list_of_dicts( ordered_lefts, (absolute_clan_or_multiclan if sort_key is None else sorted(absolute_clan_or_multiclan, key=sort_key))) # Write the dictionaries. _csv_dict_writer(file_or_path, ordered_lefts, clan_as_list_of_dicts) return True
def is_regular(mo: _mo.MathObject, _checked: bool=True) -> bool: r"""Return whether ``mo`` is :term:`regular` or `Undef()` if not applicable. Is implemented for :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of clans. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_regular == _mo.CacheStatus.IS: return True if mo.cached_regular == _mo.CacheStatus.IS_NOT: return False if mo.cached_regular == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check type (regular is only defined on Sets and Multisets) and algebra memberships. if not mo.is_set and not mo.is_multiset: mo.cache_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _clans.is_member(mo): return _clans.is_regular(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_regular(mo, _checked=False) # Check higher (not yet defined) algebras. if mo.get_ground_set().get_powerset_level(_clans.get_ground_set()) > 0: mo_iter = iter(mo) elem1 = next(mo_iter) if not is_regular(elem1): mo.cache_regular(_mo.CacheStatus.IS_NOT) return False elem1_lefts = elem1.get_lefts() regular = all( is_regular(elem, _checked=False) and elem.get_lefts() == elem1_lefts for elem in mo_iter) mo.cache_regular(_mo.CacheStatus.from_bool(regular)) return mo.cached_is_regular # Nothing applied: 'regular' is not defined. mo.cache_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)
def is_regular(mo: _mo.MathObject, _checked: bool = True) -> bool: r"""Return whether ``mo`` is :term:`regular` or `Undef()` if not applicable. Is implemented for :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of clans. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_regular == _mo.CacheStatus.IS: return True if mo.cached_regular == _mo.CacheStatus.IS_NOT: return False if mo.cached_regular == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check type (regular is only defined on Sets and Multisets) and algebra memberships. if not mo.is_set and not mo.is_multiset: mo.cache_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _clans.is_member(mo): return _clans.is_regular(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_regular(mo, _checked=False) # Check higher (not yet defined) algebras. if mo.get_ground_set().get_powerset_level(_clans.get_ground_set()) > 0: mo_iter = iter(mo) elem1 = next(mo_iter) if not is_regular(elem1): mo.cache_regular(_mo.CacheStatus.IS_NOT) return False elem1_lefts = elem1.get_lefts() regular = all( is_regular(elem, _checked=False) and elem.get_lefts() == elem1_lefts for elem in mo_iter) mo.cache_regular(_mo.CacheStatus.from_bool(regular)) return mo.cached_is_regular # Nothing applied: 'regular' is not defined. mo.cache_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)