Advertisement
Guest User

Untitled

a guest
Jan 11th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. CREATE OR REPLACE FUNCTION
  2.   markov_learn(a_chain BIGINT, a_source TEXT) RETURNS VOID
  3. AS $$
  4. DECLARE
  5.   t_depth INTEGER;
  6.   t_index INTEGER;
  7.   t_words TEXT[];
  8. BEGIN
  9.   t_depth := a_chain & 7;
  10.   t_words := array_remove(regexp_split_to_array(a_source, E'\\s+'), '');
  11.   IF coalesce(array_length(t_words, 1), 0) < t_depth THEN
  12.     RETURN;
  13.   END IF;
  14.   INSERT INTO markov_start VALUES (a_chain, t_words[1 : t_depth])
  15.   ON CONFLICT DO NOTHING;
  16.   FOR t_index IN
  17.     1 .. (array_length(t_words, 1) - t_depth + 1)
  18.   LOOP
  19.     INSERT INTO markov_cont VALUES (a_chain,
  20.       t_words[t_index + 0 : t_index + t_depth - 1], coalesce(t_words[t_index + t_depth], ''), 1)
  21.     ON CONFLICT (chain, prev, curr) DO UPDATE SET count = markov_cont.count + 1;
  22.   END LOOP;
  23. END;
  24. $$ LANGUAGE plpgsql;
  25.  
  26. CREATE OR REPLACE FUNCTION
  27.   markov_getword(a_chain BIGINT, a_prev TEXT[]) RETURNS TEXT
  28. AS $$
  29. DECLARE
  30.   t_depth INTEGER;
  31.   t_final INTEGER;
  32.   t_accum INTEGER := 0;
  33.   t_row markov_cont%ROWTYPE;
  34. BEGIN
  35.   t_depth := a_chain & 7;
  36.   IF t_depth <> array_length(a_prev, 1) THEN
  37.     RETURN NULL;
  38.   END IF;
  39.   SELECT round(sum(count) * random()) INTO t_final FROM markov_cont WHERE chain = a_chain AND prev = a_prev;
  40.   FOR t_row IN
  41.     SELECT * FROM markov_cont WHERE chain = a_chain AND prev = a_prev
  42.   LOOP
  43.     t_accum := t_accum + t_row.count;
  44.     if t_final <= t_accum THEN
  45.       RETURN nullif(t_row.curr, '');
  46.     END IF;
  47.   END LOOP;
  48.   RETURN NULL;
  49. END;
  50. $$ LANGUAGE plpgsql;
  51.  
  52. CREATE OR REPLACE FUNCTION
  53.   markov_getstart(a_chain BIGINT, a_words TEXT[]) RETURNS TEXT[]
  54. AS $$
  55. DECLARE
  56.   t_length INTEGER;
  57.   t_loops INTEGER := 2;
  58.   t_row1 markov_start%ROWTYPE;
  59.   t_row2 markov_cont%ROWTYPE;
  60. BEGIN
  61.   a_words := array_remove(a_words, '');
  62.   t_length := coalesce(array_length(a_words, 1), 0);
  63.   IF t_length < (a_chain & 7) THEN
  64.     FOR t_loops IN 1 .. t_loops
  65.     LOOP
  66.       FOR t_row1 IN
  67.         SELECT * FROM markov_start WHERE chain = a_chain AND prev[1 : t_length] = a_words
  68.       LOOP
  69.         EXIT WHEN random() < 0.02;
  70.       END LOOP;
  71.     END LOOP;
  72.     IF t_row1 IS NOT NULL THEN
  73.       RETURN t_row1.prev;
  74.     END IF;
  75.     FOR t_loops IN 1 .. t_loops
  76.     LOOP
  77.       FOR t_row2 IN
  78.         SELECT * FROM markov_cont WHERE chain = a_chain
  79.         AND prev[1 : t_length] = a_words
  80.       LOOP
  81.         EXIT WHEN random() < 0.02;
  82.       END LOOP;
  83.     END LOOP;
  84.     IF t_row2 IS NOT NULL THEN
  85.       RETURN t_row2.prev;
  86.     END IF;
  87.   END IF;
  88.   RETURN a_words;
  89. END;
  90. $$ LANGUAGE plpgsql;
  91.  
  92. CREATE OR REPLACE FUNCTION
  93.   markov_generate(a_chain BIGINT, a_start TEXT) RETURNS TEXT
  94. AS $$
  95. DECLARE
  96.   t_depth INTEGER;
  97.   t_offset INTEGER;
  98.   t_word TEXT;
  99.   t_words TEXT[];
  100. BEGIN
  101.   t_depth := a_chain & 7;
  102.   t_words := markov_getstart(a_chain, regexp_split_to_array(a_start, E'\\s+'));
  103.   t_offset := array_length(t_words, 1) - t_depth + 1;
  104.   LOOP
  105.     t_word := markov_getword(a_chain, t_words[t_offset + 0 : t_offset + t_depth - 1]);
  106.     EXIT WHEN t_word IS NULL;
  107.     t_words := array_append(t_words, t_word);
  108.     t_offset := t_offset + 1;
  109.   END LOOP;
  110.   RETURN array_to_string(t_words, ' ');
  111. END;
  112. $$ LANGUAGE plpgsql;
  113.  
  114. CREATE OR REPLACE FUNCTION
  115.   markov_from_messages(a_chain BIGINT, a_depth INTEGER) RETURNS BIGINT
  116. AS $$
  117. DECLARE
  118.   t_chain BIGINT;
  119.   t_row messages%ROWTYPE;
  120. BEGIN
  121.   t_chain = (a_chain & ~255) | (a_depth & 7);
  122.   FOR t_row IN
  123.     SELECT * FROM messages
  124.   LOOP
  125.     PERFORM markov_learn(t_chain, t_row.content);
  126.   END LOOP;
  127.   RETURN t_chain;
  128. END;
  129. $$ LANGUAGE plpgsql;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement