Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/ep_layer_markovchain.py
blob: 066a5ac189bd937dfe4d3a6b49dbc46a533f1d83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# coding: UTF8
# Copyright 2009 Thomas Jourdan
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import random
import exon_color
import model_layer
import ka_random

class MarkovChainLayer(model_layer.Layer):
    """Markov chain layer
    inv: self.cell_colors is not None and len(self.cell_colors) == self.states
    inv: self.probability is not None and len(self.probability) == self.states
    inv: 1 <= self.square_base <= 7
    """

    def __init__(self, trunk):
        """Markov chain layer constructor"""
        super(MarkovChainLayer, self).__init__(trunk)
        self.states = 4
        self.square_base = 3
        self.cell_colors = [None] * self.states
        for cix in range(len(self.cell_colors)):
            self.cell_colors[cix] = exon_color.Color(self.path, 0, 0, 0, 1)
        self.probability = [[1.0 / self.states] * self.states for i in range(self.states)]
#        for row, row_probabilities in enumerate(other.probability):
#            for col, cell_probability in enumerate(row_probabilities):
#                self.probability[row][col] = 1.0 / self.states

    def __eq__(self, other):
        """Equality based on the cells color components."""
        equal = isinstance(other, MarkovChainLayer) \
                and super(MarkovChainLayer, self).__eq__(other) \
                and self.states == other.states \
                and self.square_base == other.square_base
        if equal:
            for cix, cell_color in enumerate(self.cell_colors):
                equal = equal and cell_color == other.cell_colors[cix]
        if equal:
            for row, row_probabilities in enumerate(self.probability):
                for col, cell_probability in enumerate(row_probabilities):
                    equal = equal and cell_probability == other.probability[row][col]
        return equal

    def randomize(self):
        """Randomize the layers components."""
        super(MarkovChainLayer, self).randomize()
        for cix in range(len(self.cell_colors)):
            self.cell_colors[cix].randomize()
        for row, row_probabilities in enumerate(self.probability):
            for col in range(len(row_probabilities)):
                self.probability[row][col] = random.random() / self.states
        self.square_base = random.randint(1, 7)

    def mutate(self):
        """Make small random changes to the layers components."""
        super(MarkovChainLayer, self).mutate()
        for cix in range(len(self.cell_colors)):
            self.cell_colors[cix].mutate()
        for row, row_probabilities in enumerate(self.probability):
            for col, cell_probability in enumerate(row_probabilities):
                val = ka_random.limitate(cell_probability \
                                    + ka_random.jitter(1.0 / self.states))
                self.probability[row][col] = val
        if ka_random.is_mutating():
            self.square_base += random.randint(-1, 1)
        self.square_base = ka_random.limitate_range(self.square_base, 1, 7)

    def shuffle(self):
        """Shuffle similar componets.
        For example exchange foreground and background color."""
        super(MarkovChainLayer, self).shuffle()
        if ka_random.is_shuffling():
            random.shuffle(self.cell_colors)
        if ka_random.is_shuffling():
            random.shuffle(self.probability)
        for row_probabilities in self.probability:
            if ka_random.is_shuffling():
                random.shuffle(row_probabilities)

    def crossingover(self, other):
        """
        pre: isinstance(other, MarkovChainLayer)
        pre: isinstance(self, MarkovChainLayer)
        # check for distinct references, needs to copy content, not references
        post: __return__ is not self
        post: __return__ is not other
        """
        new_one = MarkovChainLayer(self.get_trunk())
        cross_sequence = self.crossingover_base(new_one, other, \
                                                1 + len(self.cell_colors))
        if cross_sequence[0]:
            new_one.square_base = self.square_base
        else:
            new_one.square_base = other.square_base
        for cix in range(len(self.cell_colors)):
            if cross_sequence[1 + cix]:
                new_one.cell_colors[cix] = self.cell_colors[cix].copy()
            else:
                new_one.cell_colors[cix] = other.cell_colors[cix].copy()
        return new_one

    def draw(self, ctx, width, height):
        """
        pre: ctx is not None
        pre: width > 0
        pre: height > 0
        pre: width == height
        """
        self.begin_draw(ctx, width, height)
        cell_state = 0
        dim = self.square_base**2
        delta_x, delta_y = 1.0 / dim, 1.0 / dim
        for y_index in range(dim):
            for x_index in range(dim):
                rgba = self.cell_colors[cell_state].rgba
                ctx.set_source_rgba(rgba[0], rgba[1], rgba[2], rgba[3])
                ctx.rectangle((x_index-0.5*dim)*delta_x, \
                              (y_index-0.5*dim)*delta_y, \
                              delta_x, delta_y)
                ctx.fill()
                cell_state = (cell_state+1) % self.states

    def explain(self, formater):
#        super(MarkovChainLayer, self).explain(formater)
        formater.color_array(self.cell_colors, 'cell colors:')

    def copy(self):
        """The Markov chain layer copy constructor
        # check for distinct references, needs to copy content, not references
        post: __return__ is not self
        """
        new_one = MarkovChainLayer(self.get_trunk())
        self.copy_base(new_one)
        new_one.states = self.states
        new_one.square_base = self.square_base 
        new_one.cell_colors = [None] * self.states
        for cix in range(len(self.cell_colors)):
            new_one.cell_colors[cix] = self.cell_colors[cix].copy()
        new_one.probability = [[0.0] * self.states for i in range(self.states)]
        for row, row_probabilities in enumerate(self.probability):
            for col, cell_probability in enumerate(row_probabilities):
                new_one.probability[row][col] = cell_probability
        return new_one