B u `'@slddlZddlmZddlmZddlmZddlmZm Z ddZ ddd Z dd d Z d d Z ddZdS)N)normalize_index)IndexedComponent_slice)UnindexedComponent_set) ComponentSet ComponentMapccsNtjtjtjf}t|drDt||r.|VqJx|D] }|Vq4Wn|VdS)N__iter__)six string_types binary_type text_typehasattr isinstance)sourceZiterable_scalarsobjr5/tmp/pip-unpacked-wheel-n62dbgi3/pyomo/util/slices.py _to_iterables    rcCstg}xj|dk rn||krP|}|rH||k rH|tj|f||krRP|tj|jf|}qW|S)aGet the call stack necessary to locate a `Component` The call stack is a `list` of `tuple`s where the first entry is a code for `__getattr__` or `__getitem__`, using the same convention as `IndexedComponent_slice`. The second entry is the argument of the corresponding function. Following this sequence of calls from `context` (or the top-level model if `context is None`) will produce comp. Parameters: ----------- comp : `pyomo.core.base.component.Component` The component to locate context : `pyomo.core.base.block.Block` The block within which to locate the component. If `None`, the top-level model will be used. Returns: -------- `list` : Contains the necessary method calls and their arguments. Note that the calls should be applied in reverse order. This is the opposite direction as in IndexedComponent_slice. N) Z parent_blockparent_componentZ is_indexedappendrget_itemindex get_attributeZ local_name)compcontext call_stackrrrrget_component_call_stacks  rc Cs|dkr|}t||}|}|}xl|r|\}}|tjkrTt||}t||}q$|tjkr$|}||}t||}t |||}||}q$W|S)aSlice a component along the indices corresponding to some sets, wherever they appear in the component's block hierarchy. Given a component or component data object, for all parent components and parent blocks between the object and the `context` block, replace any index corresponding to a set in `sets` with slices or an ellipsis. Parameters: ----------- comp: `pyomo.core.base.component.Component` or `pyomo.core.base.component.ComponentData` Component whose parent structure to search and replace sets: `pyomo.common.collections.ComponentSet` Contains the sets to replace with slices context: `pyomo.core.base.block.Block` or `pyomo.core.base.block._BlockData` Block below which to search for sets Returns: -------- `pyomo.core.base.indexed_component_slice.IndexedComponent_slice`: Slice of `comp` with wildcards replacing the indices of `sets` N) modelrpoprrgetattrr index_setget_location_set_mapreplace_indices) rsetsrrZ sliced_compcallargrlocation_set_maprrrslice_component_along_setsSs"         r&c Cstt|}g}d}t|}x||kr||}||}|j}||krP||n\|dk rl|tdddn@|} |t|d7}x&||kr||}|| k rP|d7}qWq|d7}qWt|S)aUse `location_set_map` to replace values in `index` with slices or an Ellipsis. Parameters: ----------- index: `tuple` or scalar Index whose values to replace location_set_map: `dict` Maps locations ("indices") within the index to their corresponding set sets: `pyomo.common.collections.ComponentSet` Contains the sets to replace with slices Returns: -------- `tuple`: Index with values replaced by slices rN)tuplerlendimenrsliceEllipsis) rr%r"Z new_indexloc len_indexvalZ_setr*dimen_none_setrrrr!s.       r!cCs~tt|}t|}tt|}i}|tkr4dtiStjsBtdt | }t|}d}d}d} x`t |D]T\} } | j } | dkr| }| } Px*t| D]} | ||| <| || qW|| 7}qlW|s|S|d}xt t|D]|\} } || d} | j } | dkr&| | kr$td|| | | fPx,t| D] } | ||| <| || q0W|| j 8}qWx|D]}|||<qhW|S)azMap each value in an index to the set from which it originates This function iterates over the "subsets" of `index_set` in the forward direction, assigning sets to each value in `index`, until it finds a set of dimension `None`. Then it iterates over the reversed list of subsets, assigning sets, until it encounters the same set of dimension `None`. All remaining values are assigned to the set of dimension `None`. If a second such set is found, an error is raised. Parameters: ----------- index: `tuple` or hashable scalar The index whose values will be assigned to sets index_set: `pyomo.core.base.set.SetProduct` or `pyomo.core.base.set.Set` The index set from which `index` originates Returns: -------- `dict`: Maps the "locations" (indices) within the index to the set from which it originates. rzVget_location_set_map does not support the case where normalize_index.flatten is False.Nr'zCannot get locations when multiple sets of dimen==None are present. Found %s at position %s and %s at position %s. Location is ambiguous in this case.)r(rr)setrangerrflatten ValueErrorlistsubsets enumerater*removereversed RuntimeError)rrr.Zlocations_leftr%r6Z n_subsetslocationr0Zdimen_none_set_coordZ sub_coordsubr*ir-rrrr sV          r )N)N)rZ!pyomo.core.base.indexed_componentrZ'pyomo.core.base.indexed_component_slicerZpyomo.core.base.global_setrZpyomo.common.collectionsrrrrr&r!r rrrr s    6 1.