Browse Source

Add zoopt option

pull/3/head
troyyyyy GitHub 3 years ago
parent
commit
4a217b71b7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 66 additions and 29 deletions
  1. +66
    -29
      abducer/abducer_base.py

+ 66
- 29
abducer/abducer_base.py View File

@@ -16,19 +16,22 @@ sys.path.append("..")
import abc
from abducer.kb import add_KB, hwf_KB, add_prolog_KB
import numpy as np
from zoopt import Dimension, Objective, Parameter, Opt

import time

class AbducerBase(abc.ABC):
def __init__(self, kb, dist_func = 'confidence', cache = True):
def __init__(self, kb, dist_func = 'confidence', zoopt = False, cache = True):
self.kb = kb
assert(dist_func == 'hamming' or dist_func == 'confidence')
self.dist_func = dist_func
self.cache = cache

self.zoopt = zoopt
if self.cache:
self.cache_min_address_num = {}
self.cache_candidates = {}

def hamming_dist(self, A, B):
B = np.array(B)
@@ -66,38 +69,58 @@ class AbducerBase(abc.ABC):
min_address_num = np.min(cost_list)
idxs = np.where(cost_list == min_address_num)[0]
return [candidates[idx] for idx in idxs][0]



def zoopt_address_score(self, pred_res, key, address_idx):
candidates = self.kb.address_by_idx2(pred_res, key, address_idx)
return 0 if len(candidates) > 0 else 1
def filter_all_candidates(self, pred_res, all_candidates, max_address_num, require_more_address):
if len(all_candidates) == 0:
candidates = []
min_address_num = 0
address_num = 0
else:
cost_list = self.hamming_dist(pred_res, all_candidates)
min_address_num = np.min(cost_list)
address_num = min(max_address_num, min_address_num + require_more_address)
idxs = np.where(cost_list <= address_num)[0]
candidates = [all_candidates[idx] for idx in idxs]
return candidates, min_address_num, address_num
def constraint_address_num(self, solution, max_address_num):
x = solution.get_x()
return max_address_num - x.sum()

def zoopt_get_address_idx(self, pred_res, key, max_address_num):
dimension = Dimension(size=len(pred_res),
regs=[[0, 1]] * len(pred_res),
tys=[False] * len(pred_res))
objective = Objective(lambda sol: self.zoopt_address_score(pred_res, key, [idx for idx, i in enumerate(sol.get_x()) if i != 0]),
dim=dimension,
constraint=lambda sol: self.constraint_address_num(sol, max_address_num))
parameter = Parameter(budget=100 * dimension.get_size(), autoset=True)
solution = Opt.min(objective, parameter).get_x()
address_idx = [idx for idx, i in enumerate(solution) if i != 0]
address_num = solution.sum()
return address_idx, address_num



def abduce(self, data, max_address_num = -1, require_more_address = 0):
pred_res, pred_res_prob, ans = data
pred_res, pred_res_prob, key = data
if max_address_num == -1:
max_address_num = len(pred_res)

if self.cache and (tuple(pred_res), ans) in self.cache_min_address_num:
address_num = min(max_address_num, self.cache_min_address_num[(tuple(pred_res), ans)] + require_more_address)
if (tuple(pred_res), ans, address_num) in self.cache_candidates:
candidates = self.cache_candidates[(tuple(pred_res), ans, address_num)]
if self.cache and (tuple(pred_res), key) in self.cache_min_address_num:
address_num = min(max_address_num, self.cache_min_address_num[(tuple(pred_res), key)] + require_more_address)
if (tuple(pred_res), key, address_num) in self.cache_candidates:
candidates = self.cache_candidates[(tuple(pred_res), key, address_num)]
return self.get_min_cost_candidate(pred_res, pred_res_prob, candidates)
candidates, min_address_num, address_num = self.kb.abduce_candidates(pred_res, ans, max_address_num, require_more_address)
if self.zoopt:
address_idx, address_num = self.zoopt_get_address_idx(pred_res, key, max_address_num)
candidates = self.kb.address_by_idx(pred_res, key, address_idx)
min_address_num = address_num
else:
candidates, min_address_num, address_num = self.kb.abduce_candidates(pred_res, key, max_address_num, require_more_address)
if self.cache:
self.cache_min_address_num[(tuple(pred_res), ans)] = min_address_num
self.cache_candidates[(tuple(pred_res), ans, address_num)] = candidates
self.cache_min_address_num[(tuple(pred_res), key)] = min_address_num
self.cache_candidates[(tuple(pred_res), key, address_num)] = candidates
candidate = self.get_min_cost_candidate(pred_res, pred_res_prob, candidates)
return candidate
@@ -113,8 +136,8 @@ class AbducerBase(abc.ABC):

if __name__ == '__main__':
prob1 = [[0, 0.99, 0.01, 0, 0, 0, 0, 0, 0, 0],[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
prob2 = [[0, 0, 0.01, 0, 0, 0, 0, 0.99, 0, 0],[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
prob1 = [[0, 0.99, 0.01, 0, 0, 0, 0, 0, 0, 0], [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
prob2 = [[0, 0, 0.01, 0, 0, 0, 0, 0.99, 0, 0], [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]
kb = add_KB(GKB_flag = True)
abd = AbducerBase(kb, 'confidence')
@@ -144,6 +167,20 @@ if __name__ == '__main__':
print(res)
print()
kb = add_prolog_KB()
abd = AbducerBase(kb, 'confidence', zoopt = True)
res = abd.abduce(([1, 1], prob1, 8), max_address_num = 2, require_more_address = 0)
print(res)
res = abd.abduce(([1, 1], prob2, 8), max_address_num = 2, require_more_address = 0)
print(res)
res = abd.abduce(([1, 1], prob1, 17), max_address_num = 2, require_more_address = 0)
print(res)
res = abd.abduce(([1, 1], prob1, 17), max_address_num = 1, require_more_address = 0)
print(res)
res = abd.abduce(([1, 1], prob1, 20), max_address_num = 2, require_more_address = 0)
print(res)
print()
kb = hwf_KB(len_list = [1, 3, 5])
abd = AbducerBase(kb, 'hamming')
res = abd.abduce((['5', '+', '2'], None, 3), max_address_num = 2, require_more_address = 0)
@@ -156,4 +193,4 @@ if __name__ == '__main__':
print(res)
print()

Loading…
Cancel
Save