Files
ortools-clone/examples/notebook/contrib/regular_table2.ipynb
Corentin Le Molgat 27121a1068 Update examples/notebook
generated using ./tools/gen_all_notebook.sh
2020-03-04 14:34:33 +01:00

213 lines
7.0 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# http://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License.\n",
"\"\"\"\n",
"\n",
" Global constraint regular in Google CP Solver.\n",
"\n",
" This is a translation of MiniZinc's regular constraint (defined in\n",
" lib/zinc/globals.mzn). All comments are from the MiniZinc code.\n",
" '''\n",
" The sequence of values in array 'x' (which must all be in the range 1..S)\n",
" is accepted by the DFA of 'Q' states with input 1..S and transition\n",
" function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
" (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
" 1..Q). We reserve state 0 to be an always failing state.\n",
" '''\n",
"\n",
" It is, however, translated from the Comet model:\n",
" * Comet: http://www.hakank.org/comet/regular.co\n",
"\n",
" Here we test with the following regular expression:\n",
" 0*1{3}0+1{2}0+1{1}0*\n",
" using an array of size 10.\n",
"\n",
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
" Also see my other Google CP Solver models:\n",
" http://www.hakank.org/google_or_tools/\n",
"\n",
"\"\"\"\n",
"from __future__ import print_function\n",
"from ortools.constraint_solver import pywrapcp\n",
"\n",
"\n",
"#\n",
"# Global constraint regular\n",
"#\n",
"# This is a translation of MiniZinc's regular constraint (defined in\n",
"# lib/zinc/globals.mzn), via the Comet code refered above.\n",
"# All comments are from the MiniZinc code.\n",
"# '''\n",
"# The sequence of values in array 'x' (which must all be in the range 1..S)\n",
"# is accepted by the DFA of 'Q' states with input 1..S and transition\n",
"# function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
"# (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
"# 1..Q). We reserve state 0 to be an always failing state.\n",
"# '''\n",
"#\n",
"# x : IntVar array\n",
"# Q : number of states\n",
"# S : input_max\n",
"# d : transition matrix\n",
"# q0: initial state\n",
"# F : accepting states\n",
"def regular(x, Q, S, d, q0, F):\n",
"\n",
" solver = x[0].solver()\n",
"\n",
" assert Q > 0, 'regular: \"Q\" must be greater than zero'\n",
" assert S > 0, 'regular: \"S\" must be greater than zero'\n",
"\n",
" # d2 is the same as d, except we add one extra transition for\n",
" # each possible input; each extra transition is from state zero\n",
" # to state zero. This allows us to continue even if we hit a\n",
" # non-accepted input.\n",
"\n",
" d2 = []\n",
" for i in range(Q + 1):\n",
" for j in range(1, S + 1):\n",
" if i == 0:\n",
" d2.append((0, j, 0))\n",
" else:\n",
" d2.append((i, j, d[i - 1][j - 1]))\n",
"\n",
" solver.Add(solver.TransitionConstraint(x, d2, q0, F))\n",
"\n",
"\n",
"#\n",
"# Make a transition (automaton) matrix from a\n",
"# single pattern, e.g. [3,2,1]\n",
"#\n",
"\n",
"\n",
"def make_transition_matrix(pattern):\n",
"\n",
" p_len = len(pattern)\n",
" print('p_len:', p_len)\n",
" num_states = p_len + sum(pattern)\n",
" print('num_states:', num_states)\n",
" t_matrix = []\n",
" for i in range(num_states):\n",
" row = []\n",
" for j in range(2):\n",
" row.append(0)\n",
" t_matrix.append(row)\n",
"\n",
" # convert pattern to a 0/1 pattern for easy handling of\n",
" # the states\n",
" tmp = [0 for i in range(num_states)]\n",
" c = 0\n",
" tmp[c] = 0\n",
" for i in range(p_len):\n",
" for j in range(pattern[i]):\n",
" c += 1\n",
" tmp[c] = 1\n",
" if c < num_states - 1:\n",
" c += 1\n",
" tmp[c] = 0\n",
" print('tmp:', tmp)\n",
"\n",
" t_matrix[num_states - 1][0] = num_states\n",
" t_matrix[num_states - 1][1] = 0\n",
"\n",
" for i in range(num_states):\n",
" if tmp[i] == 0:\n",
" t_matrix[i][0] = i + 1\n",
" t_matrix[i][1] = i + 2\n",
" else:\n",
" if i < num_states - 1:\n",
" if tmp[i + 1] == 1:\n",
" t_matrix[i][0] = 0\n",
" t_matrix[i][1] = i + 2\n",
" else:\n",
" t_matrix[i][0] = i + 2\n",
" t_matrix[i][1] = 0\n",
"\n",
" print('The states:')\n",
" for i in range(num_states):\n",
" for j in range(2):\n",
" print(t_matrix[i][j], end=' ')\n",
" print()\n",
" print()\n",
"\n",
" return t_matrix\n",
"\n",
"\n",
"\n",
"# Create the solver.\n",
"solver = pywrapcp.Solver('Regular test')\n",
"\n",
"#\n",
"# data\n",
"#\n",
"\n",
"this_len = 10\n",
"pp = [3, 2, 1]\n",
"\n",
"transition_fn = make_transition_matrix(pp)\n",
"n_states = len(transition_fn)\n",
"input_max = 2\n",
"\n",
"# Note: we use '1' and '2' (rather than 0 and 1)\n",
"# since 0 represents the failing state.\n",
"initial_state = 1\n",
"\n",
"accepting_states = [n_states]\n",
"\n",
"# declare variables\n",
"reg_input = [\n",
" solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n",
"]\n",
"\n",
"#\n",
"# constraints\n",
"#\n",
"regular(reg_input, n_states, input_max, transition_fn, initial_state,\n",
" accepting_states)\n",
"\n",
"#\n",
"# solution and search\n",
"#\n",
"db = solver.Phase(reg_input, solver.CHOOSE_MIN_SIZE_HIGHEST_MAX,\n",
" solver.ASSIGN_MIN_VALUE)\n",
"\n",
"solver.NewSearch(db)\n",
"\n",
"num_solutions = 0\n",
"while solver.NextSolution():\n",
" print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n",
" num_solutions += 1\n",
"\n",
"solver.EndSearch()\n",
"print()\n",
"print('num_solutions:', num_solutions)\n",
"print('failures:', solver.Failures())\n",
"print('branches:', solver.Branches())\n",
"print('WallTime:', solver.WallTime(), 'ms')\n",
"\n"
]
}
],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 4
}