B @`sA@sddlmZmZddlmZmZddlmZddlm Z ddl m Z m Z ddl mZddlmZdd ZGd d d eZd d ZddZddZdddZdddZdS))Block Reference) ComponentSet ComponentMap) SubclassOf) SetProduct)UnindexedComponent_setnormalize_index)IndexedComponent_slice) OrderedDictcCsB|jdkr:tjstdS|jdk r2tdf|jStfSndSdS)z: Get the slice of the proper dimension for a set. rN)Zdimenr flattensliceEllipsis)sr5/tmp/pip-unpacked-wheel-bi3529v6/pyomo/dae/flatten.pyget_slice_for_sets  rc@seZdZdZdS) _NotAnIndexz `None` is a valid index, so we use a dummy class to denote a slot that needs to get filled with indices from our product. N)__name__ __module__ __qualname____doc__rrrrr(srcCsjd}x0t|D]$\}}|tkr||||<|d7}qW|t|ksFtt|}t|dkrb|dS|SdS)z `filled_index` is a list with some entries `_NotAnIndex`. We fill those entries with values from `index`, a tuple. rN) enumeraterlenAssertionErrortuple) filled_indexindexjivalrrr _fill_indices0s   r"ccsLtj}z8dt_x,|D]$}t|}|t_t||Vdt_qWWd|t_XdS)a; `partial_index_list` is a list of indices, each corresponding to a set. If an entry in `partial_index_list` is `_NotAnIndex`, that slot will get filled in by an entry from `product`. `product` is a `SetProduct` with as many "factors" as there are missing indices in `partial_index_list`. FN)r r listr")Zpartial_index_listproductZ_normalize_index_flattenrrrrr_fill_indices_from_productEs   r%c #sxh|j|ddD]T}t|}fdd|D}fdd|D} fdd|D} || } | r |r | dj| dd } xt|| D]l} y>t||j| }t |t kr| }t t || |fVWqtk rYqtk rYqXqWqyF|r8t||jd }t t | n t||j}| |fVWqtk rfYqXqWxZ|jtddD]F}t|}fd d|D}fd d|D} fd d|D} tfdd| D}|| | r|r| dj| dd } xt|| D]} yt||j| }| rt | tk rL| fn| }tfddt||D}t||}t|dkr|d}||}t |t k r|n t t |}n|| }x.t||||D]\}}t||fVqWWntk rYnXqWny|rRt||jd }||}t |t k rD|n t t |}nt||j}|}x.t||||D]\}}t||fVqvWWntk rYnXx| D]}|qWq~Wd S)a Recursively generate sliced components of a block and its subblocks, along with the sets that were sliced for each component. `b` is a _BlockData object. `index_stack` is a list of indices "above" `b` in the hierarchy. Note that `b` is a data object, so any index of its parent component should be included in the stack. `slice_` is the slice generated so far. Our goal here is to yield extensions to `slice_` at this level of the hierarchy. `sets` is a ComponentSet of Pyomo sets that should be sliced. `ctype` is the type we are looking for. `index_map` is potentially a map from each set in `sets` to a "representative index" to use when descending into subblocks. F)Z descend_intocs g|]}|krt|ntqSr)rr).0r)setsrr sz.generate_sliced_components..csg|]}|kr|qSrr)r&r)r'rrr(scsg|]}|kr|qSrr)r&r)r'rrr(srrN.cs g|]}|krt|ntqSr)rr)r&r)r'rrr(scsg|]}|kr|qSrr)r&r)r'rrr(scsg|]}|kr|qSrr)r&r)r'rrr(sc3s&|]}|kr|nt|VqdS)N)r)r&r) index_maprr sz-generate_sliced_components..c3s"|]\}}|kr|ntVqdS)N)r)r&idxZsubset)r'rrr*s)Zcomponent_objectsr#Z index_setsubsetsZ is_indexedZcrossr%getattrZ local_nametyper Z duplicatenextiter StopIterationKeyErrorrrextendzipr"rgenerate_sliced_componentspop)b index_stackslice_r'ctyper)cr,Ztemp_idxZnew_setsZ other_setsZ sliced_setsZ cross_prodZ new_indexZc_sliceZ temp_slicesubZdescend_index_sliced_setsZ sub_sliceZtupl_new_indexZincomplete_descend_indexZ descend_indexZ descend_slicedatastv_r)r)r'rr5xs                r5NcCs |dkrt}n t|tkr"|}ntt||}g}t|}t}t}xt||||||D]\} } tdd| D} | |krt| dkrtf|| <n| || <| |krg|| <t| dkr||  | q\d| _ d| _ ||  t | q\Wt dd|D} t dd|D} | | fS)a This function iterates over components (recursively) contained in a block and partitions their data objects into components indexed only by the specified sets. Args: m : Block whose components (and their sub-components) will be partitioned sets : Possible indexing sets for the returned components ctype : Type of component to identify and partition indices : indices of sets to use when descending into subblocks Returns: tuple: The first entry is a list of tuples of Pyomo Sets. The second is a list of lists of components, each indexed by the corresponding sets in the first entry. Ncss|]}t|VqdS)N)id)r&r;rrrr*Ksz0flatten_components_along_sets..rFcss|] }|VqdS)Nr)r&r'rrrr*]scss|] }|VqdS)Nr)r&compsrrrr*_s)rr.r4rr r5rrrappendZ$attribute_errors_generate_exceptionsZkey_errors_generate_exceptionsrr#values)mr'r:indicesr)r8Z set_of_setsZ sets_dictZ comps_dictZ index_setsr9key sets_list comps_listrrrflatten_components_along_sets"s4    rJc Cst|f}t||||d\}}g}g}xft||D]X\} } t| dkrX| d|krX| }q2t| dks|t| dkr| dtkr| }q2tdq2W||fS)N)rFrrzInvalid model for `flatten_dae_components`. This can happen if your model has components that are indexed by time (explicitly or implicitly) multiple times.)rrJr4rr RuntimeError) modeltimer:rFtargetrHrIZ scalar_compsZ dae_compsr'rBrrrflatten_dae_componentsgs    rO)N)N)Zpyomo.core.baserrZpyomo.common.collectionsrrZpyomo.core.base.blockrZpyomo.core.base.setrZ!pyomo.core.base.indexed_componentrr Z'pyomo.core.base.indexed_component_slicer collectionsr robjectrr"r%r5rJrOrrrr s    3+ E