コード例 #1
0
ファイル: AoT.py プロジェクト: yanivbenny/RAVEN_FAIR
 def __init__(self, name, layout_constraint, entity_constraint, 
                          orig_layout_constraint=None, orig_entity_constraint=None, 
                          sample_new_num_count=None, is_pg=False):
     super(Layout, self).__init__(name, level="Layout", node_type="and", is_pg=is_pg)
     self.layout_constraint = layout_constraint
     self.entity_constraint = entity_constraint
     self.number = Number(min_level=layout_constraint["Number"][0], max_level=layout_constraint["Number"][1])
     self.position = Position(pos_type=layout_constraint["Position"][0], pos_list=layout_constraint["Position"][1])
     self.uniformity = Uniformity(min_level=layout_constraint["Uni"][0], max_level=layout_constraint["Uni"][1])
     self.number.sample()
     self.position.sample(self.number.get_value())
     self.uniformity.sample()
     # store initial layout_constraint and entity_constraint for answer generation
     if orig_layout_constraint is None:
         self.orig_layout_constraint = copy.deepcopy(self.layout_constraint)
     else:
         self.orig_layout_constraint = orig_layout_constraint
     if orig_entity_constraint is None:
         self.orig_entity_constraint = copy.deepcopy(self.entity_constraint)
     else:
         self.orig_entity_constraint = orig_entity_constraint
     if sample_new_num_count is None:
         self.sample_new_num_count = dict()
         most_num = len(self.position.values)
         for i in range(layout_constraint["Number"][0], layout_constraint["Number"][1] + 1):
             self.sample_new_num_count[i] = [comb(most_num, i + 1), []]
     else:
         self.sample_new_num_count = sample_new_num_count
コード例 #2
0
class Layout(AoTNode):
    """Layout is the highest level of the hierarchy that has attributes (Number, Position and Uniformity).
    To copy a Layout, please use deepcopy such that newly instantiated and separated attributes are created.
    """
    def __init__(self,
                 name,
                 layout_constraint,
                 entity_constraint,
                 orig_layout_constraint=None,
                 orig_entity_constraint=None,
                 sample_new_num_count=None,
                 is_pg=False):
        super(Layout, self).__init__(name,
                                     level="Layout",
                                     node_type="and",
                                     is_pg=is_pg)
        self.layout_constraint = layout_constraint
        self.entity_constraint = entity_constraint
        self.number = Number(min_level=layout_constraint["Number"][0],
                             max_level=layout_constraint["Number"][1])
        self.position = Position(pos_type=layout_constraint["Position"][0],
                                 pos_list=layout_constraint["Position"][1])
        self.uniformity = Uniformity(min_level=layout_constraint["Uni"][0],
                                     max_level=layout_constraint["Uni"][1])
        self.number.sample()
        self.position.sample(self.number.get_value())
        self.uniformity.sample()
        # store initial layout_constraint and entity_constraint for answer generation
        if orig_layout_constraint is None:
            self.orig_layout_constraint = copy.deepcopy(self.layout_constraint)
        else:
            self.orig_layout_constraint = orig_layout_constraint
        if orig_entity_constraint is None:
            self.orig_entity_constraint = copy.deepcopy(self.entity_constraint)
        else:
            self.orig_entity_constraint = orig_entity_constraint
        if sample_new_num_count is None:
            self.sample_new_num_count = dict()
            most_num = len(self.position.values)
            for i in range(layout_constraint["Number"][0],
                           layout_constraint["Number"][1] + 1):
                self.sample_new_num_count[i] = [comb(most_num, i + 1), []]
        else:
            self.sample_new_num_count = sample_new_num_count
        self.num_count = dict()
        for i in self.sample_new_num_count.keys():
            self.num_count[i] = 1

    def reset_num_count(self):
        for i in self.num_count.keys():
            if self.sample_new_num_count[i][0] > 0:
                self.num_count[i] = 1

    def add_new(self, *bboxes):
        """Add new entities into this level.
        Arguments:
            *bboxes(tuple of bbox): bboxes of new entities
        """
        name = self.number.get_value()
        uni = self.uniformity.get_value()
        for i in range(len(bboxes)):
            name += i
            bbox = bboxes[i]
            new_entity = copy.deepcopy(self.children[0])
            new_entity.name = str(name)
            new_entity.bbox = bbox
            if not uni:
                new_entity.resample()
            self._insert(new_entity)

    def resample(self, change_number=False):
        self._resample(change_number)

    def _sample(self):
        """Though Layout is an "and" node, we do not enumerate all possible configurations, but rather
        we treat it as a sampling process such that different configurtions are sampled. After the
        sampling, the lower level Entities are instantiated.
        Returns:
            new_node(Layout): a separated node with independent attributes
        """
        pos = self.position.get_value()
        new_node = copy.deepcopy(self)
        new_node.is_pg = True
        if self.uniformity.get_value():
            node = Entity(name=str(0),
                          bbox=pos[0],
                          entity_constraint=self.entity_constraint)
            new_node._insert(node)
            for i in range(1, len(pos)):
                bbox = pos[i]
                node = copy.deepcopy(node)
                node.name = str(i)
                node.bbox = bbox
                new_node._insert(node)
        else:
            for i in range(len(pos)):
                bbox = pos[i]
                node = Entity(name=str(i),
                              bbox=bbox,
                              entity_constraint=self.entity_constraint)
                new_node._insert(node)
        return new_node

    def _resample(self, change_number):
        """Resample each attribute for every child.
        This function is called across rows.
        Arguments:
            change_number(bool): whether to resample a number
        """
        if change_number:
            self.number.sample()
        del self.children[:]
        self.position.sample(self.number.get_value())
        pos = self.position.get_value()
        if self.uniformity.get_value():
            node = Entity(name=str(0),
                          bbox=pos[0],
                          entity_constraint=self.entity_constraint)
            self._insert(node)
            for i in range(1, len(pos)):
                bbox = pos[i]
                node = copy.deepcopy(node)
                node.name = str(i)
                node.bbox = bbox
                self._insert(node)
        else:
            for i in range(len(pos)):
                bbox = pos[i]
                node = Entity(name=str(i),
                              bbox=bbox,
                              entity_constraint=self.entity_constraint)
                self._insert(node)

    def _update_constraint(self, rule_group):
        """Update the constraint of the layout. If one constraint is not satisfied, return None 
        such that this structure is disgarded.
        Arguments:
            rule_group(list of Rule): all rules to apply to this layout
        Returns:
            Layout(Layout): a new Layout node with independent attributes
        """
        num_min = self.layout_constraint["Number"][0]
        num_max = self.layout_constraint["Number"][1]
        uni_min = self.layout_constraint["Uni"][0]
        uni_max = self.layout_constraint["Uni"][1]
        type_min = self.entity_constraint["Type"][0]
        type_max = self.entity_constraint["Type"][1]
        size_min = self.entity_constraint["Size"][0]
        size_max = self.entity_constraint["Size"][1]
        color_min = self.entity_constraint["Color"][0]
        color_max = self.entity_constraint["Color"][1]
        new_constraints = rule_constraint(rule_group, num_min, num_max,
                                          uni_min, uni_max, type_min, type_max,
                                          size_min, size_max, color_min,
                                          color_max)
        new_layout_constraint, new_entity_constraint = new_constraints
        new_num_min = new_layout_constraint["Number"][0]
        new_num_max = new_layout_constraint["Number"][1]
        if new_num_min > new_num_max:
            return None
        new_uni_min = new_layout_constraint["Uni"][0]
        new_uni_max = new_layout_constraint["Uni"][1]
        if new_uni_min > new_uni_max:
            return None
        new_type_min = new_entity_constraint["Type"][0]
        new_type_max = new_entity_constraint["Type"][1]
        if new_type_min > new_type_max:
            return None
        new_size_min = new_entity_constraint["Size"][0]
        new_size_max = new_entity_constraint["Size"][1]
        if new_size_min > new_size_max:
            return None
        new_color_min = new_entity_constraint["Color"][0]
        new_color_max = new_entity_constraint["Color"][1]
        if new_color_min > new_color_max:
            return None

        new_layout_constraint = copy.deepcopy(self.layout_constraint)
        new_layout_constraint["Number"][:] = [new_num_min, new_num_max]
        new_layout_constraint["Uni"][:] = [new_uni_min, new_uni_max]

        new_entity_constraint = copy.deepcopy(self.entity_constraint)
        new_entity_constraint["Type"][:] = [new_type_min, new_type_max]
        new_entity_constraint["Size"][:] = [new_size_min, new_size_max]
        new_entity_constraint["Color"][:] = [new_color_min, new_color_max]
        return Layout(self.name, new_layout_constraint, new_entity_constraint,
                      self.orig_layout_constraint, self.orig_entity_constraint,
                      self.sample_new_num_count)

    def reset_constraint(self, attr):
        attr_name = attr.lower()
        instance = getattr(self, attr_name)
        instance.min_level = self.layout_constraint[attr][0]
        instance.max_level = self.layout_constraint[attr][1]

    def _sample_new(self, attr_name, min_level, max_level, layout):
        if attr_name == "Number":
            while True:
                value_level = self.number.sample_new(min_level, max_level)
                if layout.sample_new_num_count[value_level][0] == 0:
                    continue
                new_num = self.number.get_value(value_level)
                new_value_idx = self.position.sample_new(new_num)
                set_new_value_idx = set(new_value_idx)
                if set_new_value_idx not in layout.sample_new_num_count[
                        value_level][1]:
                    layout.sample_new_num_count[value_level][0] -= 1
                    layout.sample_new_num_count[value_level][1].append(
                        set_new_value_idx)
                    break
            self.number.set_value_level(value_level)
            self.position.set_value_idx(new_value_idx)
            pos = self.position.get_value()
            del self.children[:]
            for i in range(len(pos)):
                bbox = pos[i]
                node = Entity(name=str(i),
                              bbox=bbox,
                              entity_constraint=self.entity_constraint)
                self._insert(node)
        elif attr_name == "Position":
            new_value_idx = self.position.sample_new(self.number.get_value())
            layout.position.previous_values.append(new_value_idx)
            self.position.set_value_idx(new_value_idx)
            pos = self.position.get_value()
            for i in range(len(pos)):
                bbox = pos[i]
                self.children[i].bbox = bbox
        elif attr_name == "Type":
            for index in range(len(self.children)):
                new_value_level = self.children[index].type.sample_new(
                    min_level, max_level)
                self.children[index].type.set_value_level(new_value_level)
                layout.children[index].type.previous_values.append(
                    new_value_level)
        elif attr_name == "Size":
            for index in range(len(self.children)):
                new_value_level = self.children[index].size.sample_new(
                    min_level, max_level)
                self.children[index].size.set_value_level(new_value_level)
                layout.children[index].size.previous_values.append(
                    new_value_level)
        elif attr_name == "Color":
            for index in range(len(self.children)):
                new_value_level = self.children[index].color.sample_new(
                    min_level, max_level)
                self.children[index].color.set_value_level(new_value_level)
                layout.children[index].color.previous_values.append(
                    new_value_level)
        else:
            raise ValueError("Unsupported operation")

    def _sample_new_value(self, attr_name, min_level, max_level, attr_uni,
                          mode_3):

        ret = []
        if attr_name == "Number":
            previous_num = self.number.get_value()
            while True:
                value_level = self.number.sample_new(min_level, max_level)
                if mode_3 == '3-Position-Number' and self.sample_new_num_count[
                        value_level][0] == 1:
                    continue
                if self.num_count[value_level] == 1:
                    self.num_count[value_level] = 0
                    break
            new_num = self.number.get_value(value_level)
            if previous_num >= new_num:
                select = list(
                    np.random.choice(previous_num, new_num, replace=False))
            else:
                rest = new_num
                select = []
                while previous_num < rest:
                    select += range(previous_num)
                    rest -= previous_num
                if rest > 0:
                    select += list(
                        np.random.choice(previous_num, rest, replace=False))
            ret = [value_level, select]

            t = 1
            if mode_3 == '3-Position-Number':
                t += 1
            for i in range(t):
                while True:
                    new_value_idx = self.position.sample_new(new_num)
                    set_new_value_idx = set(new_value_idx)
                    if set_new_value_idx not in self.sample_new_num_count[
                            value_level][1]:
                        self.sample_new_num_count[value_level][0] -= 1
                        self.sample_new_num_count[value_level][1].append(
                            set_new_value_idx)
                        ret.append(new_value_idx)
                        break
            if sum(self.num_count.values()) == 1:
                self.reset_num_count()

        elif attr_name == "Position":
            new_value_idx = self.position.sample_new(self.number.get_value())
            ret = [new_value_idx]

        elif attr_name == "Type":
            if attr_uni:
                new_value_level = self.children[0].type.sample_new(
                    min_level, max_level)
                ret = [new_value_level]
            else:
                for index in range(len(self.children)):
                    new_value_level = self.children[index].type.sample_new(
                        min_level, max_level)
                    ret.append(new_value_level)

        elif attr_name == "Size":
            if attr_uni:
                new_value_level = self.children[0].size.sample_new(
                    min_level, max_level)
                ret = [new_value_level]
            else:
                for index in range(len(self.children)):
                    new_value_level = self.children[index].size.sample_new(
                        min_level, max_level)
                    ret.append(new_value_level)

        elif attr_name == "Color":
            if attr_uni:
                new_value_level = self.children[0].color.sample_new(
                    min_level, max_level)
                ret = [new_value_level]
            else:
                for index in range(len(self.children)):
                    new_value_level = self.children[index].color.sample_new(
                        min_level, max_level)
                    ret.append(new_value_level)
        else:
            raise ValueError("Unsupported operation")
        return ret

    def _apply_new_value(self, attr_name, value):
        L = len(value)
        if attr_name == "Number":
            number_value = value[0]
            select = value[1]
            if L == 4 and self.position.isChanged:
                position_value = value[3]
            else:
                position_value = value[2]
            self.number.set_value_level(number_value)
            self.position.set_value_idx(position_value)
            pos = self.position.get_value()
            new_entity_list = [
                copy.deepcopy(self.children[idx]) for idx in select
            ]
            del self.children[:]
            for i in range(len(pos)):
                bbox = pos[i]
                self._insert(new_entity_list[i])
                self.children[i].bbox = bbox

        elif attr_name == "Position":
            self.position.set_value_idx(value[0])
            self.position.isChanged = True
            pos = self.position.get_value()
            for i in range(len(pos)):
                bbox = pos[i]
                self.children[i].bbox = bbox

        elif attr_name == "Type":
            for index in range(len(self.children)):
                self.children[index].type.set_value_level(value[index % L])

        elif attr_name == "Size":
            for index in range(len(self.children)):
                self.children[index].size.set_value_level(value[index % L])

        elif attr_name == "Color":
            for index in range(len(self.children)):
                self.children[index].color.set_value_level(value[index % L])
        else:
            raise ValueError("Unsupported operation")