|
| 1 | +""" |
| 2 | +Tying, Pruning, and Labelling Envy architecture tree |
| 3 | +""" |
| 4 | +import sys |
| 5 | +sys.path.append('../') |
| 6 | +from stochastic_tree import Support, BasicWood |
| 7 | +import numpy as np |
| 8 | +import random as rd |
| 9 | +import copy |
| 10 | +import gc |
| 11 | +import time |
| 12 | + |
| 13 | +from helper import * |
| 14 | + |
| 15 | +class Spur(BasicWood): |
| 16 | + count = 0 |
| 17 | + def __init__(self, copy_from = None, max_buds_segment: int = 5, thickness: float = 0.1,\ |
| 18 | + thickness_increment: float = 0.01, growth_length: float = 1., max_length: float = 7.,\ |
| 19 | + tie_axis: list = [0,1,1], order: int = 1, prototype_dict: dict = {}, name = None, color = None): |
| 20 | + super().__init__(copy_from, max_buds_segment,thickness, thickness_increment, growth_length,\ |
| 21 | + max_length, tie_axis, order, color) |
| 22 | + if copy_from: |
| 23 | + self.__copy_constructor__(copy_from) |
| 24 | + else: |
| 25 | + self.prototype_dict = prototype_dict |
| 26 | + if not name: |
| 27 | + self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count) |
| 28 | + Spur.count+=1 |
| 29 | + |
| 30 | + def is_bud_break(self, num_buds_segment): |
| 31 | + return (rd.random() < 0.1) |
| 32 | + |
| 33 | + def create_branch(self): |
| 34 | + return None |
| 35 | + |
| 36 | + def grow(self): |
| 37 | + pass |
| 38 | + |
| 39 | +class Branch(BasicWood): |
| 40 | + count = 0 |
| 41 | + def __init__(self, copy_from = None, max_buds_segment: int = 5, thickness: float = 0.1,\ |
| 42 | + thickness_increment: float = 0.01, growth_length: float = 1., max_length: float = 7.,\ |
| 43 | + tie_axis: tuple = (0,1,1), order: int = 1, prototype_dict: dict = {}, name = None, color = None): |
| 44 | + |
| 45 | + super().__init__(copy_from, max_buds_segment,thickness, thickness_increment, growth_length,\ |
| 46 | + max_length, tie_axis, order, color) |
| 47 | + if copy_from: |
| 48 | + self.__copy_constructor__(copy_from) |
| 49 | + else: |
| 50 | + self.prototype_dict = prototype_dict |
| 51 | + |
| 52 | + if not name: |
| 53 | + self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count) |
| 54 | + Branch.count+=1 |
| 55 | + |
| 56 | + def is_bud_break(self, num_buds_segment): |
| 57 | + return (rd.random() < 0.02*(1 - num_buds_segment/self.max_buds_segment)) |
| 58 | + |
| 59 | + def create_branch(self): |
| 60 | + new_ob = Spur(copy_from = self.prototype_dict['spur']) |
| 61 | + return new_ob |
| 62 | + |
| 63 | + def grow(self): |
| 64 | + pass |
| 65 | + |
| 66 | +class NonTrunk(BasicWood): |
| 67 | + count = 0 |
| 68 | + def __init__(self, copy_from = None, max_buds_segment: int = 5, thickness: float = 0.1,\ |
| 69 | + thickness_increment: float = 0.01, growth_length: float = 1., max_length: float = 7.,\ |
| 70 | + tie_axis: tuple = (0,1,1), order: int = 1, prototype_dict: dict = {}, name = None, color = None): |
| 71 | + |
| 72 | + super().__init__(copy_from, max_buds_segment,thickness, thickness_increment, growth_length,\ |
| 73 | + max_length, tie_axis, order, color) |
| 74 | + if copy_from: |
| 75 | + self.__copy_constructor__(copy_from) |
| 76 | + else: |
| 77 | + self.prototype_dict = prototype_dict |
| 78 | + |
| 79 | + if not name: |
| 80 | + self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count) |
| 81 | + Branch.count+=1 |
| 82 | + |
| 83 | + def is_bud_break(self, num_buds_segment): |
| 84 | + return (rd.random() < 0.02*(1 - num_buds_segment/self.max_buds_segment)) |
| 85 | + |
| 86 | + def create_branch(self): |
| 87 | + new_ob = Spur(copy_from = self.prototype_dict['spur']) |
| 88 | + return new_ob |
| 89 | + |
| 90 | + def grow(self): |
| 91 | + pass |
| 92 | + |
| 93 | + |
| 94 | +class Trunk(BasicWood): |
| 95 | + count = 0 |
| 96 | + """ Details of the trunk while growing a tree, length, thickness, where to attach them etc """ |
| 97 | + def __init__(self, copy_from = None, max_buds_segment: int = 5, thickness: float = 0.1,\ |
| 98 | + thickness_increment: float = 0.01, growth_length: float = 1., max_length: float = 7.,\ |
| 99 | + tie_axis: tuple = (0,1,1), order: int = 0, prototype_dict: dict = {}, name = None, color = None): |
| 100 | + |
| 101 | + super().__init__(copy_from, max_buds_segment,thickness, thickness_increment, growth_length,\ |
| 102 | + max_length, tie_axis, order, color) |
| 103 | + if copy_from: |
| 104 | + self.__copy_constructor__(copy_from) |
| 105 | + else: |
| 106 | + self.prototype_dict = prototype_dict |
| 107 | + if not name: |
| 108 | + self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count) |
| 109 | + Trunk.count+=1 |
| 110 | + |
| 111 | + def is_bud_break(self, num_buds_segment): |
| 112 | + if (rd.random() > 0.02*(1 - num_buds_segment/self.max_buds_segment)): |
| 113 | + return False |
| 114 | + return True |
| 115 | + |
| 116 | + def create_branch(self): |
| 117 | + if rd.random() > 0.8: |
| 118 | + return Spur(copy_from = self.prototype_dict['spur']) |
| 119 | + else: |
| 120 | + return Branch(copy_from = self.prototype_dict['branch']) |
| 121 | + |
| 122 | + def grow(self): |
| 123 | + pass |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | +#Pass transition probabs? --> solve with abstract classes |
| 129 | + |
| 130 | +#basicwood_prototypes = {} |
| 131 | +#basicwood_prototypes['trunk'] = Trunk(tie_axis = [0,1,1], max_length = 20, thickness_increment = 0.02, prototype_dict = basicwood_prototypes, color = 0) |
| 132 | +#basicwood_prototypes['branch'] = Branch(tie_axis = [0,1,1], max_length = 20, thickness_increment = 0.005, prototype_dict = basicwood_prototypes, color = 1) |
| 133 | +#basicwood_prototypes['spur'] = Spur(tie_axis = [0,1,1], max_length = 1, thickness_increment = 0.005, prototype_dict = basicwood_prototypes, color = 2) |
| 134 | + |
| 135 | +growth_length = 0.1 |
| 136 | +#everything is relative to growth length |
| 137 | +basicwood_prototypes = {} |
| 138 | +basicwood_prototypes['trunk'] = Trunk(tie_axis = (0,1,1), max_length = 2.5/growth_length, thickness = 0.01, growth_length = 0.1,thickness_increment = 0.0005, prototype_dict = basicwood_prototypes, color = 0) |
| 139 | +basicwood_prototypes['branch'] = Branch(tie_axis = (0,1,1), max_length = .45/growth_length, thickness = 0.01, growth_length = 0.1,thickness_increment = 0.00005, prototype_dict = basicwood_prototypes, color = 1) |
| 140 | +basicwood_prototypes['nontrunkbranch'] = NonTrunk(tie_axis = (0,0,1), max_length = 0.1/growth_length, growth_length = 0.1, thickness = 0.0001,thickness_increment = 0.0001, prototype_dict = basicwood_prototypes, color = 1) |
| 141 | +basicwood_prototypes['spur'] = Spur(tie_axis = (0,1,1), max_length = 0.01/growth_length, thickness = 0.005, growth_length = 0.01,thickness_increment = 0., prototype_dict = basicwood_prototypes, color = 2) |
| 142 | + |
| 143 | +#init |
| 144 | +trunk_base = Trunk(copy_from = basicwood_prototypes['trunk']) |
| 145 | +time_count = 0 |
| 146 | +label = True |
| 147 | +def generate_points_v_trellis(): |
| 148 | + x = np.full((7,), 1.45).astype(float) |
| 149 | + #z = np.arange(3, 24, 3).astype(float) |
| 150 | + y = np.full((7,), 0).astype(float) |
| 151 | + z = np.arange(0.6,3.4, 0.45) |
| 152 | + pts = [] |
| 153 | + id = 0 |
| 154 | + for i in range(x.shape[0]): |
| 155 | + pts.append((-x[i], y[i], z[i])) |
| 156 | + id+=1 |
| 157 | + pts.append((x[i], y[i], z[i])) |
| 158 | + id+=1 |
| 159 | + return pts |
| 160 | + |
| 161 | + |
| 162 | + |
| 163 | +support = Support(generate_points_v_trellis(), 14 , 1 , None, (0,0,1), None) |
| 164 | +num_iteration_tie = 30 |
| 165 | + |
| 166 | +###Tying stuff begins |
| 167 | + |
| 168 | +def ed(a,b): |
| 169 | + return np.linalg.norm(a-b) |
| 170 | + |
| 171 | +def get_energy_mat(branches, arch): |
| 172 | + #branches = [i for i in branches if "Branch" in i.name] |
| 173 | + num_branches = len(branches) |
| 174 | + num_wires = len(list(arch.branch_supports.values())) |
| 175 | + energy_matrix = np.ones((num_branches,num_wires))*np.inf |
| 176 | + #print(energy_matrix.shape) |
| 177 | + for branch_id, branch in enumerate(branches): |
| 178 | + if branch.has_tied: |
| 179 | + continue |
| 180 | + for wire_id, wire in arch.branch_supports.items(): |
| 181 | + if wire.num_branch>=1: |
| 182 | + continue |
| 183 | + energy_matrix[branch_id][wire_id] = ed(wire.point,branch.end)/2+ed(wire.point,branch.start)/2#+v.num_branches*10+branch.bend_energy(deflection, curr_branch.age) |
| 184 | + return energy_matrix |
| 185 | + |
| 186 | +def decide_guide(energy_matrix, branches, arch): |
| 187 | + for i in range(energy_matrix.shape[0]): |
| 188 | + min_arg = np.argwhere(energy_matrix == np.min(energy_matrix)) |
| 189 | + #print(min_arg) |
| 190 | + if(energy_matrix[min_arg[0][0]][min_arg[0][1]] == np.inf):# or energy_matrix[min_arg[0][0]][min_arg[0][1]] > 1: |
| 191 | + return |
| 192 | + if not (branches[min_arg[0][0]].has_tied == True):# and not (arch.branch_supports[min_arg[0][1]].num_branch >=1): |
| 193 | + #print("Imp:",min_arg[0][0], min_arg[0][1], energy_matrix[min_arg[0][0]][min_arg[0][1]]) |
| 194 | + branches[min_arg[0][0]].guide_target = arch.branch_supports[min_arg[0][1]]#copy.deepcopy(arch.branch_supports[min_arg[0][1]].point) |
| 195 | + #trellis_wires.trellis_pts[min_arg[0][1]].num_branches+=1 |
| 196 | + for j in range(energy_matrix.shape[1]): |
| 197 | + energy_matrix[min_arg[0][0]][j] = np.inf |
| 198 | + for j in range(energy_matrix.shape[0]): |
| 199 | + energy_matrix[j][min_arg[0][1]] = np.inf |
| 200 | + |
| 201 | +def tie(lstring): |
| 202 | + for j,i in enumerate(lstring): |
| 203 | + if i == 'C' and i[0].type.__class__.__name__ == 'Branch': |
| 204 | + if i[0].type.tie_updated == False: |
| 205 | + continue |
| 206 | + curr = i[0] |
| 207 | + if i[0].type.guide_points: |
| 208 | + #print("tying ", i[0].type.name, i[0].type.guide_target.point) |
| 209 | + i[0].type.tie_updated = False |
| 210 | + i[0].type.guide_target.add_branch() |
| 211 | + lstring, count = i[0].type.tie_lstring(lstring, j) |
| 212 | + |
| 213 | + return True |
| 214 | + return False |
| 215 | + |
| 216 | +#Pruning strategy |
| 217 | + |
| 218 | +def pruning_strategy(lstring): #Remove remnants of cut |
| 219 | + cut = False |
| 220 | + |
| 221 | + for j,i in enumerate(lstring): |
| 222 | + |
| 223 | + if i.name == 'C' and i[0].type.age > 10 and i[0].type.has_tied == False and i[0].type.cut == False: |
| 224 | + |
| 225 | + i[0].type.cut = True |
| 226 | + #print("Cutting", i[0].type.name) |
| 227 | + lstring = cut_from(j, lstring) |
| 228 | + |
| 229 | + return True |
| 230 | + |
| 231 | + return False |
| 232 | + |
| 233 | +def StartEach(lstring): |
| 234 | + global parent_child_dict |
| 235 | + for i in parent_child_dict[trunk_base.name]: |
| 236 | + if i.tie_updated == False: |
| 237 | + i.tie_update() |
| 238 | + |
| 239 | + |
| 240 | +def EndEach(lstring): |
| 241 | + global parent_child_dict, support |
| 242 | + tied = False |
| 243 | + |
| 244 | + if (getIterationNb()+1)%num_iteration_tie == 0: |
| 245 | + energy_matrix = get_energy_mat(parent_child_dict[trunk_base.name], support) |
| 246 | + print(energy_matrix) |
| 247 | + decide_guide(energy_matrix, parent_child_dict[trunk_base.name], support) |
| 248 | + for branch in parent_child_dict[trunk_base.name]: |
| 249 | + branch.update_guide(branch.guide_target) |
| 250 | + print(branch.name, branch.guide_target) |
| 251 | + while tie(lstring): |
| 252 | + pass |
| 253 | + while pruning_strategy(lstring): |
| 254 | + pass |
| 255 | + return lstring |
| 256 | + |
| 257 | +parent_child_dict = {} |
| 258 | +parent_child_dict[trunk_base.name] = [] |
| 259 | +#print(generate_points_ufo()) |
| 260 | +module Attractors |
| 261 | +module grow_object |
| 262 | +module bud |
| 263 | +module branch |
| 264 | +module C |
| 265 | +Axiom: Attractors(support)grow_object(trunk_base) |
| 266 | +derivation length: 100 |
| 267 | + |
| 268 | +production: |
| 269 | +#Decide whether branch internode vs trunk internode need to be the same size. |
| 270 | +grow_object(o) : |
| 271 | + if o == None: |
| 272 | + produce * |
| 273 | + if o.length >= o.max_length: |
| 274 | + o.age+=1 |
| 275 | + nproduce * |
| 276 | + else: |
| 277 | + if label: |
| 278 | + nproduce SetColor(o.color) |
| 279 | + o.grow_one() |
| 280 | + produce I(o.growth_length, o.thickness, o)bud(ParameterSet(type = o, num_buds = 0))grow_object(o) |
| 281 | + |
| 282 | +bud(t) : |
| 283 | + if t.type.is_bud_break(t.num_buds): |
| 284 | + new_object = t.type.create_branch() |
| 285 | + if new_object == None: |
| 286 | + produce * |
| 287 | + parent_child_dict[new_object.name] = [] |
| 288 | + parent_child_dict[t.type.name].append(new_object) |
| 289 | + #Store new object somewhere |
| 290 | + t.num_buds+=1 |
| 291 | + t.type.num_branches+=1 |
| 292 | + nproduce [@RGetPos(new_object.start)C(ParameterSet(type = new_object))/(rd.random()*360)&(rd.random()*90)grow_object(new_object)GetPos(new_object.end)]bud(t) |
| 293 | + |
| 294 | + |
| 295 | +I(s,r,o) --> I(s,r+o.thickness_increment, o) |
| 296 | +_(r) --> _(r+o.thickness_increment) |
| 297 | + |
| 298 | +homomorphism: |
| 299 | + |
| 300 | +I(a,r,o) --> F(a,r) |
| 301 | +S(a,r,o) --> F(a,r) |
| 302 | + |
| 303 | +production: |
| 304 | +Attractors(support): |
| 305 | + pttodisplay = support.attractor_grid.get_enabled_points() |
| 306 | + if len(pttodisplay) > 0: |
| 307 | + produce [,(3) @g(PointSet(pttodisplay,width=10))] |
0 commit comments