示例#1
0
def test_factoradics():
    for i in range(100):
        assert from_factoradic(to_factoradic(i)) == i
    assert tuple(map(to_factoradic, range(10))) == (
        (0,), (1, 0,), (1, 0, 0), (1, 1, 0), (2, 0, 0), (2, 1, 0),
        (1, 0, 0, 0), (1, 0, 1, 0), (1, 1, 0, 0), (1, 1, 1, 0)
    )
示例#2
0
    def __getitem__(self, i):
        if isinstance(i, (slice, sequence_tools.CanonicalSlice)):
            canonical_slice = sequence_tools.CanonicalSlice(
                i, self.length, offset=self.canonical_slice.start)
            return PermSpace(self.sequence,
                             domain=self.domain,
                             n_elements=self.n_elements,
                             fixed_map=self.fixed_map,
                             degrees=self.degrees,
                             is_combination=self.is_combination,
                             slice_=canonical_slice,
                             perm_type=self.perm_type)

        assert isinstance(i, numbers.Integral)
        if i <= -1:
            i += self.length

        if not (0 <= i < self.length):
            raise IndexError
        elif self.is_sliced:
            return self.unsliced[i + self.canonical_slice.start]
        elif self.is_dapplied:
            return self.perm_type(self.undapplied[i], perm_space=self)

        #######################################################################
        elif self.is_degreed:
            if self.is_rapplied:
                assert not self.is_recurrent and \
                       not self.is_partial and not self.is_combination and \
                       not self.is_dapplied and not self.is_sliced
                return self.perm_type(map(self.sequence.__getitem__,
                                          self.unrapplied[i]),
                                      perm_space=self)


            assert not self.is_rapplied and not self.is_recurrent and \
                   not self.is_partial and not self.is_combination and \
                   not self.is_dapplied and not self.is_sliced
            # If that wasn't an example of asserting one's dominance, I don't
            # know what is.

            available_values = list(self.free_values)
            wip_perm_sequence_dict = dict(self.fixed_map)
            wip_n_cycles_in_fixed_items = \
                                    self._n_cycles_in_fixed_items_of_just_fixed
            wip_i = i
            for j in self.sequence:
                if j in wip_perm_sequence_dict:
                    continue
                for unused_value in available_values:
                    candidate_perm_sequence_dict = dict(wip_perm_sequence_dict)
                    candidate_perm_sequence_dict[j] = unused_value

                    ### Checking whether we closed a cycle: ###################
                    #                                                         #
                    if j == unused_value:
                        closed_cycle = True
                    else:
                        current = j
                        while True:
                            current = candidate_perm_sequence_dict[current]
                            if current == j:
                                closed_cycle = True
                                break
                            elif current not in candidate_perm_sequence_dict:
                                closed_cycle = False
                                break
                    #                                                         #
                    ### Finished checking whether we closed a cycle. ##########

                    candidate_n_cycles_in_fixed_items = \
                                     wip_n_cycles_in_fixed_items + closed_cycle

                    candidate_fixed_perm_space_length = sum(
                        math_tools.abs_stirling(
                            self.sequence_length -
                            len(candidate_perm_sequence_dict),
                            self.sequence_length - degree -
                            candidate_n_cycles_in_fixed_items)
                        for degree in self.degrees)

                    if wip_i < candidate_fixed_perm_space_length:
                        available_values.remove(unused_value)
                        wip_perm_sequence_dict[j] = unused_value
                        wip_n_cycles_in_fixed_items = \
                                              candidate_n_cycles_in_fixed_items

                        break
                    wip_i -= candidate_fixed_perm_space_length
                else:
                    raise RuntimeError
            assert wip_i == 0
            return self.perm_type(
                (wip_perm_sequence_dict[k] for k in self.domain), self)

        #######################################################################
        elif self.is_recurrent:
            assert not self.is_dapplied and not self.is_degreed and \
                                                             not self.is_sliced
            available_values = list(self.sequence)
            reserved_values = nifty_collections.Bag(self.fixed_map.values())
            wip_perm_sequence_dict = dict(self.fixed_map)
            wip_i = i
            shit_set = set()
            for j in range(self.n_elements):
                if j in self.fixed_map:
                    available_values.remove(self.fixed_map[j])
                    reserved_values[self.fixed_map[j]] -= 1
                    continue
                unused_values = [
                    item for item in
                    nifty_collections.OrderedBag(available_values) -
                    reserved_values if item not in shit_set
                ]
                for unused_value in unused_values:
                    wip_perm_sequence_dict[j] = unused_value

                    candidate_sub_perm_space = \
                                             PermSpace._create_with_cut_prefix(
                        self.sequence,
                        n_elements=self.n_elements,
                        fixed_map=wip_perm_sequence_dict,
                        is_combination=self.is_combination,
                        shit_set=shit_set, perm_type=self.perm_type
                    )

                    if wip_i < candidate_sub_perm_space.length:
                        available_values.remove(unused_value)
                        break
                    else:
                        wip_i -= candidate_sub_perm_space.length
                        if self.is_combination:
                            shit_set.add(wip_perm_sequence_dict[j])
                        del wip_perm_sequence_dict[j]
                else:
                    raise RuntimeError
            assert wip_i == 0
            return self.perm_type(
                dict_tools.get_tuple(wip_perm_sequence_dict, self.domain),
                self)

        #######################################################################
        elif self.is_fixed:
            free_values_perm = self._free_values_unsliced_perm_space[i]
            free_values_perm_iterator = iter(free_values_perm)
            return self.perm_type(
                tuple((self._undapplied_fixed_map[m] if (
                    m in self.fixed_indices
                ) else next(free_values_perm_iterator))
                      for m in self.indices), self)

        #######################################################################
        elif self.is_combination:
            wip_number = self.length - 1 - i
            wip_perm_sequence = []
            for i in range(self.n_elements, 0, -1):
                for j in range(self.sequence_length, i - 2, -1):
                    candidate = math_tools.binomial(j, i)
                    if candidate <= wip_number:
                        wip_perm_sequence.append(self.sequence[-(j + 1)])
                        wip_number -= candidate
                        break
                else:
                    raise RuntimeError
            result = tuple(wip_perm_sequence)
            assert len(result) == self.n_elements
            return self.perm_type(result, self)

        #######################################################################
        else:
            factoradic_number = math_tools.to_factoradic(
                i * math.factorial(self.n_unused_elements),
                n_digits_pad=self.sequence_length)
            if self.is_partial:
                factoradic_number = factoradic_number[:-self.n_unused_elements]
            unused_numbers = list(self.sequence)
            result = tuple(
                unused_numbers.pop(factoradic_digit)
                for factoradic_digit in factoradic_number)
            assert sequence_tools.get_length(result) == self.n_elements
            return self.perm_type(result, self)
示例#3
0
    def __getitem__(self, i):
        if isinstance(i, (slice, sequence_tools.CanonicalSlice)):
            canonical_slice = sequence_tools.CanonicalSlice(
                i, self.length, offset=self.canonical_slice.start
            )
            return PermSpace(
                self.sequence, domain=self.domain, n_elements=self.n_elements,
                fixed_map=self.fixed_map, degrees=self.degrees,
                is_combination=self.is_combination, slice_=canonical_slice,
                perm_type=self.perm_type
            )
        
        assert isinstance(i, numbers.Integral)
        if i <= -1:
            i += self.length
            
        if not (0 <= i < self.length):
            raise IndexError
        elif self.is_sliced:
            return self.unsliced[i + self.canonical_slice.start]
        elif self.is_dapplied:
            return self.perm_type(self.undapplied[i], perm_space=self)

        #######################################################################
        elif self.is_degreed:
            if self.is_rapplied:
                assert not self.is_recurrent and \
                       not self.is_partial and not self.is_combination and \
                       not self.is_dapplied and not self.is_sliced
                return self.perm_type(map(self.sequence.__getitem__,
                                          self.unrapplied[i]),
                                      perm_space=self)
                
            
            assert not self.is_rapplied and not self.is_recurrent and \
                   not self.is_partial and not self.is_combination and \
                   not self.is_dapplied and not self.is_sliced
            # If that wasn't an example of asserting one's dominance, I don't
            # know what is.
            
            available_values = list(self.free_values)
            wip_perm_sequence_dict = dict(self.fixed_map)
            wip_n_cycles_in_fixed_items = \
                                    self._n_cycles_in_fixed_items_of_just_fixed
            wip_i = i
            for j in self.sequence:
                if j in wip_perm_sequence_dict:
                    continue
                for unused_value in available_values:
                    candidate_perm_sequence_dict = dict(wip_perm_sequence_dict)
                    candidate_perm_sequence_dict[j] = unused_value
                    
                    ### Checking whether we closed a cycle: ###################
                    #                                                         #
                    if j == unused_value:
                        closed_cycle = True
                    else:
                        current = j
                        while True:
                            current = candidate_perm_sequence_dict[current]
                            if current == j:
                                closed_cycle = True
                                break
                            elif current not in candidate_perm_sequence_dict:
                                closed_cycle = False
                                break
                    #                                                         #
                    ### Finished checking whether we closed a cycle. ##########
                    
                    candidate_n_cycles_in_fixed_items = \
                                     wip_n_cycles_in_fixed_items + closed_cycle
                    
                    candidate_fixed_perm_space_length = sum(
                        math_tools.abs_stirling(
                            self.sequence_length -
                                             len(candidate_perm_sequence_dict),
                            self.sequence_length - degree -
                                              candidate_n_cycles_in_fixed_items
                        ) for degree in self.degrees
                    )
                    
                    
                    if wip_i < candidate_fixed_perm_space_length:
                        available_values.remove(unused_value)
                        wip_perm_sequence_dict[j] = unused_value
                        wip_n_cycles_in_fixed_items = \
                                              candidate_n_cycles_in_fixed_items
                        
                        break
                    wip_i -= candidate_fixed_perm_space_length
                else:
                    raise RuntimeError
            assert wip_i == 0
            return self.perm_type((wip_perm_sequence_dict[k] for k in
                                   self.domain), self)
        
        #######################################################################
        elif self.is_recurrent:
            assert not self.is_dapplied and not self.is_degreed and \
                                                             not self.is_sliced
            available_values = list(self.sequence)
            reserved_values = nifty_collections.Bag(self.fixed_map.values())
            wip_perm_sequence_dict = dict(self.fixed_map)
            wip_i = i
            shit_set = set()
            for j in range(self.n_elements):
                if j in self.fixed_map:
                    available_values.remove(self.fixed_map[j])
                    reserved_values[self.fixed_map[j]] -= 1
                    continue
                unused_values = [
                    item for item in
                    nifty_collections.OrderedBag(available_values) -
                    reserved_values if item not in shit_set
                ]
                for unused_value in unused_values:
                    wip_perm_sequence_dict[j] = unused_value
                    
                    candidate_sub_perm_space = \
                                             PermSpace._create_with_cut_prefix(
                        self.sequence,
                        n_elements=self.n_elements,
                        fixed_map=wip_perm_sequence_dict,
                        is_combination=self.is_combination,
                        shit_set=shit_set, perm_type=self.perm_type
                    )
                    
                    if wip_i < candidate_sub_perm_space.length:
                        available_values.remove(unused_value)
                        break
                    else:
                        wip_i -= candidate_sub_perm_space.length
                        if self.is_combination:
                            shit_set.add(wip_perm_sequence_dict[j])
                        del wip_perm_sequence_dict[j]
                else:
                    raise RuntimeError
            assert wip_i == 0
            return self.perm_type(
                dict_tools.get_tuple(wip_perm_sequence_dict, self.domain),
                self
            )
        
        #######################################################################
        elif self.is_fixed:
            free_values_perm = self._free_values_unsliced_perm_space[i]
            free_values_perm_iterator = iter(free_values_perm)
            return self.perm_type(
                tuple(
                    (self._undapplied_fixed_map[m] if
                     (m in self.fixed_indices) else
                     next(free_values_perm_iterator))
                                       for m in range(self.sequence_length)
                ),
                self
            )
        
        #######################################################################
        elif self.is_combination:
            wip_number = self.length - 1 - i
            wip_perm_sequence = []
            for i in range(self.n_elements, 0, -1):
                for j in range(self.sequence_length, i - 2, -1):
                    candidate = math_tools.binomial(j, i)
                    if candidate <= wip_number:
                        wip_perm_sequence.append(
                            self.sequence[-(j+1)]
                        )
                        wip_number -= candidate
                        break
                else:
                    raise RuntimeError
            result = tuple(wip_perm_sequence)
            assert len(result) == self.n_elements
            return self.perm_type(result, self)

        
        #######################################################################
        else:
            factoradic_number = math_tools.to_factoradic(
                i * math.factorial(
                     self.n_unused_elements),
                n_digits_pad=self.sequence_length
            )
            if self.is_partial:
                factoradic_number = factoradic_number[:-self.n_unused_elements]
            unused_numbers = list(self.sequence)
            result = tuple(unused_numbers.pop(factoradic_digit) for
                                         factoradic_digit in factoradic_number)
            assert sequence_tools.get_length(result) == self.n_elements
            return self.perm_type(result, self)