@@ -200,22 +200,22 @@ class Reasoner: | |||
""" | |||
dimension = Dimension(size=symbol_num, regs=[[0, 1]] * symbol_num, tys=[False] * symbol_num) | |||
objective = Objective( | |||
lambda sol: self.zoopt_revision_score(symbol_num, data_example, sol), | |||
lambda sol: self.zoopt_score(symbol_num, data_example, sol), | |||
dim=dimension, | |||
constraint=lambda sol: self._constrain_revision_num(sol, max_revision_num), | |||
) | |||
parameter = Parameter(budget=200, intermediate_result=False, autoset=True) | |||
parameter = Parameter(budget=self.zoopt_budget(symbol_num), intermediate_result=False, autoset=True) | |||
solution = Opt.min(objective, parameter) | |||
return solution | |||
def zoopt_revision_score( | |||
def zoopt_score( | |||
self, | |||
symbol_num: int, | |||
data_example: ListData, | |||
sol: Solution, | |||
) -> int: | |||
""" | |||
Get the revision score for a solution. A lower score suggests that ZOOpt library | |||
Set the revision score for a solution. A lower score suggests that ZOOpt library | |||
has a higher preference for this solution. | |||
Parameters | |||
@@ -240,6 +240,29 @@ class Reasoner: | |||
return np.min(self._get_cost_list(data_example, candidates, reasoning_results)) | |||
else: | |||
return symbol_num | |||
def zoopt_budget(self, symbol_num: int) -> int: | |||
""" | |||
Sets a default budget for ZOOpt optimization. The function, in its default implementation, | |||
returns a fixed budget value of 100. However, it can be adjusted to return other fixed | |||
values, or a dynamic budget based on the number of symbols, if desired. For example, one might choose to | |||
set the budget as 100 times symbol_num. | |||
Parameters | |||
---------- | |||
symbol_num : int | |||
The number of symbols to be considered in the ZOOpt optimization process. Although this parameter | |||
can be used to compute a dynamic optimization budget, by default it is not utilized in the | |||
calculation. | |||
Returns | |||
------- | |||
int | |||
The budget for ZOOpt optimization. By default, this is a fixed value of 100, | |||
irrespective of the symbol_num value. | |||
""" | |||
return 100 | |||
def _constrain_revision_num(self, solution: Solution, max_revision_num: int) -> int: | |||
""" | |||
@@ -208,32 +208,34 @@ Building the Reasoning Part | |||
In the reasoning part, we first build a knowledge base. As mentioned | |||
before, the knowledge base in this task involves the structure of the | |||
equations and a recursive definition of bit-wise operations. The | |||
knowledge base is already defined in ``HedKB``, which is derived from | |||
``PrologKB``, and is built upon Prolog file ``reasoning/BK.pl`` and | |||
``reasoning/learn_add.pl``. | |||
Specifically, the knowledge about the structure of equations (in | |||
``reasoning/BK.pl``) is a set of DCG (definite clause grammar) rules | |||
recursively define that a digit is a sequence of ‘0’ and ‘1’, and | |||
equations and a recursive definition of bit-wise operations, which are | |||
defined in Prolog file ``examples/hed/reasoning/BK.pl`` | |||
and ``examples/hed/reasoning/learn_add.pl``, respectively. | |||
Specifically, the knowledge about the structure of equations is a set of DCG | |||
rules recursively define that a digit is a sequence of ‘0’ and ‘1’, and | |||
equations share the structure of X+Y=Z, though the length of X, Y and Z | |||
can be varied. The knowledge about bit-wise operations (in | |||
``reasoning/learn_add.pl``) is a recursive logic program, which | |||
reversely calculates X+Y, i.e., it operates on X and Y digit-by-digit | |||
and from the last digit to the first. | |||
Note: Please notice that, the specific rules for calculating the | |||
operations are undefined in the knowledge base, i.e., results of ‘0+0’, | |||
‘0+1’ and ‘1+1’ could be ‘0’, ‘1’, ‘00’, ‘01’ or even ‘10’. The missing | |||
calculation rules are required to be learned from the data. Therefore, | |||
``HedKB`` incorporates methods for abducing rules from data. Users | |||
interested can refer to the specific implementation of ``HedKB`` in | |||
``reasoning/reasoning.py`` | |||
can be varied. The knowledge about bit-wise operations is a recursive | |||
logic program, which reversely calculates X+Y, i.e., it operates on | |||
X and Y digit-by-digit and from the last digit to the first. | |||
The knowledge base is already built in ``HedKB``. | |||
``HedKB`` is derived from class ``PrologKB``, and is built upon the aformentioned Prolog | |||
files. | |||
.. code:: ipython3 | |||
kb = HedKB() | |||
.. note:: | |||
Please notice that, the specific rules for calculating the | |||
operations are undefined in the knowledge base, i.e., results of ‘0+0’, | |||
‘0+1’ and ‘1+1’ could be ‘0’, ‘1’, ‘00’, ‘01’ or even ‘10’. The missing | |||
calculation rules are required to be learned from the data. Therefore, | |||
``HedKB`` incorporates methods for abducing rules from data. Users | |||
interested can refer to the specific implementation of ``HedKB`` in | |||
``examples/hed/reasoning/reasoning.py`` | |||
Then, we create a reasoner. Due to the indeterminism of abductive | |||
reasoning, there could be multiple candidates compatible to the | |||
knowledge base. When this happens, reasoner can minimize inconsistencies | |||
@@ -290,11 +290,9 @@ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"In the reasoning part, we first build a knowledge base. As mentioned before, the knowledge base in this task involves the structure of the equations and a recursive definition of bit-wise operations. The knowledge base is already defined in `HedKB`, which is derived from `PrologKB`, and is built upon Prolog file `reasoning/BK.pl` and `reasoning/learn_add.pl`.\n", | |||
"In the reasoning part, we first build a knowledge base. As mentioned before, the knowledge base in this task involves the structure of the equations and a recursive definition of bit-wise operations, which are defined in Prolog file ``reasoning/BK.pl`` and ``reasoning/learn_add.pl``, respectively. Specifically, the knowledge about the structure of equations is a set of DCG rules recursively define that a digit is a sequence of ‘0’ and ‘1’, and equations share the structure of X+Y=Z, though the length of X, Y and Z can be varied. The knowledge about bit-wise operations is a recursive logic program, which reversely calculates X+Y, i.e., it operates on X and Y digit-by-digit and from the last digit to the first.\n", | |||
"\n", | |||
"Specifically, the knowledge about the structure of equations (in `reasoning/BK.pl`) is a set of DCG (definite clause grammar) rules recursively define that a digit is a sequence of '0' and '1', and equations share the structure of X+Y=Z, though the length of X, Y and Z can be varied. The knowledge about bit-wise operations (in `reasoning/learn_add.pl`) is a recursive logic program, which reversely calculates X+Y, i.e., it operates on X and Y digit-by-digit and from the last digit to the first.\n", | |||
"\n", | |||
"Note: Please notice that, the specific rules for calculating the operations are undefined in the knowledge base, i.e., results of '0+0', '0+1' and '1+1' could be '0', '1', '00', '01' or even '10'. The missing calculation rules are required to be learned from the data. Therefore, `HedKB` incorporates methods for abducing rules from data. Users interested can refer to the specific implementation of `HedKB` in `reasoning/reasoning.py`" | |||
"The knowledge base is already built in ``HedKB``. ``HedKB`` is derived from class ``PrologKB``, and is built upon the aformentioned Prolog files. " | |||
] | |||
}, | |||
{ | |||
@@ -306,6 +304,13 @@ | |||
"kb = HedKB()" | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
"source": [ | |||
"Note: Please notice that, the specific rules for calculating the operations are undefined in the knowledge base, i.e., results of '0+0', '0+1' and '1+1' could be '0', '1', '00', '01' or even '10'. The missing calculation rules are required to be learned from the data. Therefore, `HedKB` incorporates methods for abducing rules from data. Users interested can refer to the specific implementation of `HedKB`." | |||
] | |||
}, | |||
{ | |||
"cell_type": "markdown", | |||
"metadata": {}, | |||
@@ -31,8 +31,11 @@ class HedReasoner(Reasoner): | |||
data_example.pred_pseudo_label, data_example.Y, data_example.X, revision_idx | |||
) | |||
return candidate | |||
def zoopt_budget(self, symbol_num): | |||
return 200 | |||
def zoopt_revision_score(self, symbol_num, data_example, sol, get_score=True): | |||
def zoopt_score(self, symbol_num, data_example, sol, get_score=True): | |||
revision_flag = reform_list( | |||
list(sol.get_x().astype(np.int32)), data_example.pred_pseudo_label | |||
) | |||
@@ -78,7 +81,7 @@ class HedReasoner(Reasoner): | |||
max_revision_num = self._get_max_revision_num(self.max_revision, symbol_num) | |||
solution = self._zoopt_get_solution(symbol_num, data_example, max_revision_num) | |||
max_candidate_idxs = self.zoopt_revision_score(symbol_num, data_example, solution, get_score=False) | |||
max_candidate_idxs = self.zoopt_score(symbol_num, data_example, solution, get_score=False) | |||
abduced_pseudo_label = [[] for _ in range(len(data_example))] | |||