def test_alphabet_unions():
    # Thanks to sparse maps it should now be possible to compute the union of FSMs
    # with disagreeing alphabets!
    a = fsm(
        alphabet={"a"},
        states={0, 1},
        initial=0,
        finals={1},
        map={
            0: {
                "a": 1
            },
        },
    )

    b = fsm(
        alphabet={"b"},
        states={0, 1},
        initial=0,
        finals={1},
        map={
            0: {
                "b": 1
            },
        },
    )

    assert (a | b).accepts(["a"])
    assert (a | b).accepts(["b"])
    assert (a & b).empty()
    assert (a + b).accepts(["a", "b"])
    assert (a ^ b).accepts(["a"])
    assert (a ^ b).accepts(["b"])
Example #2
0
def test_empty(a, b):
	assert not a.empty()
	assert not b.empty()

	assert fsm(
		alphabet = {},
		states = {0, 1},
		initial = 0,
		finals = {1},
		map = {0:{}, 1:{}},
	).empty()

	assert not fsm(
		alphabet = {},
		states = {0},
		initial = 0,
		finals = {0},
		map = {0:{}},
	).empty()

	assert fsm(
		alphabet = {"a", "b"},
		states = {0, 1, None, 2},
		initial = 0,
		finals = {2},
		map = { 
			0    : {"a" : 1   , "b" : 1   },
			1    : {"a" : None, "b" : None},
			None : {"a" : None, "b" : None},
			2    : {"a" : None, "b" : None},
		},
	).empty()
Example #3
0
def test_alphabet_unions():
	# Thanks to sparse maps it should now be possible to compute the union of FSMs
	# with disagreeing alphabets!
	a = fsm(
		alphabet = {"a"},
		states   = {0, 1},
		initial  = 0,
		finals   = {1},
		map      = {
			0    : {"a" : 1},
		},
	)

	b = fsm(
		alphabet = {"b"},
		states   = {0, 1},
		initial  = 0,
		finals   = {1},
		map      = {
			0    : {"b" : 1},
		},
	)

	assert (a | b).accepts(["a"])
	assert (a | b).accepts(["b"])
	assert (a & b).empty()
	assert (a + b).accepts(["a", "b"])
	assert (a ^ b).accepts(["a"])
	assert (a ^ b).accepts(["b"])
Example #4
0
def test_bug_36():
    etc1 = fsm(alphabet={anything_else},
               states={0},
               initial=0,
               finals={0},
               map={0: {
                   anything_else: 0
               }})
    etc2 = fsm(alphabet={'s', anything_else},
               states={0, 1},
               initial=0,
               finals={1},
               map={
                   0: {
                       's': 1
                   },
                   1: {
                       's': 1,
                       anything_else: 1
                   }
               })
    both = etc1 & etc2
    assert etc1.accepts(["s"])
    assert etc2.accepts(["s"])
    assert both.alphabet == {anything_else, "s"}
    assert both.accepts(["s"])
Example #5
0
def test_addbug():
	# Odd bug with fsm.__add__(), exposed by "[bc]*c"
	int5A = fsm(
		alphabet = {"a", "b", "c", anything_else},
		states   = {0, 1},
		initial  = 1,
		finals   = {1},
		map      = {
			0: {anything_else: 0, "a": 0, "b": 0, "c": 0},
			1: {anything_else: 0, "a": 0, "b": 1, "c": 1},
		}
	)
	assert int5A.accepts("")

	int5B = fsm(
		alphabet = {"a", "b", "c", anything_else},
		states   = {0, 1, 2},
		initial  = 1,
		finals   = {0},
		map      = {
			0: {anything_else: 2, "a": 2, "b": 2, "c": 2},
			1: {anything_else: 2, "a": 2, "b": 2, "c": 0},
			2: {anything_else: 2, "a": 2, "b": 2, "c": 2},
		}
	)
	assert int5B.accepts("c")

	int5C = int5A + int5B
	assert int5C.accepts("c")
def test_addbug():
    # Odd bug with fsm.__add__(), exposed by "[bc]*c"
    int5A = fsm(alphabet={"a", "b", "c", anything_else},
                states={0, 1},
                initial=1,
                finals={1},
                map={
                    0: {
                        anything_else: 0,
                        "a": 0,
                        "b": 0,
                        "c": 0
                    },
                    1: {
                        anything_else: 0,
                        "a": 0,
                        "b": 1,
                        "c": 1
                    },
                })
    assert int5A.accepts("")

    int5B = fsm(alphabet={"a", "b", "c", anything_else},
                states={0, 1, 2},
                initial=1,
                finals={0},
                map={
                    0: {
                        anything_else: 2,
                        "a": 2,
                        "b": 2,
                        "c": 2
                    },
                    1: {
                        anything_else: 2,
                        "a": 2,
                        "b": 2,
                        "c": 0
                    },
                    2: {
                        anything_else: 2,
                        "a": 2,
                        "b": 2,
                        "c": 2
                    },
                })
    assert int5B.accepts("c")

    int5C = int5A + int5B
    assert int5C.accepts("c")
def test_empty(a, b):
    assert not a.empty()
    assert not b.empty()

    assert fsm(
        alphabet={},
        states={0, 1},
        initial=0,
        finals={1},
        map={
            0: {},
            1: {}
        },
    ).empty()

    assert not fsm(
        alphabet={},
        states={0},
        initial=0,
        finals={0},
        map={
            0: {}
        },
    ).empty()

    assert fsm(
        alphabet={"a", "b"},
        states={0, 1, None, 2},
        initial=0,
        finals={2},
        map={
            0: {
                "a": 1,
                "b": 1
            },
            1: {
                "a": None,
                "b": None
            },
            None: {
                "a": None,
                "b": None
            },
            2: {
                "a": None,
                "b": None
            },
        },
    ).empty()
Example #8
0
def internal_mutation_fsm(ind, indpb, new_layer_pb, config):
    num_layers = len(ind.net_struct)
    for pos_layer in range(0, num_layers):

        parameters_dict = ind.net_struct[pos_layer].parameters
        layer_type = ind.net_struct[pos_layer].type
        for parameter in parameters_dict.keys():
            # TODO QUITA LA ÑAPA Alex
            if random.random(
            ) < indpb and parameter != 'input_shape' and parameter != 'units':
                parameters_dict[parameter] = generate_random_layer_parameter(
                    parameter, layer_type, config)

    if random.random() < new_layer_pb:
        # Where to insert new layers?
        position = random.choice(range(0, len(ind.net_struct) - 1))
        init_type = ind.net_struct[position].type
        end_type = ind.net_struct[position + 1].type
        the_map = config.fsm['map']
        # Forces the FSM to start at the same type as the selected gen
        the_map['inicial'] = {init_type: init_type}
        state_machine = fsm(alphabet=set(config.fsm['alphabet']),
                            states=set(config.fsm['states']),
                            initial="inicial",
                            finals={end_type},
                            map=the_map)
        # Computes sequences [init_type, ..., end_type] with length between 3 and 5 in order to insert 1 to 3 new layers
        candidates = list(
            itertools.takewhile(
                lambda c: len(c) <= 5,
                itertools.dropwhile(lambda l: len(l) < 3,
                                    state_machine.strings())))

        first_layers = list(set([b[0] for b in candidates]))
        candidates = [
            random.choice([z for z in candidates if z[0] == first_layers[l]])
            for l in range(len(first_layers))
        ]

        # Sizes of the candidates
        sizes = list(set(map(len, candidates)))
        max_layers = config.global_parameters['number_layers']['values'][1]
        sizes = list(
            filter(lambda s: s <= max_layers - len(ind.net_struct), sizes))
        if sizes:
            # Chooses a size of candidate...
            random_size = random.choice(sizes)
            candidates_size = list(
                filter(lambda c: len(c) == random_size, candidates))
            if candidates_size:
                # ... and selects it as the layers to be inserted
                candidate = random.choice(candidates_size)
                candidate = list(map(lambda lt: Layer([lt], config),
                                     candidate))
                # Updates the individual with new layers
                ind.net_struct = ind.net_struct[:position + 1] + candidate[
                    1:-1] + ind.net_struct[position + 1:]

    ind.global_attributes.number_layers = len(ind.net_struct)
    return ind
Example #9
0
def test_base_N():
	# Machine accepts only numbers in selected base (e.g. 2, 10) that are
	# divisible by N (e.g. 3, 7).
	# "0" alone is acceptable, but leading zeroes (e.g. "00", "07") are not
	base = 2
	N = 3
	assert base <= 10
	divN = from_fsm(fsm.fsm(
		alphabet = set(str(i) for i in range(base)),
		states = set(range(N)) | {"initial", "zero", None},
		initial = "initial",
		finals = {"zero", 0},
		map = dict(
			[
				("initial", dict([(str(j), j              % N) for j in range(1, base)] + [("0", "zero")])),
				("zero"   , dict([(str(j), None              ) for j in range(   base)]                  )),
				(None     , dict([(str(j), None              ) for j in range(   base)]                  )),
			] + [
				(i        , dict([(str(j), (i * base + j) % N) for j in range(   base)]                  ))
				for i in range(N)
			]
		),
	))
	gen = divN.strings()
	a = next(gen)
	assert a == "0"
	for i in range(7):
		b = next(gen)
		assert int(a, base) + N == int(b, base)
		a = b
Example #10
0
def test_binary_3():
	# Binary numbers divisible by 3.
	# Disallows the empty string
	# Allows "0" on its own, but not leading zeroes.
	div3 = from_fsm(fsm.fsm(
		alphabet = {"0", "1"},
		states = {"initial", "zero", 0, 1, 2, None},
		initial = "initial",
		finals = {"zero", 0},
		map = {
			"initial" : {"0" : "zero", "1" : 1   },
			"zero"    : {"0" : None  , "1" : None},
			0         : {"0" : 0     , "1" : 1   },
			1         : {"0" : 2     , "1" : 0   },
			2         : {"0" : 1     , "1" : 2   },
			None      : {"0" : None  , "1" : None},
		},
	))
	assert str(div3) == "0|1(01*0|10*1)*10*"
	gen = div3.strings()
	assert next(gen) == "0"
	assert next(gen) == "11"
	assert next(gen) == "110"
	assert next(gen) == "1001"
	assert next(gen) == "1100"
Example #11
0
def test_base_N():
	# Machine accepts only numbers in selected base (e.g. 2, 10) that are
	# divisible by N (e.g. 3, 7).
	# "0" alone is acceptable, but leading zeroes (e.g. "00", "07") are not
	base = 2
	N = 3
	assert base <= 10
	divN = from_fsm(fsm.fsm(
		alphabet = set(str(i) for i in range(base)),
		states = set(range(N)) | {"initial", "zero", None},
		initial = "initial",
		finals = {"zero", 0},
		map = dict(
			[
				("initial", dict([(str(j), j              % N) for j in range(1, base)] + [("0", "zero")])),
				("zero"   , dict([(str(j), None              ) for j in range(   base)]                  )),
				(None     , dict([(str(j), None              ) for j in range(   base)]                  )),
			] + [
				(i        , dict([(str(j), (i * base + j) % N) for j in range(   base)]                  ))
				for i in range(N)
			]
		),
	))
	gen = divN.strings()
	a = next(gen)
	assert a == "0"
	for i in range(7):
		b = next(gen)
		assert int(a, base) + N == int(b, base)
		a = b
def test_difference(a, b):
    aorb = fsm(
        alphabet={"a", "b"},
        states={0, 1, None},
        initial=0,
        finals={1},
        map={
            0: {
                "a": 1,
                "b": 1
            },
            1: {
                "a": None,
                "b": None
            },
            None: {
                "a": None,
                "b": None
            },
        },
    )

    assert list((a ^ a).strings()) == []
    assert list((b ^ b).strings()) == []
    assert list((a ^ b).strings()) == [["a"], ["b"]]
    assert list((aorb ^ a).strings()) == [["b"]]
Example #13
0
	def fsm(self, alphabet=None):
		from greenery.fsm import fsm

		if alphabet is None:
			alphabet = self.alphabet()

		# 0 is initial, 1 is final, 2 is oblivion

		# If negated, make a singular FSM accepting any other characters
		if self.negated:
			map = {
				0: dict([(symbol, 2 if symbol in self.chars else 1) for symbol in alphabet]),
				1: dict([(symbol, 2) for symbol in alphabet]),
				2: dict([(symbol, 2) for symbol in alphabet]),
			}

		# If normal, make a singular FSM accepting only these characters
		else:
			map = {
				0: dict([(symbol, 1 if symbol in self.chars else 2) for symbol in alphabet]),
				1: dict([(symbol, 2) for symbol in alphabet]),
				2: dict([(symbol, 2) for symbol in alphabet]),
			}

		return fsm(
			alphabet = alphabet,
			states   = set([0, 1, 2]),
			initial  = 0,
			finals   = set([1]),
			map      = map,
		)
def test_crawl_reduction():
    # this is "0*1" in heavy disguise. crawl should resolve this duplication
    # Notice how states 2 and 3 behave identically. When resolved together,
    # states 1 and 2&3 also behave identically, so they, too should be resolved
    # (this is impossible to spot before 2 and 3 have been combined).
    # Finally, the oblivion state should be omitted.
    merged = fsm(alphabet={"0", "1"},
                 states={1, 2, 3, 4, "oblivion"},
                 initial=1,
                 finals={4},
                 map={
                     1: {
                         "0": 2,
                         "1": 4
                     },
                     2: {
                         "0": 3,
                         "1": 4
                     },
                     3: {
                         "0": 3,
                         "1": 4
                     },
                     4: {
                         "0": "oblivion",
                         "1": "oblivion"
                     },
                     "oblivion": {
                         "0": "oblivion",
                         "1": "oblivion"
                     },
                 }).reduce()
    assert len(merged.states) == 2
def test_oblivion_crawl(a):
    # When crawling a new FSM, we should avoid generating an oblivion state.
    # `abc` has no oblivion state... all the results should not as well!
    abc = fsm(alphabet={"a", "b", "c"},
              states={0, 1, 2, 3},
              initial=0,
              finals={3},
              map={
                  0: {
                      "a": 1
                  },
                  1: {
                      "b": 2
                  },
                  2: {
                      "c": 3
                  },
              })
    assert len((abc + abc).states) == 7
    assert len(abc.star().states) == 3
    assert len((abc * 3).states) == 10
    assert len(reversed(abc).states) == 4
    assert len((abc | abc).states) == 4
    assert len((abc & abc).states) == 4
    assert len((abc ^ abc).states) == 1
    assert len((abc - abc).states) == 1
Example #16
0
def test_even_star_bug():
	# Bug fix. This is a(a{2})* (i.e. accepts an odd number of "a" chars in a
	# row), but when from_fsm() is called, the result is "a+". Turned out to be
	# a fault in the lego.multiplier.__mul__() routine
	elesscomplex = fsm.fsm(
		alphabet = {"a"},
		states = {0, 1},
		initial = 0,
		finals = {1},
		map = {
			0 : {"a" : 1},
			1 : {"a" : 0},
		},
	)
	assert not elesscomplex.accepts("")
	assert elesscomplex.accepts("a")
	assert not elesscomplex.accepts("aa")
	assert elesscomplex.accepts("aaa")
	elesscomplex = from_fsm(elesscomplex)
	assert str(elesscomplex) in {"a(aa)*", "(aa)*a"}
	elesscomplex = elesscomplex.to_fsm()
	assert not elesscomplex.accepts("")
	assert elesscomplex.accepts("a")
	assert not elesscomplex.accepts("aa")
	assert elesscomplex.accepts("aaa")
	gen = elesscomplex.strings()
	assert next(gen) == ["a"]
	assert next(gen) == ["a", "a", "a"]
	assert next(gen) == ["a", "a", "a", "a", "a"]
	assert next(gen) == ["a", "a", "a", "a", "a", "a", "a"]
Example #17
0
def test_star_advanced():
	# This is (a*ba)*. Naively connecting the final states to the initial state
	# gives the incorrect result here.
	starred = fsm(
		alphabet = {"a", "b"},
		states   = {0, 1, 2, "oblivion"},
		initial  = 0,
		finals   = {2},
		map      = {
			0          : {"a" : 0         , "b" : 1         },
			1          : {"a" : 2         , "b" : "oblivion"},
			2          : {"a" : "oblivion", "b" : "oblivion"},
			"oblivion" : {"a" : "oblivion", "b" : "oblivion"},
		}
	).star()
	assert starred.alphabet == frozenset(["a", "b"])
	assert starred.accepts("")
	assert not starred.accepts("a")
	assert not starred.accepts("b")
	assert not starred.accepts("aa")
	assert starred.accepts("ba")
	assert starred.accepts("aba")
	assert starred.accepts("aaba")
	assert not starred.accepts("aabb")
	assert starred.accepts("abababa")
Example #18
0
def test_even_star_bug():
	# Bug fix. This is a(a{2})* (i.e. accepts an odd number of "a" chars in a
	# row), but when from_fsm() is called, the result is "a+". Turned out to be
	# a fault in the lego.multiplier.__mul__() routine
	elesscomplex = fsm.fsm(
		alphabet = {"a"},
		states = {0, 1},
		initial = 0,
		finals = {1},
		map = {
			0 : {"a" : 1},
			1 : {"a" : 0},
		},
	)
	assert not elesscomplex.accepts("")
	assert elesscomplex.accepts("a")
	assert not elesscomplex.accepts("aa")
	assert elesscomplex.accepts("aaa")
	elesscomplex = from_fsm(elesscomplex)
	assert str(elesscomplex) in {"a(aa)*", "(aa)*a"}
	elesscomplex = elesscomplex.to_fsm()
	assert not elesscomplex.accepts("")
	assert elesscomplex.accepts("a")
	assert not elesscomplex.accepts("aa")
	assert elesscomplex.accepts("aaa")
	gen = elesscomplex.strings()
	assert next(gen) == ["a"]
	assert next(gen) == ["a", "a", "a"]
	assert next(gen) == ["a", "a", "a", "a", "a"]
	assert next(gen) == ["a", "a", "a", "a", "a", "a", "a"]
Example #19
0
def test_binary_3():
	# Binary numbers divisible by 3.
	# Disallows the empty string
	# Allows "0" on its own, but not leading zeroes.
	div3 = from_fsm(fsm.fsm(
		alphabet = {"0", "1"},
		states = {"initial", "zero", 0, 1, 2, None},
		initial = "initial",
		finals = {"zero", 0},
		map = {
			"initial" : {"0" : "zero", "1" : 1   },
			"zero"    : {"0" : None  , "1" : None},
			0         : {"0" : 0     , "1" : 1   },
			1         : {"0" : 2     , "1" : 0   },
			2         : {"0" : 1     , "1" : 2   },
			None      : {"0" : None  , "1" : None},
		},
	))
	assert str(div3) == "0|1(01*0|10*1)*10*"
	gen = div3.strings()
	assert next(gen) == "0"
	assert next(gen) == "11"
	assert next(gen) == "110"
	assert next(gen) == "1001"
	assert next(gen) == "1100"
def test_star_advanced():
    # This is (a*ba)*. Naively connecting the final states to the initial state
    # gives the incorrect result here.
    starred = fsm(alphabet={"a", "b"},
                  states={0, 1, 2, "oblivion"},
                  initial=0,
                  finals={2},
                  map={
                      0: {
                          "a": 0,
                          "b": 1
                      },
                      1: {
                          "a": 2,
                          "b": "oblivion"
                      },
                      2: {
                          "a": "oblivion",
                          "b": "oblivion"
                      },
                      "oblivion": {
                          "a": "oblivion",
                          "b": "oblivion"
                      },
                  }).star()
    assert starred.alphabet == frozenset(["a", "b"])
    assert starred.accepts("")
    assert not starred.accepts("a")
    assert not starred.accepts("b")
    assert not starred.accepts("aa")
    assert starred.accepts("ba")
    assert starred.accepts("aba")
    assert starred.accepts("aaba")
    assert not starred.accepts("aabb")
    assert starred.accepts("abababa")
Example #21
0
def test_dead_default():
	'''
		You may now omit a transition, or even an entire state, from the map. This
		affects every usage of `fsm.map`.
	'''
	blockquote = fsm(
		alphabet = {"/", "*", anything_else},
		states = {0, 1, 2, 3, 4, 5},
		initial = 0,
		finals = {4},
		map = {
				0 : {"/" : 1},
				1 : {"*" : 2},
				2 : {"/" : 2, anything_else : 2, "*" : 3},
				3 : {"/" : 4, anything_else : 2, "*" : 3},
		}
	)
	assert blockquote.accepts(["/", "*", "whatever", "*", "/"])
	assert not blockquote.accepts(["*", "*", "whatever", "*", "/"])
	str(blockquote) # test stringification
	blockquote | blockquote
	blockquote & blockquote
	blockquote ^ blockquote
	reversed(blockquote)
	assert not blockquote.everythingbut().accepts(["/", "*", "whatever", "*", "/"])
	assert blockquote.everythingbut().accepts(["*"]) # deliberately seek oblivion
	assert blockquote.islive(3)
	assert blockquote.islive(4)
	assert not blockquote.islive(5)
	gen = blockquote.strings()
	assert next(gen) == ["/", "*", "*", "/"]
Example #22
0
def to_fsm(treeoid):
    s_map = {}
    count = 1
    final = {}
    alphabet = set()

    def go(treeoid, current=0):
        nonlocal count
        s_map[current] = {}
        for k, v in treeoid.items():
            alphabet.add(k)
            c = count
            count += 1
            if v == True:  #final
                if k not in final:
                    final[k] = c
                    s_map[current][k] = c
                else:
                    s_map[current][k] = final[k]
            else:  # unfinal
                s_map[current][k] = c
                go(v, c)

    go(treeoid)
    print(treeoid)

    print(len(s_map), "states")

    from greenery import fsm
    return fsm.fsm(alphabet=alphabet,
                   states=set(s_map.keys()) | set(final.values()),
                   map=s_map,
                   finals=set(final.values()),
                   initial=0)
Example #23
0
def test_anything_else_acceptance():
	a = fsm(
		alphabet = {"a", "b", "c", anything_else},
		states = {1},
		initial = 1,
		finals = {1},
		map = {
			1 : {"a" : 1, "b" : 1, "c" : 1, anything_else : 1}
		},
	)
	assert a.accepts("d")
def test_invalid_fsms():
    # initial state 1 is not a state
    try:
        fsm(alphabet={}, states={}, initial=1, finals=set(), map={})
        assert False
    except AssertionError:
        assert False
    except Exception:
        pass

    # final state 2 not a state
    try:
        fsm(alphabet={}, states={1}, initial=1, finals={2}, map={})
        assert False
    except AssertionError:
        assert False
    except Exception:
        pass

    # invalid transition for state 1, symbol "a"
    try:
        fsm(alphabet={"a"},
            states={1},
            initial=1,
            finals=set(),
            map={1: {
                "a": 2
            }})
        assert False
    except AssertionError:
        assert False
    except Exception:
        pass
Example #25
0
def test_abstar():
	# Buggggs.
	abstar = fsm.fsm(
		alphabet = {'a', fsm.anything_else, 'b'},
		states   = {0, 1},
		initial  = 0,
		finals   = {0},
		map      = {
			0: {'a': 0, fsm.anything_else: 1, 'b': 0},
			1: {'a': 1, fsm.anything_else: 1, 'b': 1}
		}
	)
	assert str(from_fsm(abstar)) == "[ab]*"
Example #26
0
def test_dead_default():
	blockquote = from_fsm(fsm.fsm(
		alphabet = {"/", "*", fsm.anything_else},
		states = {0, 1, 2, 3, 4},
		initial = 0,
		finals = {4},
		map = {
				0    : {"/" : 1},
				1    : {"*" : 2},
				2    : {"/" : 2, fsm.anything_else : 2, "*" : 3},
				3    : {"/" : 4, fsm.anything_else : 2, "*" : 3},
		}
	))
Example #27
0
def test_abstar():
	# Buggggs.
	abstar = fsm.fsm(
		alphabet = {'a', fsm.anything_else, 'b'},
		states   = {0, 1},
		initial  = 0,
		finals   = {0},
		map      = {
			0: {'a': 0, fsm.anything_else: 1, 'b': 0},
			1: {'a': 1, fsm.anything_else: 1, 'b': 1}
		}
	)
	assert str(from_fsm(abstar)) == "[ab]*"
Example #28
0
def test_dead_default():
	blockquote = from_fsm(fsm.fsm(
		alphabet = {"/", "*", fsm.anything_else},
		states = {0, 1, 2, 3, 4},
		initial = 0,
		finals = {4},
		map = {
				0    : {"/" : 1},
				1    : {"*" : 2},
				2    : {"/" : 2, fsm.anything_else : 2, "*" : 3},
				3    : {"/" : 4, fsm.anything_else : 2, "*" : 3},
		}
	))
Example #29
0
def b():
	b = fsm(
		alphabet = {"a", "b"},
		states   = {0, 1, "ob"},
		initial  = 0,
		finals   = {1},
		map      = {
			0    : {"a" : "ob", "b" : 1   },
			1    : {"a" : "ob", "b" : "ob"},
			"ob" : {"a" : "ob", "b" : "ob"},
		},
	)
	return b
Example #30
0
def test_lego_recursion_error():
	# Catch a recursion error
	assert str(from_fsm(fsm.fsm(
		alphabet = {"0", "1"},
		states   = {0, 1, 2, 3},
		initial  = 3,
		finals   = {1},
		map      = {
			0: {"0": 1, "1": 1},
			1: {"0": 2, "1": 2},
			2: {"0": 2, "1": 2},
			3: {"0": 0, "1": 2},
		}
	))) == "0[01]"
Example #31
0
def test_lego_recursion_error():
	# Catch a recursion error
	assert str(from_fsm(fsm.fsm(
		alphabet = {"0", "1"},
		states   = {0, 1, 2, 3},
		initial  = 3,
		finals   = {1},
		map      = {
			0: {"0": 1, "1": 1},
			1: {"0": 2, "1": 2},
			2: {"0": 2, "1": 2},
			3: {"0": 0, "1": 2},
		}
	))) == "0[01]"
def test_anything_else_acceptance():
    a = fsm(
        alphabet={"a", "b", "c", anything_else},
        states={1},
        initial=1,
        finals={1},
        map={1: {
            "a": 1,
            "b": 1,
            "c": 1,
            anything_else: 1
        }},
    )
    assert a.accepts("d")
Example #33
0
def test_reverse_brzozowski():
	# This is (a|b)*a(a|b)
	brzozowski = fsm(
		alphabet = {"a", "b"},
		states = {"A", "B", "C", "D", "E"},
		initial = "A",
		finals = {"C", "E"},
		map = {
			"A" : {"a" : "B", "b" : "D"},
			"B" : {"a" : "C", "b" : "E"},
			"C" : {"a" : "C", "b" : "E"},
			"D" : {"a" : "B", "b" : "D"},
			"E" : {"a" : "B", "b" : "D"},
		},
	)
	assert brzozowski.accepts("aa")
	assert brzozowski.accepts("ab")
	assert brzozowski.accepts("aab")
	assert brzozowski.accepts("bab")
	assert brzozowski.accepts("abbbbbbbab")
	assert not brzozowski.accepts("")
	assert not brzozowski.accepts("a")
	assert not brzozowski.accepts("b")
	assert not brzozowski.accepts("ba")
	assert not brzozowski.accepts("bb")
	assert not brzozowski.accepts("bbbbbbbbbbbb")

	# So this is (a|b)a(a|b)*
	b2 = reversed(brzozowski)
	assert b2.accepts("aa")
	assert b2.accepts("ba")
	assert b2.accepts("baa")
	assert b2.accepts("bab")
	assert b2.accepts("babbbbbbba")
	assert not b2.accepts("")
	assert not b2.accepts("a")
	assert not b2.accepts("b")
	assert not b2.accepts("ab")
	assert not b2.accepts("bb")
	assert not b2.accepts("bbbbbbbbbbbb")

	# Test string generator functionality.
	gen = b2.strings()
	assert next(gen) == ["a", "a"]
	assert next(gen) == ["b", "a"]
	assert next(gen) == ["a", "a", "a"]
	assert next(gen) == ["a", "a", "b"]
	assert next(gen) == ["b", "a", "a"]
	assert next(gen) == ["b", "a", "b"]
	assert next(gen) == ["a", "a", "a", "a"]
Example #34
0
def test_adotb():
	adotb = fsm.fsm(
		alphabet = {'a', fsm.anything_else, 'b'},
		states   = {0, 1, 2, 3, 4},
		initial  = 0,
		finals   = {4},
		map      = {
			0: {'a': 2, fsm.anything_else: 1, 'b': 1},
			1: {'a': 1, fsm.anything_else: 1, 'b': 1},
			2: {'a': 3, fsm.anything_else: 3, 'b': 3},
			3: {'a': 1, fsm.anything_else: 1, 'b': 4},
			4: {'a': 1, fsm.anything_else: 1, 'b': 1}
		}
	)
	assert str(from_fsm(adotb)) == "a.b"
Example #35
0
def test_adotb():
	adotb = fsm.fsm(
		alphabet = {'a', fsm.anything_else, 'b'},
		states   = {0, 1, 2, 3, 4},
		initial  = 0,
		finals   = {4},
		map      = {
			0: {'a': 2, fsm.anything_else: 1, 'b': 1},
			1: {'a': 1, fsm.anything_else: 1, 'b': 1},
			2: {'a': 3, fsm.anything_else: 3, 'b': 3},
			3: {'a': 1, fsm.anything_else: 1, 'b': 4},
			4: {'a': 1, fsm.anything_else: 1, 'b': 1}
		}
	)
	assert str(from_fsm(adotb)) == "a.b"
Example #36
0
 def __init__(self, alphabet, states, initial, finals, map):
     """
     create a new MinDFA object.
     input params - as described in greenery.fsm
     additional members:
     is_all_words: flag to indicate (when possible) if the DFA is equal to the entire domain
                  (e.g. create from_fsm dfa_all_words)
                  Relevant for performance improvements (though, if keeping the current __eq__ override, may not be
                                                         necessary)
     complement_dfa: MinDFA of the complement dfa of self, e.g: relevant when doing subtraction from 'all'.
                     for performance improvement (avoid computation of complement if could use this member instead).
     """
     self.fsm = fsm(initial, finals, alphabet, states, map)
     self.is_all_words = MinDFA.Ternary.UNKNOWN
     self.complement_dfa = None
Example #37
0
def test_reduce():
	# FSM accepts no strings but has 3 states, needs only 1
	asdf = fsm(
		alphabet = {None},
		states   = {0, 1, 2},
		initial  = 0,
		finals   = {1},
		map = {
			0 : {None : 2},
			1 : {None : 2},
			2 : {None : 2},
		},
	)
	asdf = asdf.reduce()
	assert len(asdf.states) == 1
Example #38
0
def graph2fsm(g):
    states = set(g.node.keys())

    # map alphabet to regex compatible chars
    sym = 'a'
    alph_mapper = dict()
    for state in states:
        alph_mapper[state] = sym
        sym = chr(ord(sym) + 1)

    # transitions: (FROM_STATE -> (INPUT -> TO_STATE))
    transistions = dict()
    for state in states:
        succs = g.adj.get(state)
        succs = set(succs.keys())
        transistions[state] = dict(
            map(lambda e: (alph_mapper.get(e), e), succs))

    # find start node
    start_node = ""
    for (k, v) in g.in_degree().items():
        if v == 0:
            if start_node != "":
                print("Error: More than one start states!")
            else:
                start_node = k

    # find end nodes
    end_nodes = dict((k, v) for k, v in g.out_degree().items() if v == 0)
    end_nodes = set(end_nodes.keys())

    # construct fsm from digraph data
    f = fsm.fsm(
        alphabet=alph_mapper.values(),
        states=states,
        initial=start_node,
        finals=end_nodes,
        map=transistions,
    )

    # convert fsm to regex
    r = lego.from_fsm(f)
    print("Regex: {}".format(r))
    print("Regex Mapping:\n--------------")
    for (k, v) in alph_mapper.items():
        print("{}: \t {}".format(v, k))

    return r
Example #39
0
def test_reverse_abc():
	abc = fsm(
		alphabet = {"a", "b", "c"},
		states   = {0, 1, 2, 3, None},
		initial  = 0,
		finals   = {3},
		map = {
			0    : {"a" : 1   , "b" : None, "c" : None},
			1    : {"a" : None, "b" : 2   , "c" : None},
			2    : {"a" : None, "b" : None, "c" : 3   },
			3    : {"a" : None, "b" : None, "c" : None},
			None : {"a" : None, "b" : None, "c" : None},
		},
	)
	cba = reversed(abc)
	assert cba.accepts("cba")
Example #40
0
def test_difference(a, b):
	aorb = fsm(
		alphabet = {"a", "b"},
		states = {0, 1, None},
		initial = 0,
		finals = {1},
		map = { 
			0    : {"a" : 1   , "b" : 1   },
			1    : {"a" : None, "b" : None},
			None : {"a" : None, "b" : None},
		},
	)

	assert list((a ^ a).strings()) == []
	assert list((b ^ b).strings()) == []
	assert list((a ^ b).strings()) == [["a"], ["b"]]
	assert list((aorb ^ a).strings()) == [["b"]]
Example #41
0
def dfa_to_regex():
    received_json = request.get_json(silent=True)

    constructed_automata = fsm.fsm(
        alphabet=set(received_json['alphabet']),
        states=set(received_json['states']),
        initial=received_json['initial'],
        finals=set(received_json['finals']),
        map=received_json['map'],
    )

    constructed_regex = lego.from_fsm(constructed_automata)
    constructed_regex.reduce()

    return jsonify({
        "regex": str(lego.from_fsm(constructed_automata))
    })
def test_dead_default():
    '''
		You may now omit a transition, or even an entire state, from the map. This
		affects every usage of `fsm.map`.
	'''
    blockquote = fsm(alphabet={"/", "*", anything_else},
                     states={0, 1, 2, 3, 4, 5},
                     initial=0,
                     finals={4},
                     map={
                         0: {
                             "/": 1
                         },
                         1: {
                             "*": 2
                         },
                         2: {
                             "/": 2,
                             anything_else: 2,
                             "*": 3
                         },
                         3: {
                             "/": 4,
                             anything_else: 2,
                             "*": 3
                         },
                     })
    assert blockquote.accepts(["/", "*", "whatever", "*", "/"])
    assert not blockquote.accepts(["*", "*", "whatever", "*", "/"])
    str(blockquote)  # test stringification
    blockquote | blockquote
    blockquote & blockquote
    blockquote ^ blockquote
    reversed(blockquote)
    assert not blockquote.everythingbut().accepts(
        ["/", "*", "whatever", "*", "/"])
    assert blockquote.everythingbut().accepts(["*"
                                               ])  # deliberately seek oblivion
    assert blockquote.islive(3)
    assert blockquote.islive(4)
    assert not blockquote.islive(5)
    gen = blockquote.strings()
    assert next(gen) == ["/", "*", "*", "/"]
Example #43
0
def test_binary_3():
	# Binary numbers divisible by 3.
	# Disallows the empty string
	# Allows "0" on its own, but not leading zeroes.
	div3 = fsm(
		alphabet = {"0", "1"},
		states = {"initial", "zero", 0, 1, 2, None},
		initial = "initial",
		finals = {"zero", 0},
		map = {
			"initial" : {"0" : "zero", "1" : 1   },
			"zero"    : {"0" : None  , "1" : None},
			0         : {"0" : 0     , "1" : 1   },
			1         : {"0" : 2     , "1" : 0   },
			2         : {"0" : 1     , "1" : 2   },
			None      : {"0" : None  , "1" : None},
		},
	)
	assert not div3.accepts("")
	assert div3.accepts("0")
	assert not div3.accepts("1")
	assert not div3.accepts("00")
	assert not div3.accepts("01")
	assert not div3.accepts("10")
	assert div3.accepts("11")
	assert not div3.accepts("000")
	assert not div3.accepts("001")
	assert not div3.accepts("010")
	assert not div3.accepts("011")
	assert not div3.accepts("100")
	assert not div3.accepts("101")
	assert div3.accepts("110")
	assert not div3.accepts("111")
	assert not div3.accepts("0000")
	assert not div3.accepts("0001")
	assert not div3.accepts("0010")
	assert not div3.accepts("0011")
	assert not div3.accepts("0100")
	assert not div3.accepts("0101")
	assert not div3.accepts("0110")
	assert not div3.accepts("0111")
	assert not div3.accepts("1000")
	assert div3.accepts("1001")
Example #44
0
def test_crawl_reduction():
	# this is "0*1" in heavy disguise. crawl should resolve this duplication
	# Notice how states 2 and 3 behave identically. When resolved together,
	# states 1 and 2&3 also behave identically, so they, too should be resolved
	# (this is impossible to spot before 2 and 3 have been combined).
	# Finally, the oblivion state should be omitted.
	merged = fsm(
		alphabet = {"0", "1"},
		states   = {1, 2, 3, 4, "oblivion"},
		initial  = 1,
		finals   = {4},
		map      = {
			1          : {"0" : 2         , "1" : 4         },
			2          : {"0" : 3         , "1" : 4         },
			3          : {"0" : 3         , "1" : 4         },
			4          : {"0" : "oblivion", "1" : "oblivion"},
			"oblivion" : {"0" : "oblivion", "1" : "oblivion"},
		}
	).reduce()
	assert len(merged.states) == 2
Example #45
0
    def test_basic(self):
        dfa1 = get_str_dfa("put|get")
        dfa2 = get_str_dfa("get|put")
        self.assertEqual(dfa1, dfa2)
        dfa3 = get_str_dfa("put")
        dfa4 = get_str_dfa("get")
        self.assertEqual(dfa1, dfa3 | dfa4)
        self.assertEqual(dfa1, dfa4 | dfa3)
        dfa5 = dfa4 & dfa1
        self.assertEqual(dfa5, dfa4)
        print(dfa4.get_fsm_str())
        print(repr(dfa4))
        # equiv dfa created directly, with a different set of state numbers
        equiv_dfa = fsm(alphabet={"e", "g", "t", anything_else},
                        states={0, 1, 2, 5},
                        initial=0,
                        finals={5},
                        map={
                            0: {
                                'g': 1
                            },
                            1: {
                                'e': 2
                            },
                            2: {
                                't': 5
                            },
                            5: {}
                        })
        dfa6 = MinDFA.dfa_from_fsm(equiv_dfa)
        res1 = dfa6 == dfa4
        print(res1)
        self.assertFalse(res1)

        dfa6 = dfa6.get_fsm()
        dfa4 = dfa4.get_fsm()
        res2 = dfa6.equivalent(dfa4)
        print(res2)
        self.assertTrue(res2)
        dfa6.reduce()
        print(repr(dfa6))
def test_reduce():
    # FSM accepts no strings but has 3 states, needs only 1
    asdf = fsm(
        alphabet={None},
        states={0, 1, 2},
        initial=0,
        finals={1},
        map={
            0: {
                None: 2
            },
            1: {
                None: 2
            },
            2: {
                None: 2
            },
        },
    )
    asdf = asdf.reduce()
    assert len(asdf.states) == 1
def test_bug_28():
	# This is (ab*)* and it caused some defects.
	abstar = fsm(
		alphabet = {'a', 'b'},
		states   = {0, 1},
		initial  = 0,
		finals   = {1},
		map = {
			0: {'a': 1},
			1: {'b': 1}
		}
	)
	assert abstar.accepts("a")
	assert not abstar.accepts("b")
	assert abstar.accepts("ab")
	assert abstar.accepts("abb")
	abstarstar = abstar.star()
	assert abstarstar.accepts("a")
	assert not abstarstar.accepts("b")
	assert abstarstar.accepts("ab")
	assert not abstar.star().accepts("bb")
Example #48
0
def test_bad_alphabet():
	# You can use anything you like in your FSM alphabet, but if you try to
	# convert it to a `lego` object then the only acceptable symbols are single
	# characters or `fsm.anything_else`.
	for bad_symbol in [None, (), 0, ("a",), "", "aa", "ab", True]:
		f = fsm.fsm(
			alphabet = {bad_symbol},
			states = {0},
			initial = 0,
			finals = set(),
			map = {
				0 : {bad_symbol : 0}
			},
		)
		try:
			from_fsm(f)
			assert False
		except AssertionError as e:
			raise Exception("Accepted bad symbol: " + repr(bad_symbol))
		except Exception as e:
			pass
Example #49
0
def test_bad_alphabet():
	# You can use anything you like in your FSM alphabet, but if you try to
	# convert it to a `lego` object then the only acceptable symbols are single
	# characters or `fsm.anything_else`.
	for bad_symbol in [None, (), 0, ("a",), "", "aa", "ab", True]:
		f = fsm.fsm(
			alphabet = {bad_symbol},
			states = {0},
			initial = 0,
			finals = set(),
			map = {
				0 : {bad_symbol : 0}
			},
		)
		try:
			from_fsm(f)
			assert False
		except AssertionError as e:
			raise Exception("Accepted bad symbol: " + repr(bad_symbol))
		except Exception as e:
			pass
Example #50
0
def test_invalid_fsms():
	# initial state 1 is not a state
	try:
		fsm(
			alphabet = {},
			states = {},
			initial = 1,
			finals = set(),
			map = {}
		)
		assert False
	except AssertionError:
		assert False
	except Exception:
		pass

	# final state 2 not a state
	try:
		fsm(
			alphabet = {},
			states = {1},
			initial = 1,
			finals = {2},
			map = {}
		)
		assert False
	except AssertionError:
		assert False
	except Exception:
		pass

	# invalid transition for state 1, symbol "a"
	try:
		fsm(
			alphabet = {"a"},
			states = {1},
			initial = 1,
			finals = set(),
			map = {
				1 : {"a" : 2}
			}
		)
		assert False
	except AssertionError:
		assert False
	except Exception:
		pass
Example #51
0
def test_oblivion_crawl(a):
	# When crawling a new FSM, we should avoid generating an oblivion state.
	# `abc` has no oblivion state... all the results should not as well!
	abc = fsm(
		alphabet = {"a", "b", "c"},
		states = {0, 1, 2, 3},
		initial = 0,
		finals = {3},
		map = {
			0 : {"a" : 1},
			1 : {"b" : 2},
			2 : {"c" : 3},
		}
	)
	assert len((abc + abc).states) == 7
	assert len(abc.star().states) == 3
	assert len((abc * 3).states) == 10
	assert len(reversed(abc).states) == 4
	assert len((abc | abc).states) == 4
	assert len((abc & abc).states) == 4
	assert len((abc ^ abc).states) == 1
	assert len((abc - abc).states) == 1
def a():
    a = fsm(
        alphabet={"a", "b"},
        states={0, 1, "ob"},
        initial=0,
        finals={1},
        map={
            0: {
                "a": 1,
                "b": "ob"
            },
            1: {
                "a": "ob",
                "b": "ob"
            },
            "ob": {
                "a": "ob",
                "b": "ob"
            },
        },
    )
    return a
Example #53
0
    def __init__(self, config, n_global_in, n_global_out):

        n_layers_start = 5
        num_min = 3
        self.configuration = config

        self.global_attributes = GlobalAttributes(self.configuration)

        self.net_struct = []

        state_machine = fsm(alphabet=set(config.fsm['alphabet']),
                            states=set(config.fsm['states']),
                            initial="inicial",
                            finals={"Dense"},
                            map=config.fsm['map'])

        candidates = list(
            itertools.takewhile(
                lambda c: len(c) <= n_layers_start,
                itertools.dropwhile(lambda l: len(l) < num_min,
                                    state_machine.strings())))

        first_layers = list(set([b[0] for b in candidates]))
        candidates = [
            random.choice([z for z in candidates if z[0] == first_layers[l]])
            for l in range(len(first_layers))
        ]

        sizes = list(set(map(len, candidates)))
        random_size = random.choice(sizes)
        candidates = filter(lambda c: len(c) == random_size, candidates)

        candidate = random.choice(candidates)
        candidate = map(lambda lt: Layer([lt], config), candidate)
        self.net_struct = candidate
        self.net_struct[0].parameters['input_shape'] = (n_global_in, )
        self.net_struct[-1].parameters['output_dim'] = n_global_out
        self.global_attributes.number_layers = len(self.net_struct)
def test_bug_28():
    # This is (ab*)* and it caused some defects.
    abstar = fsm(alphabet={'a', 'b'},
                 states={0, 1},
                 initial=0,
                 finals={1},
                 map={
                     0: {
                         'a': 1
                     },
                     1: {
                         'b': 1
                     }
                 })
    assert abstar.accepts("a")
    assert not abstar.accepts("b")
    assert abstar.accepts("ab")
    assert abstar.accepts("abb")
    abstarstar = abstar.star()
    assert abstarstar.accepts("a")
    assert not abstarstar.accepts("b")
    assert abstarstar.accepts("ab")
    assert not abstar.star().accepts("bb")
def test_reverse_abc():
    abc = fsm(
        alphabet={"a", "b", "c"},
        states={0, 1, 2, 3, None},
        initial=0,
        finals={3},
        map={
            0: {
                "a": 1,
                "b": None,
                "c": None
            },
            1: {
                "a": None,
                "b": 2,
                "c": None
            },
            2: {
                "a": None,
                "b": None,
                "c": 3
            },
            3: {
                "a": None,
                "b": None,
                "c": None
            },
            None: {
                "a": None,
                "b": None,
                "c": None
            },
        },
    )
    cba = reversed(abc)
    assert cba.accepts("cba")