def __init__(self, windspeed, relative_scale, world): self.air = Air(b2Vec2(-windspeed, 0.0)) self.water = Water(b2Vec2(0.0,0.0)) self.world = world gap = 10.0 h_length = 1.0 h_wchord = 0.5 h_wspan = 2.0 h_schord = 0.25 h_sspan = 0.75 a_length = h_length * relative_scale a_wchord = h_wchord * relative_scale a_wspan = h_wspan * relative_scale a_schord = h_schord * relative_scale a_sspan = h_sspan * relative_scale self.airfoil = Glider (x=0.0, y=gap*0.5, anchor_point=0.12, polarity=1.0, body_length=a_length, wing_chord=a_wchord, wing_span=a_wspan, stabilizer_chord=a_schord, stabilizer_span=a_sspan, fluid=self.air, box2dWorld=world, density=50.0) self.hydrofoil = Glider (x=0.0, y=gap*-0.5, anchor_point=0.12, polarity=-1.0, body_length=h_length, wing_chord=h_wchord, wing_span=h_wspan, stabilizer_chord=h_schord, stabilizer_span=h_sspan, fluid=self.water, box2dWorld=world, density=300.0) self.add_anchor_joint()
def __init__(self, windspeed, relative_scale, world): self.air = Air(b2Vec2(-windspeed, 0.0)) self.water = Water(b2Vec2(0.0, 0.0)) self.world = world gap = 10.0 h_length = 1.0 h_wchord = 0.5 h_wspan = 2.0 h_schord = 0.25 h_sspan = 0.75 a_length = h_length * relative_scale a_wchord = h_wchord * relative_scale a_wspan = h_wspan * relative_scale a_schord = h_schord * relative_scale a_sspan = h_sspan * relative_scale self.airfoil = Glider(x=0.0, y=gap * 0.5, anchor_point=0.12, polarity=1.0, body_length=a_length, wing_chord=a_wchord, wing_span=a_wspan, stabilizer_chord=a_schord, stabilizer_span=a_sspan, fluid=self.air, box2dWorld=world, density=50.0) self.hydrofoil = Glider(x=0.0, y=gap * -0.5, anchor_point=0.12, polarity=-1.0, body_length=h_length, wing_chord=h_wchord, wing_span=h_wspan, stabilizer_chord=h_schord, stabilizer_span=h_sspan, fluid=self.water, box2dWorld=world, density=300.0) self.add_anchor_joint()
def gt_eval(self, gt): # run trials data = [] for cfg in range(1, 5): # for supervised trials if self.sup: self.sup_sts = self.supervised_states(cfg) # new world and glider self.world = defaultdict(int) self.glider = Glider(gt, config=cfg) ft, prog, gl_states = self.trial() data.append([ft, prog, gl_states]) # average fitness # av_ft = sum([dtrial[0] for dtrial in data])/len(data) # weighted fitness sorted_fts = sorted([dt[0] for dt in data], reverse=True) wft = 2 / (len(data) * (len(data) + 1)) * sum([(i + 1) * fi for i, fi in enumerate(sorted_fts)]) data.insert(0, wft) return data
def __init__(self, x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld): self.glider = Glider(x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld) self.original_x = x # Make an anchor anchorBodyDef = b2BodyDef() anchorBodyDef.position.Set(x, 0.0) anchor = box2dWorld.CreateBody(anchorBodyDef) shapeDef = b2PolygonDef() shapeDef.SetAsBox(1.0, 1.0) shapeDef.density = 1000 # kg/m^3, from wikipedia for styrofoam density anchor.CreateShape(shapeDef) anchor.SetMassFromShapes() self.anchor = anchor self.world = box2dWorld # Create the anchor joint self.move_anchor(0.0)
class Craft(object): def __init__(self, windspeed, relative_scale, world): self.air = Air(b2Vec2(-windspeed, 0.0)) self.water = Water(b2Vec2(0.0, 0.0)) self.world = world gap = 10.0 h_length = 1.0 h_wchord = 0.5 h_wspan = 2.0 h_schord = 0.25 h_sspan = 0.75 a_length = h_length * relative_scale a_wchord = h_wchord * relative_scale a_wspan = h_wspan * relative_scale a_schord = h_schord * relative_scale a_sspan = h_sspan * relative_scale self.airfoil = Glider(x=0.0, y=gap * 0.5, anchor_point=0.12, polarity=1.0, body_length=a_length, wing_chord=a_wchord, wing_span=a_wspan, stabilizer_chord=a_schord, stabilizer_span=a_sspan, fluid=self.air, box2dWorld=world, density=50.0) self.hydrofoil = Glider(x=0.0, y=gap * -0.5, anchor_point=0.12, polarity=-1.0, body_length=h_length, wing_chord=h_wchord, wing_span=h_wspan, stabilizer_chord=h_schord, stabilizer_span=h_sspan, fluid=self.water, box2dWorld=world, density=300.0) self.add_anchor_joint() def windspeed(self): return self.air.velocity.Length() def move_anchor(self, glider, amount): glider.move_anchor(amount) if hasattr(self, "anchorJoint"): self.world.DestroyJoint(self.anchorJoint) self.add_anchor_joint() def add_anchor_joint(self): anchorJoint = b2DistanceJointDef() anchor1 = self.airfoil.get_anchor_point() anchor2 = self.hydrofoil.get_anchor_point() anchorJoint.Initialize(self.airfoil.body, self.hydrofoil.body, anchor1, anchor2) anchorJoint.collideConnected = True self.anchorJoint = self.world.CreateJoint(anchorJoint).getAsType() def get_center(self): return (self.airfoil.body.GetPosition() + self.hydrofoil.body.GetPosition()) * 0.5 def step(self, damper=0.0): self.airfoil.step(damper) self.hydrofoil.step(damper) def draw(self, ctx): self.airfoil.draw(ctx) self.hydrofoil.draw(ctx) def get_force_vectors(self): forces = [] forces += self.airfoil.get_force_vectors() forces += self.hydrofoil.get_force_vectors() return forces def clear_force_vectors(self): self.airfoil.clear_force_vectors() self.hydrofoil.clear_force_vectors() def velocity(self): return (self.hydrofoil.velocity() + self.airfoil.velocity()) / 2.0
class Kite(object): def __init__(self, x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld): self.glider = Glider(x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld) self.original_x = x # Make an anchor anchorBodyDef = b2BodyDef() anchorBodyDef.position.Set(x, 0.0) anchor = box2dWorld.CreateBody(anchorBodyDef) shapeDef = b2PolygonDef() shapeDef.SetAsBox(1.0, 1.0) shapeDef.density = 1000 # kg/m^3, from wikipedia for styrofoam density anchor.CreateShape(shapeDef) anchor.SetMassFromShapes() self.anchor = anchor self.world = box2dWorld # Create the anchor joint self.move_anchor(0.0) def MakeTestKite(fluid, world): return Kite(x=2.0, y=20.0, anchor_point=0.12, polarity=1, body_length=6.0, wing_chord=1, wing_span=4.0, stabilizer_chord=0.5, stabilizer_span=1.5, fluid=fluid, box2dWorld=world) def MakeGiantKite(fluid, world): return Kite(x=2.0, y=20.0, anchor_point=0.12, polarity=1, body_length=8.0, wing_chord=2, wing_span=12.0, stabilizer_chord=1, stabilizer_span=8.0, fluid=fluid, box2dWorld=world) MakeTestKite = staticmethod(MakeTestKite) MakeGiantKite = staticmethod(MakeGiantKite) def get_force_vectors(self): return self.glider.get_force_vectors() def clear_force_vectors(self): self.glider.clear_force_vectors() def move_anchor(self, amount): anchor_point = self.glider.move_anchor(amount) if hasattr(self, "anchorJoint"): self.world.DestroyJoint(self.anchorJoint) self.add_anchor_joint(anchor_point) def add_anchor_joint(self, anchor_point): # Make a pully joint connecting the mount to the anchor anchorJoint = b2PulleyJointDef() anchor2 = self.anchor.GetWorldCenter() groundAnchor1 = b2Vec2(self.original_x - 0.2, 0.2) groundAnchor2 = b2Vec2(self.original_x - 0.1, 0.2) ratio = 1.0 anchorJoint.Initialize(self.glider.body, self.anchor, groundAnchor1, groundAnchor2, anchor_point, anchor2, ratio) anchorJoint.maxLength2 = 10.0 anchorJoint.collideConnected = False self.anchorJoint = self.world.CreateJoint(anchorJoint).getAsType() def step(self, damper=0.0): self.glider.step(damper) def draw(self, ctx): self.glider.draw(ctx)
class Evaluation: def __init__(self, gt, time=25, wsize=100, supervised=True): self.time = time self.wsize = wsize self.sup = supervised '''evaluate the glider behavior starting from each of the 4 canonical configurations''' def gt_eval(self, gt): # run trials data = [] for cfg in range(1, 5): # for supervised trials if self.sup: self.sup_sts = self.supervised_states(cfg) # new world and glider self.world = defaultdict(int) self.glider = Glider(gt, config=cfg) ft, prog, gl_states = self.trial() data.append([ft, prog, gl_states]) # average fitness # av_ft = sum([dtrial[0] for dtrial in data])/len(data) # weighted fitness sorted_fts = sorted([dt[0] for dt in data], reverse=True) wft = 2 / (len(data) * (len(data) + 1)) * sum([(i + 1) * fi for i, fi in enumerate(sorted_fts)]) data.insert(0, wft) return data '''just the continuous update of the glider elements history: space/domain conformed by the glider's cells fitness: number of living cells at each time step ft is intended to be global and simple, avoiding cells ft(?)''' def trial(self): ft = 0 prog = [] gl_states = [self.glider.state] # run trial for ti in range(self.time): # update world and glider self.update_world() self.glider.update(self.world) # save cells history gl_states.append(self.glider.state) # ids of living cells ai = np.where(self.glider.state[:, 5] > 0) prog.append(self.glider.state[ai][:, 0]) # fitness fx according to supervised/unsupervised trial if self.sup: # ft according to cells' known locations + surviving ft_t = self.supervised_ftfx(ti, gl_states[-2][:, 1:3]) else: # ft based only on number of surviving cells ft_t = np.sum(self.glider.state[:, 5]) # to give more importance to later states: max=418 # ft += ft_t*(ti+1)/10 ft += ft_t # in case all cells die before time if ft_t == 0: return (ft, prog, gl_states) return (ft, prog, gl_states) '''rules for world change, just reset in empty world''' def update_world(self): self.world = defaultdict(int) '''fts according to the known glider states (only xy)''' def supervised_ftfx(self, ti, gl_xy0): ct = ti % 4 # array with the 22 expected dxy sup_dxy = np.array([sup_ci[ct] for sup_ci in self.sup_sts]) # expected xy sup_xy = gl_xy0 + sup_dxy # discard dead cells glider_xy = self.glider.state[:, 1:3] * np.asarray( [self.glider.state[:, 5]]).T # compare expected vs glider sup_gl_xy = np.sum(sup_xy - glider_xy, axis=1) ft_t = np.sum(np.where(sup_gl_xy == 0, 1, 0)) return ft_t '''states to train the cells to behave as a glider (only xy)''' def supervised_states(self, cfg): sup_sts = [None] * 22 # glider cell blocks (cells with the same behavior) b0 = [i for i in range(1, 10)] b1 = [10, 11, 12] b2 = [14, 16, 18] b3 = [13, 15, 17] b4 = [19, 20, 21] b5 = [22] blocks = [b0, b1, b2, b3, b4, b5] # "correct" glider transitions: 0:g12, 2:g23, 3:g34, 4:g41 b0_sts = [(0, -1), (0, 0), (1, 0), (0, 0)] b1_sts = [(0, -1), (1, 0), (-1, 0), (1, 0)] b2_sts = [(0, 1), (0, -1), (1, 0), (0, -1)] b3_sts = [(0, 0), (0, -1), (1, 0), (0, 0)] b4_sts = [(0, -1), (0, 0), (0, 0), (1, 0)] b5_sts = [(0, 0), (0, -1), (0, 0), (1, 0)] block_sts = [b0_sts, b1_sts, b2_sts, b3_sts, b4_sts, b5_sts] # according to initial cfg if cfg == 1: cfg_sts = [0, 1, 2, 3] elif cfg == 2: cfg_sts = [1, 2, 3, 0] elif cfg == 3: cfg_sts = [2, 3, 0, 1] elif cfg == 4: cfg_sts = [3, 0, 1, 2] # map of correct movements for bi, block in enumerate(blocks): for ci in block: block_st = [block_sts[bi][cfg_i] for cfg_i in cfg_sts] # from 1:22 to 0:21 (for array) sup_sts[ci - 1] = block_st # sup_sts: list of lists (index = sorted cell correct cfg xy) return sup_sts
class Craft(object): def __init__(self, windspeed, relative_scale, world): self.air = Air(b2Vec2(-windspeed, 0.0)) self.water = Water(b2Vec2(0.0,0.0)) self.world = world gap = 10.0 h_length = 1.0 h_wchord = 0.5 h_wspan = 2.0 h_schord = 0.25 h_sspan = 0.75 a_length = h_length * relative_scale a_wchord = h_wchord * relative_scale a_wspan = h_wspan * relative_scale a_schord = h_schord * relative_scale a_sspan = h_sspan * relative_scale self.airfoil = Glider (x=0.0, y=gap*0.5, anchor_point=0.12, polarity=1.0, body_length=a_length, wing_chord=a_wchord, wing_span=a_wspan, stabilizer_chord=a_schord, stabilizer_span=a_sspan, fluid=self.air, box2dWorld=world, density=50.0) self.hydrofoil = Glider (x=0.0, y=gap*-0.5, anchor_point=0.12, polarity=-1.0, body_length=h_length, wing_chord=h_wchord, wing_span=h_wspan, stabilizer_chord=h_schord, stabilizer_span=h_sspan, fluid=self.water, box2dWorld=world, density=300.0) self.add_anchor_joint() def windspeed(self): return self.air.velocity.Length() def move_anchor(self, glider, amount): glider.move_anchor(amount) if hasattr(self, "anchorJoint"): self.world.DestroyJoint(self.anchorJoint) self.add_anchor_joint() def add_anchor_joint(self): anchorJoint = b2DistanceJointDef() anchor1 = self.airfoil.get_anchor_point() anchor2 = self.hydrofoil.get_anchor_point() anchorJoint.Initialize(self.airfoil.body, self.hydrofoil.body, anchor1, anchor2); anchorJoint.collideConnected = True self.anchorJoint = self.world.CreateJoint(anchorJoint).getAsType() def get_center(self): return (self.airfoil.body.GetPosition() + self.hydrofoil.body.GetPosition()) * 0.5 def step(self, damper=0.0): self.airfoil.step(damper) self.hydrofoil.step(damper) def draw(self, ctx): self.airfoil.draw(ctx) self.hydrofoil.draw(ctx) def get_force_vectors(self): forces = [] forces += self.airfoil.get_force_vectors() forces += self.hydrofoil.get_force_vectors() return forces def clear_force_vectors(self): self.airfoil.clear_force_vectors() self.hydrofoil.clear_force_vectors() def velocity(self): return (self.hydrofoil.velocity() + self.airfoil.velocity()) / 2.0
class Kite(object): def __init__(self, x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld): self.glider = Glider(x, y, anchor_point, polarity, body_length, wing_chord, wing_span, stabilizer_chord, stabilizer_span, fluid, box2dWorld) self.original_x = x # Make an anchor anchorBodyDef = b2BodyDef() anchorBodyDef.position.Set(x, 0.0) anchor = box2dWorld.CreateBody(anchorBodyDef) shapeDef = b2PolygonDef() shapeDef.SetAsBox(1.0, 1.0) shapeDef.density = 1000 # kg/m^3, from wikipedia for styrofoam density anchor.CreateShape(shapeDef) anchor.SetMassFromShapes() self.anchor = anchor self.world = box2dWorld # Create the anchor joint self.move_anchor(0.0) def MakeTestKite(fluid, world): return Kite(x=2.0, y=20.0, anchor_point=0.12, polarity=1, body_length=6.0, wing_chord=1, wing_span=4.0, stabilizer_chord=0.5, stabilizer_span=1.5, fluid=fluid, box2dWorld=world) def MakeGiantKite(fluid, world): return Kite(x=2.0, y=20.0, anchor_point=0.12, polarity=1, body_length=8.0, wing_chord=2, wing_span=12.0, stabilizer_chord=1, stabilizer_span=8.0, fluid=fluid, box2dWorld=world) MakeTestKite = staticmethod(MakeTestKite) MakeGiantKite = staticmethod(MakeGiantKite) def get_force_vectors(self): return self.glider.get_force_vectors() def clear_force_vectors(self): self.glider.clear_force_vectors() def move_anchor(self, amount): anchor_point = self.glider.move_anchor(amount) if hasattr(self, "anchorJoint"): self.world.DestroyJoint(self.anchorJoint) self.add_anchor_joint(anchor_point) def add_anchor_joint(self, anchor_point): # Make a pully joint connecting the mount to the anchor anchorJoint = b2PulleyJointDef() anchor2 = self.anchor.GetWorldCenter() groundAnchor1 = b2Vec2(self.original_x - 0.2, 0.2) groundAnchor2 = b2Vec2(self.original_x - 0.1, 0.2) ratio = 1.0 anchorJoint.Initialize(self.glider.body, self.anchor, groundAnchor1, groundAnchor2, anchor_point, anchor2, ratio); anchorJoint.maxLength2 = 10.0 anchorJoint.collideConnected = False self.anchorJoint = self.world.CreateJoint(anchorJoint).getAsType() def step(self, damper=0.0): self.glider.step(damper) def draw(self, ctx): self.glider.draw(ctx)