Exemplo n.º 1
0
 def color(self):
     """Render cell's genome as hue/sat, cell's energy as value."""
     if self._legacy_coloring:
         red, green, blue = GenomeColor.modular(self.main.rule >> 1, 360)
     else:
         red, green, blue = GenomeColor.positional(self.main.rule,
                                                   self.main.rule.bit_width)
     is_live = (self.main.rule > 0) * (self.main.energy < 255)
     energy = (255 - self.main.energy) * is_live
     red = xmath.int(red * energy)
     green = xmath.int(green * energy)
     blue = xmath.int(blue * energy)
     return (red, green, blue, )
Exemplo n.º 2
0
    def emit(self):
        """Apply ConcervedLife dynamics."""
        self.main.new_energy = 1 * self.main.energy

        # calculate number of full neighbors
        num_full = core.IntegerVariable()
        for i in range(len(self.buffers)):
            is_full = self.neighbors[i].main.energy >= self.meta.full_treshold
            num_full += is_full

        # decide, do cell need to spread an energy
        me_full = self.main.energy >= self.meta.full_treshold
        me_empty = self.main.energy < self.meta.full_treshold
        me_dying = xmath.int(self.main.rule.is_sustained(num_full)) == 0
        me_dying = xmath.int(me_dying)
        me_birthing = self.main.rule.is_born(num_full)
        has_free_energy = self.main.energy > self.meta.full_treshold
        has_free_energy = xmath.int(has_free_energy)
        need_spread_full = 1 * me_full * (has_free_energy | me_dying)
        need_spread_empty = 1 * me_empty * (xmath.int(me_birthing) == 0)
        need_spread = need_spread_full + need_spread_empty

        # search the direction to spread energy
        denergy = core.IntegerVariable()
        energy_passed = core.IntegerVariable()
        energy_passed *= 1
        gate = core.IntegerVariable()
        gate += xmath.int(self.main.rng.uniform * 8)
        gate_final = core.IntegerVariable()
        treshold = self.meta.full_treshold
        for i in range(len(self.buffers) * 3):
            i_valid = (i >= gate) * (i < gate + len(self.buffers) * 2)
            is_birthing = self.neighbors[i % 8].main.birthing * (i < 8 + gate)
            is_empty = self.neighbors[i % 8].main.energy < treshold
            is_empty = is_empty * (i >= 8 + gate)
            is_fit = is_empty + is_birthing
            denergy *= 0
            denergy += xmath.min(self.main.new_energy, self.meta.death_speed)
            denergy *= need_spread * is_fit * (energy_passed == 0)
            denergy *= i_valid
            gate_final *= (energy_passed != 0)
            gate_final += (i % 8) * (energy_passed == 0)
            energy_passed += denergy

        # spread the energy in chosen direction
        for i in range(len(self.buffers)):
            gate_fit = i == gate_final
            self.buffers[i].energy = energy_passed * gate_fit
            self.buffers[i].rule = self.main.rule * gate_fit

        self.main.new_energy -= energy_passed
Exemplo n.º 3
0
def genome_crossover(state, num_genes, *genomes, max_genes=None,
                     mutation_prob=0, rng_name="rng"):
    """
    Crossover given genomes in stochastic way.

    :param state:
        A container holding model's properties.
    :param num_genes:
        Genome length, assuming all genomes has the same number of genes.
    :param genomes:
        A list of genomes (integers) to crossover
    :param max_genes:
        Upper limit for '1' genes in the resulting genome.
    :param mutation_prob:
        Probability of a single gene's mutation.
    :param rng_name:
        Name of ``RandomProperty``.

    :returns: Single integer, a resulting genome.

    """
    max_genes = max_genes or num_genes
    gene_choose = core.IntegerVariable()
    new_genome = core.IntegerVariable()
    num_genomes = core.IntegerVariable()
    num_active = core.IntegerVariable()
    new_gene = core.IntegerVariable()
    rand_val = getattr(state, rng_name).uniform
    start_gene = core.IntegerVariable()
    start_gene *= 0
    start_gene += xmath.int(rand_val * num_genes) % len(genomes)
    for gene in range(num_genes):
        gene_choose *= 0
        num_genomes *= 0
        gene = (gene + start_gene) % num_genes
        for genome in genomes:
            gene_choose += ((genome >> gene) & 1 & (genome > 0)) << num_genomes
            num_genomes += (genome > 0)
        rand_val = getattr(state, rng_name).uniform
        winner_gene = xmath.int(rand_val * num_genomes)
        new_gene *= 0
        new_gene += ((gene_choose >> winner_gene) & 1)
        num_active += new_gene
        new_gene *= num_active <= max_genes
        is_mutated = 0
        if mutation_prob > 0:
            is_mutated = getattr(state, rng_name).uniform < mutation_prob
            is_mutated = is_mutated * (gene_choose > 0)
        new_genome += (new_gene ^ is_mutated) << gene
    return new_genome
Exemplo n.º 4
0
    def emit(self):
        """
        Implement the logic of emit phase.

        Each cell is a Poisson process that fires an energy in the
        gate direction, when Poisson event occurs.

        The rate of events depends on cell's energy level: more
        energy, higher the rate.

        The amount of energy depends on the cell's own "valency" and
        its gated neighbour's "valency" (energy % 8).

        When neighbour's valency is 0, cell spreads the amount of
        energy, equal to its own valency. Otherwise, it spreads some
        default amount of energy.

        Cells are also spreading their gate values when event occurs,
        so they are "syncing" with neighbours.

        """
        shade = xmath.min(255, self.main.energy)
        lmb = xmath.float(self.main.interval) / xmath.float(256 - shade)
        prob = 1 - xmath.exp(-lmb)
        fired = core.IntegerVariable()
        fired += xmath.int(self.main.rng.uniform < prob)
        fired *= self.main.energy > 0
        denergy = xmath.min(self.default_denergy, shade)
        gate = self.main.gate

        mutated = core.IntegerVariable()
        mutated += xmath.int(self.main.rng.uniform < 0.0001)
        denergy = denergy - 1 * (denergy > 0) * mutated
        energy_passed = core.IntegerVariable()
        for i in range(len(self.buffers)):
            valency1 = self.neighbors[i].main.energy % 8
            valency2 = self.main.energy % 8
            gate_fit = (i == gate)
            full_transition = denergy * (valency1 != 0 | valency2 == 0)
            potent_transition = valency2 * (valency1 == 0)
            denergy_fin = full_transition + potent_transition
            energy_passed += denergy_fin * fired * gate_fit
            self.buffers[i].energy = energy_passed * fired * gate_fit
            self.buffers[i].gate = (self.main.gate + 7) * fired * gate_fit

        self.main.interval = (self.main.interval + 1) * (energy_passed == 0)
        self.main.energy -= energy_passed * (energy_passed > 0)
        self.main.gate = (self.main.gate + 1) % 8
Exemplo n.º 5
0
 def _get_next(self):
     """Generate and return the next RNG value."""
     val_int = xmath.int(DeferredExpression(self.var_name))
     val = ((val_int * 58321 + 11113)) % 65535
     self.__set__(self, val)
     container = inspect.currentframe().f_back.f_locals['obj']
     self.bsca.deferred_write(container)
Exemplo n.º 6
0
 def color(self):
     """Render cell's genome as hue/sat, cell's energy as value."""
     if self._legacy_coloring:
         red, green, blue = GenomeColor.modular(self.main.rule >> 1, 360)
     else:
         red, green, blue = GenomeColor.positional(self.main.rule,
                                                   self.main.rule.bit_width)
     shade = xmath.min(self.main.energy, self.meta.full_treshold)
     shade = shade * 255 / self.meta.full_treshold
     red = xmath.int(red * shade)
     green = xmath.int(green * shade)
     blue = xmath.int(blue * shade)
     return (
         red,
         green,
         blue,
     )
Exemplo n.º 7
0
def hsv2rgb(hue, saturation, value):
    """
    Convert HSV color to RGB format.

    :param hue: Hue value [0, 1]
    :param saturation: Saturation value [0, 1]
    :param value: Brightness value [0, 1]

    :returns: tuple (red, green, blue)

    """
    if isinstance(hue, DeferredExpression):
        hue_f = core.FloatVariable()
        hue_f += hue * 6
        hue_i = core.IntegerVariable()
        hue_i += xmath.int(hue_f)
        hue_f -= hue_i
        sat = core.FloatVariable()
        sat += saturation
        val = core.FloatVariable()
        val += value
        grad_p = core.FloatVariable()
        grad_p += val * (1 - sat)
        grad_q = core.FloatVariable()
        grad_q += val * (1 - sat * hue_f)
        grad_t = core.FloatVariable()
        grad_t += val * (1 - sat * (1 - hue_f))
    else:
        hue_f = hue * 6
        hue_i = int(hue_f)
        hue_f -= hue_i
        sat = saturation
        val = value
        grad_p = val * (1 - sat)
        grad_q = val * (1 - sat * hue_f)
        grad_t = val * (1 - sat * (1 - hue_f))

    red = ((hue_i == 0) | (hue_i >= 5)) * val
    red = red + (hue_i == 1) * grad_q
    red = red + ((hue_i == 2) | (hue_i == 3)) * grad_p
    red = red + (hue_i == 4) * grad_t

    green = ((hue_i == 0) | (hue_i >= 6)) * grad_t
    green = green + ((hue_i == 1) | (hue_i == 2)) * val
    green = green + (hue_i == 3) * grad_q
    green = green + ((hue_i == 4) | (hue_i == 5)) * grad_p

    blue = ((hue_i == 0) | (hue_i == 1) | (hue_i >= 6)) * grad_p
    blue = blue + (hue_i == 2) * grad_t
    blue = blue + ((hue_i == 3) | (hue_i == 4)) * val
    blue = blue + (hue_i == 5) * grad_q

    return (red, green, blue)
Exemplo n.º 8
0
 def color(self):
     """Make some noise, now for real."""
     val = xmath.int(self.main.rng.uniform * 255)
     return (val, val, val)