Skip to content

Instantly share code, notes, and snippets.

@kurubushi--rm
Created June 12, 2016 06:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kurubushi--rm/1b2d9c20fac4ded079f81862532d0a49 to your computer and use it in GitHub Desktop.
Save kurubushi--rm/1b2d9c20fac4ded079f81862532d0a49 to your computer and use it in GitHub Desktop.
# coding: utf-8
# In[1]:
from __future__ import print_function
from IPython.core.magic import (register_line_magic, register_cell_magic)
import pandas as pd
import numpy as np
from sympy import *
init_printing()
import io
import re
import itertools
# ## サンプル作成用関数
# In[2]:
@register_cell_magic
def csv2df(line, cell):
sio = io.StringIO(cell)
return pd.read_csv(sio)
# In[3]:
#真理表の論理変数をつくる
def make_logic_table(n):
A2Z = [chr(i+ord('A')) for i in range(26)]
print (','.join(A2Z[:n]), ',') #アルファベット大文字のリストから前からn個
l = ['0','1']
# デカルト積 繰り返しを許す: 1,1 がある、順序が違えば別と見なす: 1,2 と 2,1 は別
for element in itertools.product(l, repeat=n):
print (','.join(element), ',')
# In[4]:
#事例テーブルを乱数でつくる
def random_case_table(n,m):
A2Z = [chr(i+ord('A')) for i in range(26)] #アルファベット大文字のリストから前からn個
case_df = pd.DataFrame(np.random.randint(0,5,(n,m)), columns=A2Z[:m]) #randint(a,b,(c,d)) aからbまでの整数乱数をc×dの行列に
case_df[chr(m+ord('A'))] = np.random.randint(0,5,(n,1))
return case_df
# # ブール代数アプローチ用の関数
# In[5]:
def binarize_rep (df, col, str_list):
'''
コラムの中身を数値に置き換えて論理変数にする
df: 事例表のデータフレーム
col : データフレームのうち二値化して論理変数とするコラム
str_list: 置換前の文字列(1つめが0に、2つめが1に、3つめが2に・・・(以下同様)置換される)
返り値:コラムを置換したデータフレーム
例 replace_col(df,'ネオ・コーポラティズムか',['Yes','No'])
'''
for old, new in zip(str_list, range(len(str_list))):
df[col] = df[col].str.replace(old, str(new))
df[col] = df[col].astype(int)
return df
def binarize(df, cond_list, threshold_list):
'''
閾値を使って独立関数を二値化して論理変数にする
df: 事例表のデータフレーム
cond_list : データフレームのうち二値化して論理変数とするコラム(列)のリスト
threshold_list: 二値化の閾値のリスト(それぞれのコラムについて、この値以上なら1、未満なら0にする)
返り値:独立関数を二値化して論理変数にした事例表のデータフレーム
'''
for col, threshold in zip(cond_list, threshold_list):
df[col] = df[col].apply( lambda x: 1 if x >= float(threshold) else 0 )
return df
def mark_contains(df, check_col, mark_string_list, mark_list):
'''
特定の文字列が含んでいるかどうかで論理変数を決めてコラムとして追加する
df: 事例表のデータフレーム
check_col: 文字列が含まれるかどうかチェックする対象のコラム名
mark_string_list: 含んでいるかどうかチェックする文字列のリスト
例: ['飢饉','凶作','干ばつ','地震','流行','米価暴騰','乱','変','大獄','長州征討','大政奉還']
mark_list: 文字列が含まれていた時に1をセットするカラム名(mark_string_listと同じ長さ)
例:['E','E','E','D','D','E','P','P','P','P','P']
返り値:論理変数を格納するmark_listのカラムを追加した事例表のデータフレーム
'''
df_n = df.dropna(subset=[check_col]) #nanが含まれるとうまく動かないので除いてる
already_col = [] #一度出てきたカラムは上書きして0に戻さないように記録する
for k,v in zip(mark_list, mark_string_list):
#print (k,v)
if k in already_col:
df_n[k] = df_n.apply( lambda x: 1 if x[k] or (v in x[check_col]) else 0 , axis=1)
else:
df_n[k] = df_n[check_col].apply( lambda x: 1 if v in x else 0 )
already_col.append(k)
return df_n
# In[6]:
def CT2TT(df, cond_list, result_col, cutpoint):
'''
事例表から真理表をつくる
df : 事例表のデータフレーム
cond_list : データフレームのうち論理変数が入ってるコラム(列)のリスト
result_col : 出力変数が入っているコラム(列)
cutpoint : 現象が生起したとみなせる結果の件数の下限値
返り値:真理表のデータフレーム(論理変数〜現象が生起したとみなせる結果の事例数〜当該の論理変数を満たす事例数)
'''
result = ','.join(cond_list) +','+ result_col +'_cases,all_cases\n'
query_root_string = '&'.join([col+'=={}' for col in cond_list]) #'A=={}&B=={}&C=={}'
query_root_cutpoint_string = query_root_string + '&' + result_col + '>=' + str(cutpoint) #'A=={}&B=={}&C=={}&D>=5'
for element in itertools.product([0,1], repeat=len(cond_list)):
query_string = query_root_string.format(*element)
query_cutpoint_string = query_root_cutpoint_string.format(*element)
result += ','.join(map(str, element)) +',' + str(df.query(query_cutpoint_string).count()[result_col])+',' + str(df.query(query_string).count()[result_col]) + '\n'
sio = io.StringIO(result)
return_df = pd.read_csv(sio)
return_df[result_col] = return_df['{}_cases'.format(result_col)] / return_df['all_cases']
return return_df
# In[7]:
def table2bool(df, cond_list, result_col, cutpoint):
'''
真理表からブール式をつくる
df : 真理表のデータフレーム
cond_list : データフレームのうち論理変数が入ってるコラム(列)のリスト
result_col : 出力変数が入っているコラム(列)
cutpoint : 現象が生起したとみなせる結果の件数の下限値
例: table2bool(df, ['L','C','G'],'E', 1)
=>CGL+CGl+Cgl+GLc
'''
true_case_df = df[df[result_col].apply(lambda x: float(x)) >= cutpoint]
#return true_case_df
wholeform = []
for idx in true_case_df.index:
nowitem = []
for column in cond_list:
#print (column, true_case_df.ix[idx][column], end='')
TF = int(true_case_df.ix[idx][column])
if TF:
nowitem.append(column.upper())
else:
nowitem.append(column.lower())
#print (nowitem, end='\n')
wholeform.append('*'.join(nowitem))
return sympify('+'.join(wholeform))
# In[8]:
def bool2logic(b):
'''
ブール代数式を論理式に変換する
'''
s = srepr(b).replace('Mul','And').replace('Add','Or')
s = re.sub(r"Symbol\('([A-Za-z])'\)", r'\1', s)
s = re.sub(r'([ \(])([a-z])', (lambda x: x.group(1) + 'Not(' + x.group(2).upper() +')' ), s)
return sympify(s)
# In[9]:
def logic2bool(l):
'''
論理式をブール代数式に変換する
'''
s = srepr(l).replace('And','Mul').replace('Or','Add')
s = re.sub(r"Symbol\('([A-Z])'\)", r'\1', s)
s = re.sub(r'Not\(([A-Z]+)\)', (lambda x: x.group(1).lower()) , s)
return sympify(s)
# In[10]:
def complement_bool(b):
'''
ブール代数式から補集合のブール式を得る
'''
return logic2bool(to_dnf(Not(bool2logic(b))))
def simplify_bool(b):
'''
ブール代数式を積和標準形の形に簡単化する
'''
return logic2bool(simplify_logic(bool2logic(b),form='dnf'))
# In[11]:
def minimize(df, cond_list, result_col, cutpoint, dontcare_symbol=''):
'''
真理表から縮約した論理式をつくる
df : 真理表のデータフレーム
cond_list : データフレームのうち論理変数が入ってるコラム(列)のリスト
result_col : 出力変数が入っているコラム(列)
cutpoint : 現象が生起したとみなせる結果の件数の下限値
dontcare_symbol: don't care条件して用いる行の出力変数の値
例: 真理表のデータフレームtrue_tableについて、
論理変数L,C,Gと出力変数Eを指定、
Eが1以上の行を真理条件とし、Eが?の行をdon't care条件として
真理表から縮約した論理式を得る
minimize(true_table, ['L','C','G'], 'E', 1,'?')
=>(C∧¬L)∨(G∧L)
'''
if dontcare_symbol:
#don't care条件がある場合
dontcare_df = df[df[result_col].str.contains(dontcare_symbol) ]
dontcares = dontcare_df[cond_list].values.tolist()
df = df[~df[result_col].str.contains(dontcare_symbol) ] #dontcareシンボルが含まれない行だけを対象にする
else:
#don't care条件がない場合
dontcares = []
true_case_df = df[df[result_col].apply(lambda x: float(x)) >= cutpoint]
minterms = true_case_df[cond_list].values.tolist()
return SOPform(cond_list, minterms, dontcares)
# In[12]:
def minimize_bool(df, cond_list, result_col, cutpoint,dontcare_symbol=''):
'''
dontcare_symbol: don't care条件して用いる行の出力変数の値
例: 真理表のデータフレームtrue_tableについて、
論理変数L,C,Gと出力変数Eを指定、
Eが1以上の行を真理条件とし、Eが?の行をdon't care条件として
真理表から縮約したブール式を得る
minimize(true_table, ['L','C','G'], 'E', 1,'?')
=>Cl+GL
'''
return logic2bool(minimize(df, cond_list, result_col, cutpoint,dontcare_symbol))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment