Программа итерационного поиска

в 12:38, , рубрики: math, python, Python 2.7, метки: ,

Введение

Как-то возникла необходимость быстро восстановить ход решения одной задачи. Т.е. у меня был набор входных данных и полученные результаты. Хотелось быстро найти алгоритмы, по которому были получены все ответы. Я попытался написать программу-подсказчик.

Что было сделано

Начал я с малого — создал на python 2.7 программу, находящую по заданному частному делимое и делитель. Простым перебором. Затем добавил умножение, вычитание и деление, что пригодилось на поздних этапах. На данном этапе программа уже умела определить, что число 0.428571428571 получено путем 3/7.
Добавил (скорее для тестов) возможность вводить как число, так и функцию.
Позже добавил стандартные иррациональности. Программа находила, что 0.785398163397 было получено из pi/4.

Вот версия 4.6:

# -*- coding: cp1251 -*-
#Concatenate 3.2.py+2.3.py
#==========================
#Программа для нахождения записи введенного вами числа
#как отношения двух целых чисел либо
#как функции целого числа.
#
#поддерживаемые функции:
#'sqrt(y)','exp(y)','log(y)','log10(y)','y**(1/3)','y**2','y**3','2**y','log2(y)'

from math import *
print ('For example: c=? (0.3752*sqrt(3.0)+exp(2.0))/cos(pi/4.0)-2.0**(-2.0)')
#print ('Use 0<c<9802' for 'a=range(1,101)')
c = float(input ('c=? '))
print 'c =',c
#Проверка отрицательности:
c1=0
if c<0: #Будем работать с положительными числами. Учтем это в логарифмах.
    c=-c
    c1=-1
#==========================
z=0 #индикатор
integer=[float(i) for i in range(1,101)]
i=0
while i<len(integer):
    if c==integer[i]:
        z=1 #индикатор
        print 'integer'
    i+=1
#==========================

#Add 2.3.py
"""
##all variables:
##a, b, c, d, e, j, i, f, g, h, k, l, m, n, e1, l1
##aa, bb, cc, dd, ee, jj, ii, ff, gg, hh, kk, ll, mm, nn, ee1, ll1
##p,q, 
##r
"""
#import math
#from math import *
#
#Division
#used variables: a, b, c, d, e, j, i, e1. (7 items) (j and i are iteration's variables)
#c = float(raw_input('c=? '))
#print ('For example: c=? (0.3752*sqrt(3)+exp(2))/cos(pi/4)-2**(-2)')
#print ('Use 0<c<9802' for 'a=range(1,100)')
#c = input ('c=? ')
a=range(1,101) #1.you may change here. 'a=change(1,l1)' or 'a=change(1,1001)'
b=a = [float(i) for i in a]
i=0
d=1.1
e=[]
while i<len(a):
    j=0
    while j<len(b): 
        if abs(a[i]/b[j]-c)< d:
            d=abs(a[i]/b[j]-c)
            e.append([a[i],'/',b[j],'=',a[i]/b[j],'Error =',d])
            e1=a[i]/b[j]
        j+= 1
    i+=1
"print e[-1]"
#====================
#Complication
#used variables: f, g, h, k, l, m, n, l1 (7 items)
"h = float(raw_input('h=? '))"
h=c
f=a
#f=range(0,101) #you may stay 'f=range(1,11)' or 'f=range(1,1001)'
g=f = [float(n) for n in f]
n=0
k=1.1
l=[]
while n<len(f):
    m=0
    while m<len(g): 
        if abs(f[n]*g[m]-h)< k:
            k=abs(f[n]*g[m]-h)
            l.append([f[n],'*',g[m],'=',f[n]*g[m],'Error =',k])
            l1=f[n]*g[m]
        m+= 1
    n+=1
"print l[-1]"
#=================
#Addittion
#added variables: aa, bb, cc, dd, ee, jj, ii, ee1 (7 items)
"cc = float(raw_input('cc=? '))"
cc=c
aa=a
#aa=range(0,101) #you may stay 'aa=range(1,11)' or 'aa=range(1,1001)'
bb=aa = [float(ii) for ii in aa]
ii=0
dd=1.1
ee=[]
while ii<len(aa):
    jj=0
    while jj<len(bb): 
        if abs(aa[ii]+bb[jj]-cc)< dd:
            dd=abs(aa[ii]+bb[jj]-cc)
            ee.append([aa[ii],'+',bb[jj],'=',aa[ii]+bb[jj],'Error =',dd])
            ee1=aa[ii]+bb[jj]
        jj+= 1
    ii+=1
"print ee[-1]"
#=================
#subtraction
#used variables: ff, gg, hh, kk, ll, mm, nn, ll1 (7 items)
"hh = float(raw_input('hh=? '))"
hh=c
ff=a
#ff=range(0,101) #you may stay 'ff=range(1,11)' or 'ff=range(1,1001)'
gg=ff = [float(nn) for nn in ff]
nn=0
kk=1.1
ll=[]
while nn<len(ff):
    mm=0
    while mm<len(gg): 
        if abs(ff[nn]-gg[mm]-hh)< kk:
            kk=abs(ff[nn]-gg[mm]-hh)
            ll.append([ff[nn],'-',gg[mm],'=',ff[nn]-gg[mm],'Error =',kk])
            ll1=ff[nn]-gg[mm]
        mm+= 1
    nn+=1
"print ll[-1]"
#=================
#comparision.
#used variables: p,q
#print 'c =',c
p=min(d,k,dd,kk)
if p==d:
    q=e[-1]
    #print q
if p==k:
    q=l[-1]
    #print q
if p==dd:
    q=ee[-1]
    #print q
if p==kk:
    q=ll[-1]
    #print q
#print q
#for 4.0:
pp=p
qq=q
if c1==-1:
    qq=['-']+qq
#=================================================================================
#=================================================================================
#Add 3.2.py
i=0
a = [float(i) for i in range(1,11)]
f=[sqrt(i) for i in a] 
g=[exp(i) for i in a]
if c==-1:
    m=[1.0/log[i] for i in a]
else:
    m=[log(i) for i in a]
if c==-1:
    n=[1.0/log10(i) for i in a]
else:
    n=[log10(i) for i in a]
p=[i**(1/3.0) for i in a]
q=[i**2.0 for i in a]
s=[i**3.0 for i in a]
t=[2.0**i for i in a]
if c==-1:
    u=[1.0/log(i,2) for i in a]
else:
    u=[log(i,2) for i in a]
v=[(sqrt(5.0)+1.0)/2.0,pi/6.0,pi/4.0,pi/3.0,pi/2.0,pi,pi*3/2.0,pi*2.0,1/3.0,1/2.0]
#v=[pi*i for i in vpi]

h=a+f+g+m+n+p+q+s+t+u+v
i=0
r=10.1
while i <len(h):
    if c>0:
        if abs(c-h[i])<r:
            k=h[i]
            b=i
            r=abs(c-h[i])
        i+=1
#=======================================================
if z==0:
    if abs(h[b]-c)<=pp:
        if 0<=b<=9:
            pass
            #print 'Integer'
        elif 10<=b<=19:
            print 'sqrt(y)'
        elif 20<=b<=29:
            print 'exp(y)'
        elif 30<=b<=39:
            print 'log(y)'
        elif 40<=b<=49:
            print 'log10(y)'
        elif 50<=b<=59:
            print 'y**(1/3)'
        elif 60<=b<=69:
            print 'y**2'
        elif 70<=b<=79:
            print 'y**3'
        elif 80<=b<=89:
            print '2**y'
        elif 90<=b<=99:
            print 'log2(y)'
        elif b==100:
            print 'fi=(sqrt(5)+1)/2'
        elif b==101:
            print 'pi/6'
        elif b==102:
            print 'pi/4'
        elif b==103:
            print 'pi/3'
        elif b==104:
            print 'pi/2'
        elif b==105:
            print 'pi'
        elif b==106:
            print '3*pi/2'
        elif b==107:
            print '2*pi'
        elif b==108:
            print '1/3'
        elif b==109:
            print '1/2'
        
        if 0<=b<=9:
            bb=b
        elif 10<=b<=99:
            bb=b%10
        elif 100<=b<=1000:
            bb=b%100

        if not 100<=b<=109:
            print 'y =',bb+1
        if c1==-1:
            print '-f(y)=','-',h[b]
        else:
            print 'f(y)=',h[b]
        print 'Error=',abs(h[b]-c)
    else:
        print qq

Следующим шагом добавил вторую итерацию — полученный массив данных на первом этапе проходил повторный прогон.
Программа находила по заданному 3.69314718056 искомые 3+log(2)

Версия 5.1:

# -*- coding: cp1251 -*-
#iteration 2 step
from math import *
#--------------
#This version have MemoryError
#0 iteration
c = float(input ('c=? '))
#c=1/sqrt(2)
print 'c =',c
c1=1 #индикатор знака по умолчанию положителен.
if c<0:
    c=-c
    c1=-1 #индикатор знака - изменен на отрицательный.
k=10

#-1 iteration
z1=range(1,11)
z2=[]
z2=[pi,exp(1)]
z3=[]
z3=[sqrt(2),sqrt(3)]
z4=[]
z4=[sqrt(2)/2.0, sqrt(3)/2.0]
z5=[2**(1/3.0),3**(1/3.0)]
if c>=1:
    z6=[log(2),log10(2)]
else:
    z6=[-log(1/2.0),-log10(1/2.0)]
z=z1
z234=z2+z3+z4+z5+z6
if c1>=1:
   z2345=['pi','exp(1)','sqrt(2)','sqrt(3)','sqrt(2)/2.0', 'sqrt(3)/2.0', '2**(1/3.0)','3**(1/3.0)','log(2)','log10(2)']
else:
   z2345=['pi','exp(1)','sqrt(2)','sqrt(3)','sqrt(2)/2.0', 'sqrt(3)/2.0', '2**(1/3.0)','3**(1/3.0)','-log(1/2.0)','-log10(1/2.0)']
#z=z1+z234
a=z
#print len(a)

#0 iteration
b=a = [float(i) for i in a]
i=0
adivb=[]
while i<len(a):
    j=0
    while j<len(b): 
        ab=a[i]/b[j]
        adivb.append(ab)
        j+= 1
    i+=1
#sqrt1=[sqrt(i) for i in a]
#exp1=[sqrt(i) for i in a]
#print len(adivb)
#-------------
#1 iteration
i=0
adivb1=[]
acomplb1=[]
asumb1=[]
asubb1=[]
a1=adivb
b1=z234
while i<len(a1):
    j=0
    while j<len(b1): 
        ab1=a1[i]/b1[j] #div
        #adivb1.append(ab1)
        if abs(ab1-c)<k:
            k=abs(ab1-c)
            q='/'
            p=j
            r=i
            g=[a1[i],'/',z2345[j]]
#           g=[a1[i],'/',b1[j]]
        ax1=a1[i]*b1[j] #compl
        #acomplb1.append(ax1)
        if abs(ax1-c)<k:
            k=abs(ax1-c)
            q='*'
            p=j
            r=i
            g=[a1[i],'*',z2345[j]]
#           g=[a1[i],'*',b1[j]]
        ay1=a1[i]+b1[j] #sum
        #asumb1.append(ay1)
        if abs(ay1-c)<k:
            k=abs(ay1-c)
            q='+'
            p=j
            r=i
            g=[a1[i],'+',z2345[j]]
#           g=[a1[i],'+',b1[j]]
        az1=a1[i]-b1[j] #subtraction
        #asubb1.append(az1)
        if abs(az1-c)<k:
            k=abs(az1-c)
            q='-'
            p=j
            r=i
            g=[a1[i],'-',z2345[j]]
#           g=[a1[i],'-',b1[j]]
        j+= 1
    i+=1
#print r,k,p,z234[p]
print g
#-----------------------
#aabb=adivb1+acomplb1+asumb1+asubb1
#print len(aabb)
#-------------------------
#print "----------------------------"
"""
i=0
k=10
while i<len(aabb):
    if abs(aabb[i]-c)<k:
        k=abs(aabb[i]-c)
        kk=i
    i+=1
#print 'c = ',c
#print 'index =',kk
#print 'ближайшее значение =',aabb[kk]
#print 'k =',k #error


if kk>9:
    bb=(kk)%10

if 0<=kk<=9:
    print '1','/',kk+1
elif 10<=kk<=19:
    print '2','/',bb+1
elif 20<=kk<=29:
    print '3','/',bb+1
elif 30<=kk<=39:
    print '4','/',bb+1
elif 40<=kk<=49:
    print '5','/',bb+1
elif 50<=kk<=59:
    print '6','/',bb+1
elif 60<=kk<=69:
    print '7','/',bb+1
elif 70<=kk<=79:
    print '8','/',bb+1
elif 80<=kk<=89:
    print '9','/',bb+1
elif 90<=kk<=99:
    print '10','/',bb+1
"""
#-------
#if c1>=1:
#   z234=[pi,exp(1),sqrt(2),sqrt(3),sqrt(2)/2.0, sqrt(3)/2.0, 2**(1/3.0),3**(1/3.0),log(2),log10(2)]
#else:
#   z234=[pi,exp(1),sqrt(2),sqrt(3),sqrt(2)/2.0, sqrt(3)/2.0, 2**(1/3.0),3**(1/3.0),-log(1/2.0),-log10(1/2.0)]

"""
#1 iteration
if kk>99:
    bb=(kk)%100
if 0<=kk<=99:
    pass
elif 100<=kk<=199:
    print '1','/','(','1','/',kk+1,')'
elif 200<=kk<=299:
    print '1','/','(','2','/',bb+1,')'
elif 300<=kk<=399:
    print '1','/','(','3','/',bb+1,')'
elif 400<=kk<=499:
    print '1','/','(','4','/',bb+1,')'
elif 500<=kk<=599:
    print '1','/','(','5','/',bb+1,')'
elif 600<=kk<=690:
    print '1','/','(','6','/',bb+1,')'
elif 700<=kk<=799:
    print '1','/','(','7','/',bb+1,')'
elif 800<=kk<=899:
    print '1','/','(','8','/',bb+1,')'
elif 900<=kk<=999:
    print '1','/','(','9','/',bb+1,')'
elif 1000<=kk<=1099:
    print '1','/','(','9','/',bb+1,')'
"""

К сожалению на 3-ю итерацию памяти питона уже не хватало. Поэтому находить по заданному 10.007106781 искомые 3+sqrt(2)*5 уже не получится. Оно и понятно, чудес не бывает.

Что хотелось реализовать, но сделано не было

1.Сервис не выложен в интернет.
2.Хотелось все-таки преодолеть лимит памяти в 2 действия.
3.Дать пользователю самому вводить область поиска — т.е. используемые значения. К примеру, если в тестовой задаче дано 6 конкретных чисел, то нет смысла использовать все натуральные и иррациональные числа, а достаточно оперировать только этими значениями.
(Другое дело, что этих значений может быть недостаточно — от пользователя могут потребоваться общие знания. Например, при заданных значениях длины и ширины прямоугольника, пользователь должен знать о удвоении этих величин при вычислении периметра. Программа-же заранее знать о назначении величин не может. Либо опять-таки надо добавлять к введенным пользователем величинам набор натуральных значений от 1 до 10 плюс стандартные иррациональности.)
4.Даже если пользователь получит все алгоритмы всех тестовых ответов, он все равно не знает, какой из них правильный. Хотя тут уже вопрос к пользователю, а не к программе-подсказчику.

Где можно применять

1.При решении простых тестовых задач по математике, физике.
2.Там, где требуется установить зависимости между входными и выходными данными.

Вопросы к читателям:
1.Будете ли вы при необходимости пользоваться программой (бесплатно, на сайте, где есть немного рекламы)?
2.Стоит ли добавлять нереализованные возможности?
3.Знаете ли вы более удобные аналоги программы?

image
image

Автор: Michael134096

Источник

Поделиться

* - обязательные к заполнению поля