- •Курсовой проект
- •Оглавление
- •Введение
- •Концептуальное модельное представление задачи как системы
- •Программная реализация представления концептуальной модели задачи Решение задач посредством прямого расчёта
- •Решение судоку Разрешение концептуальных моделей
- •Метод полного перебора
- •Логические методы решения
- •Составление судоку
- •Составление открытием
- •Решение вычёркиванием
- •Переносимость и интегрируемость
- •Литература
- •Приложение. Программный код Решатель математических моделей
- •Решатель судоку методом полного перебора
- •Решатель судоку аналитическими методами
- •Генератор судоку методом открытий
Составление судоку
Составление судоку может осуществляться двумя методами – либо сокрытием случайной ячейки после составления правильного латинского квадрата, либо наоборот открытием случайных ячеек. В первом случае после каждого шага выполняется решение и проверяется количество итераций и их сложность (применение методов первичных, slicing and dicing, предположений).
Составление открытием
Но несмотря на то, что цифры из доски выполняется в порядке, обратном заполнению, всё равно возможно получение недетерменированного судоку и данную проблему разрешить невозможно.
Решение вычёркиванием
Решение вычёркиванием состоит в получении правильного латинского квадрата. Затем в полученном латинском квадрате рекурсивно осуществляются перестановки строк, столбцов и малых квадратов в соответствие с требованиями. Затем происходит вычёркивание случайного элемента и решение полученного судоку на основе методов решения. Сложность алгоритма определяется количеством итераций, которые необходимы для решения.
Переносимость и интегрируемость
Так как программа написана на Python, программа является переносимой на любую платформу (Windows, Linux, MacOS).
В целях интегрируемости программа принимает параметры в командной строке. Перечень параметров:
-t, --type – [math | sudoku] – тип шаблона, математические формулы по предметной области или судоку
-a, --task – [solve | generate] – задание, решить или создать, для шаблона math по умолчанию - решить
-m, --method – [[None] | [brute | analytic] | [opening | cut]] – метод, не применим для шаблона math, принимает значения brute или analytic при задании solve или opening или cut при задании generate
-q, --template – шаблон для математических формул
-i, --input – входной файл
-o, --output – выходной файл
Литература
-
Нечаев В.В. Концептуальное модельное представление задачи как системы. Информационные технологии, № --. 2009. ----- с.
-
http://www.angusj.com/sudoku/hints.php
Приложение. Программный код Решатель математических моделей
# -*- coding: cp1251 -*-
import math
import codecs
import re
import sys
import string
import graphWindow
import copy
class solver():
def __init__(self, data, rules, goals, **kwargs):
self._recursionLevel = 0
self.data = (data.lower()).split("\n")
self.rules = (rules.lower()).split("\n")
self.goals = (goals.lower()).split("\n")
self.rawgoals = self.goals
self.templateVars = kwargs.get('templateVars', {})
self.templateFull = kwargs.get('templateFull', {})
self.sErrTxt = ''
self.sSolveTxt = ''
self.env = kwargs.get('env', {})
self.__globals = {}
self.__locals = {}
self.fString = []
self.parent = kwargs.get('parent', None)
self.analyzeData()
self.analyzeRules()
self.analyzeGoals()
self.makeSolveFor()
#for g in self.goals:
#self.makeSolveFor(g)
def analyzeData(self):
self.definiedVariables = []
for q in self.data:
r = q.split('=')
self.definiedVariables.append(r[0].strip())
self.definiedVariablesFirst = copy.copy(self.definiedVariables)
def analyzeRules(self):
print self.rules
self.ruledVariablesLeft = []
self.ruledVariablesRight = []
l = 0
for q in self.rules:
r = q.split('=')
self.ruledVariablesLeft.append(r[0])
try:
r[1]
except IndexError:
self.solveErr = 31
self.solveErrExtend = { 'vString' : r}
self.solveErrorsText()
return
splRules = re.split('([A-Za-z]+)([0-9]*)', r[1])
self.ruledVariablesRight.append([])
print splRules
for sId in range(len(splRules)-1):
sRule = splRules[sId]
nsRule = splRules[sId+1]
if re.match('^[A-Za-z]+$', sRule) and ('' == nsRule or re.match('^[0-9]+$', nsRule)):
print sRule+nsRule
self.ruledVariablesRight[l].append(str(sRule+nsRule))
l = l + 1
def analyzeGoals(self):
goals = self.goals
self.goals = []
for i in goals:
goalParts = re.split('(^[A-Za-z]+)([0-9]+)$', i)
self.goals.append({ 'goalLine' : i,
'goalParts' : goalParts if goalParts[0] != '' else goalParts[1:3]
})
def makeSolveFor(self):
print 'Solving'
print self.ruledVariablesLeft
print self.ruledVariablesRight
print self.goals
self.solveErr = 0
self.solveErrExtend = {}
self.solution = 0
self.solutionString = 'крабе'
exec('import math', self.__globals, self.__locals)
for cGoal in self.goals:
if cGoal['goalParts'][0] not in self.templateVars['vars'].lower().split(','):
self.solveErr = 24
self.solveErrExtend = { 'vName' : cGoal['goalParts'][0], 'dVars' : self.templateVars['vars']}
for cGoal in self.goals:
print 'definded: '+ ''.join(self.definiedVariables)
print 'goal:'+cGoal['goalLine']
if cGoal['goalLine'] in self.definiedVariables:
print 'Found'
self.solveErr = 14
self.solveErrExtend = cGoal['goalLine']
self.solveErrorsText()
return
if self._recursionLevel == 0:
for iData in self.data:
if iData.strip() == '':
break
try:
exec(iData+';', self.__globals, self.__locals)
self.log("Ввод (exec) начальной информации: %s"%(iData))
except NameError as err:
print 'NameError %s' %(err)
self.solveErr = 1
self.solveErrExtend = { 'vName' : err }
return
except:
print 'Unknown exception %s'%sys.exc_info()[0]
self.solveErr = 3
self.solveErrExtend = {}
for m in range(len(self.goals)):
self.log('Step %d:\n'%m)
for iRule in self.rules:
if iRule.strip() == '':
break
try:
self.log('Применяем правило %s' %iRule)
exec(iRule+';', self.__globals, self.__locals)
except NameError as err:
print 'NameError %s' %(err)
self.solveErr = 15
self.solveErrExtend = { 'vName' : err }
self.solveErrorsText()
return
except:
print 'Unknown exception'
self.solveErr = 18
self.solveErrExtend = {}
self.solveErrorsText()
return
l = self.preFind()
#l = [0]
if (l[0] not in (0, 2, 5, 13)):
if 12 == l[0]:
self.solveErrorsText()
if self._recursionLevel < 2:
self._recursionLevel = self._recursionLevel + 1
self.makeSolveFor()
pass
else:
self.solveErrorsText()
return
elif 2 == l[0]:
self.solveErrorsText()
elif 5 == l[0]:
try:
self.solveErrorsText()
exec(l[1]['ruleString'], self.__globals, self.__locals)
self.log(l[1]['varName'])
self.log("%s = %2.8lf" %(l[1]['varName'], eval(l[1]['varName'], self.__globals, self.__locals)))
return
except NameError as s:
print 'NameError in right solving %s' %s
self.solveErr = 21
self.solveErrExtend = l[1]
self.solveErrorsText()
return
for (key, val) in self.templateFull.iteritems():
if (key == self.goals[m]['goalParts'][0]):
print 'Found %s'%key
try:
if -1 != self.goals[m]['goalParts'][1]:
# заменяем шаблон
lf = val.lower()
for ctr in self.templateVars['vars'].lower().split(','):
lf = string.replace(lf, ctr, ctr+str(self.goals[m]['goalParts'][1]))
except IndexError as s:
print 'IndexError %s'%s
lf = val.lower()
pass
self.log('Применение шаблона %s = %s для переменной %s (%s = %s)' % (key, val, self.goals[m]['goalLine'], self.goals[m]['goalLine'], lf))
try:
exec("%s=%s"%(self.goals[m]['goalLine'], lf), self.__globals, self.__locals)
self.fString.append((self.goals[m]['goalLine'], lf))
self.log(self.goals[m]['goalLine'])
r = eval(self.goals[m]['goalLine'], self.__globals, self.__locals)
self.log("%s = %2.8lf" %(self.goals[m]['goalLine'], r))
self.data.append(r)
self.definiedVariables.append(self.goals[m]['goalLine'])
self.checkEnv(self.goals[m]['goalLine'], r)
continue
except NameError as err:
self.solveErr = 36
self.solveErrExtend = { 'line' : "%s=%s"%(self.goals[m]['goalLine'], lf), 'err' : err}
return
except:
self.solveErr = 37
self.solveErrExtend = { 'line' : "%s=%s"%(self.goals[m]['goalLine'], lf), 'err' : sys.exc_info()[0]}
return
# if (key == self.goals[m]['goalLine']):
def preFind(self):
print 'Analyzing'
print self.goals, self._recursionLevel
for sGoal in self.goals:
goalLine = sGoal['goalLine']
for sRule in self.ruledVariablesRight:
if goalLine in sRule:
self.solveErr = 2
self.solveErrExtend = {'vName' : goalLine}
return (2, {})
if goalLine in self.ruledVariablesLeft:
self.solveErr = 5
rS = self.retRuleStringByVal(goalLine)
self.solveErrExtend = { 'vName' : goalLine, 'ruleString' : rS }
return (5, {'ruleString' : rS, 'varName' : goalLine})
err = 0
for sRule in self.ruledVariablesRight:
for l in sRule:
if l in self.definiedVariables:
err = 1
if l in self.ruledVariablesLeft:
err = 2
if 1 == err:
return (0, {})
elif 2 == err:
self.solveErr = 13
return (0, {})
else:
q = self.analyzeGoalsNeeded()
print q
if q == '':
return (0, {})
else:
self.solveErr = 12
line = self.analyzeGoalsNeeded()
self.solveErrExtend = { 'vName' : line }
#self.goals = ('%s' %(line)).split('\'')[1]+"\n".join(self.rawgoals)
self.goals = []
self.goals.append(('%s' %(line)).split('\'')[1])
for i in self.rawgoals:
self.goals.append(i)
self.log('Поиск \'%s\''%('%s' %(line)).split('\'')[1])
print 'Поиск \'%s\''%('%s' %(line)).split('\'')[1]
self.analyzeGoals()
return (12, {})
def analyzeGoalsNeeded(self):
for goalLine in self.goals:
gL = goalLine['goalLine']
gP = goalLine['goalParts']
for (key, val) in self.templateFull.iteritems():
if key == gP[0]:
try:
if -1 != gP[1]:
# заменяем шаблон
lf = val.lower()
for ctr in self.templateVars['vars'].lower().split(','):
lf = string.replace(lf, ctr, ctr+str(self.goals[m]['goalParts'][1]))
except IndexError as s:
print 'IndexError %s'%s
lf = val.lower()
pass
try:
print lf
exec(lf, self.__globals, self.__locals)
except NameError as err:
return err
return ''
def simpleCheckEnv(self, varName, envVar, envParts, envElem):
try:
envParts[1]
except:
return
if envVar == varName:
l = eval(envElem, self.__globals, self.__locals)
if l:
print 'TRUE'
else:
self.log('Переменная %s не удовлетворяет параметрам внешней среды (%s)'%(varName, envElem))
print 'FALSE'
def checkEnv(self, varName, res):
print 'Checking %s by %lf'%(varName, res)
print self.env
for (envKey, envElem) in self.env.iteritems():
envParts = envElem.split('>=')
envVar = envParts[0].lower().strip()
self.simpleCheckEnv(varName, envVar, envParts, envElem)
envParts = envElem.split('<=')
envVar = envParts[0].lower().strip()
self.simpleCheckEnv(varName, envVar, envParts, envElem)
envParts = envElem.split('>')
envVar = envParts[0].lower().strip()
self.simpleCheckEnv(varName, envVar, envParts, envElem)
envParts = envElem.split('<')
envVar = envParts[0].lower().strip()
self.simpleCheckEnv(varName, envVar, envParts, envElem)
def retRuleStringByVal(self, val):
for i in self.rules:
if val == i.split('=')[0].strip():
return i
def retSolving(self, **kwargs):
ret = { 'err' : self.solveErr,
'errTxt' : self.sSolveTxt,
'sol' : self.solution,
'solStr' : self.sSolveTxt
}
return ret
def solveErrorsText(self):
self.log({
0 : lambda q: 'ОК',
1 : lambda q: "Переменная %s используется, но не задана" %(q['vName']),
2 : lambda q: "Переменная %s задана для поиска и в то же время используется в правиле. Возможна рекурсия"%(q),
3 : lambda q: 'Неизвестная ошибка при задании начальных условий',
5 : lambda q: "Переменная %s прямо вычисляется по правилу %s"%(q['vName'], q['ruleString']),
6 : lambda q: "Не задана переменная %s" %(q['vName']),
12 : lambda q: 'Какая-то из переменных правой части правил не может быть найдена в условиях и/или других правилах, ожидается %s'%(q['vName']),
13 : lambda q: 'Переменная правой части условий найдена в задании левой. Может вызвать ошибку',
14 : lambda q: 'Избыточные данные: переменная %s задана и требуется найти'%(q),
15 : lambda q: "Попытка использовать незаданную переменную %s в правилах" %(q['vName']),
18 : lambda q: 'Неизвестная ошибка при задании правил',
21 : lambda q: 'Ошибка прямого подсчёта, строка %s, переменная %s: '%(q['ruleString'], q['varName']),
24 : lambda q:
"Переменная %s не найдена среди возможных (%s)" %(q['vName'], q['dVars']),
31 : lambda q: 'Не заданы правило: строка должна быть формата A=(B) (дано: %s'%(''.join(q['vString'])),
36 : lambda q: 'Ошибка обработки строки %s: %s'%(q['line'], q['str'])
}[self.solveErr](self.solveErrExtend), True)
def log(self, txt, error=False, onlyError=False):
if error:
self.sErrTxt = self.sErrTxt + "\n" + txt
if not onlyError:
self.sSolveTxt = self.sSolveTxt + "\n" + txt
def graph(self, event):
print self.definiedVariables
print self.definiedVariablesFirst
graphWindow.graphWindow(self.parent, globals=self.__globals, locals=self.__locals,
defined=self.definiedVariablesFirst,
data=self.data,
fString=self.fString)