Skip to content

Commit

Permalink
"Friendly" output of requirements and features
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-zeller committed Jan 5, 2025
1 parent 166986f commit 57e23a4
Showing 1 changed file with 65 additions and 22 deletions.
87 changes: 65 additions & 22 deletions notebooks/Alhazen.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -605,10 +605,12 @@
" key : The feature key (e.g., the chosen alternative or rule itself).\n",
" '''\n",
"\n",
" def __init__(self, name: str, rule: str, key: str) -> None:\n",
" def __init__(self, name: str, rule: str, key: str, /,\n",
" friendly_name: str = None) -> None:\n",
" self.name = name\n",
" self.rule = rule\n",
" self.key = key\n",
" self._friendly_name = friendly_name or name\n",
" super().__init__()\n",
"\n",
" def __repr__(self) -> str:\n",
Expand All @@ -619,6 +621,9 @@
" def name_rep(self) -> str:\n",
" pass\n",
"\n",
" def friendly_name(self) -> str:\n",
" return self._friendly_name\n",
"\n",
" @abstractmethod\n",
" def get_feature_value(self, derivation_tree) -> float:\n",
" '''Returns the feature value for a given derivation tree of an input.'''\n",
Expand Down Expand Up @@ -648,8 +653,9 @@
" key : The feature key, equal to the rule attribute for production features,\n",
" or equal to the corresponding alternative for alternative features.\n",
" '''\n",
" def __init__(self, name: str, rule: str, key: str) -> None:\n",
" super().__init__(name, rule, key)\n",
" def __init__(self, name: str, rule: str, key: str,\n",
" friendly_name: str = None) -> None:\n",
" super().__init__(name, rule, key, friendly_name=friendly_name)\n",
"\n",
" def name_rep(self) -> str:\n",
" if self.rule == self.key:\n",
Expand Down Expand Up @@ -709,8 +715,8 @@
" e.g., 'num(<integer>)'\n",
" rule : The production rule.\n",
" '''\n",
" def __init__(self, name: str, rule: str) -> None:\n",
" super().__init__(name, rule, rule)\n",
" def __init__(self, name: str, rule: str, friendly_name: str = None) -> None:\n",
" super().__init__(name, rule, rule, friendly_name=friendly_name)\n",
"\n",
" def name_rep(self) -> str:\n",
" return f\"num({self.key})\"\n",
Expand Down Expand Up @@ -766,7 +772,11 @@
" features.append(ExistenceFeature(f\"exists({rule})\", rule, rule))\n",
" # add all alternatives\n",
" for count, expansion in enumerate(grammar[rule]):\n",
" features.append(ExistenceFeature(f\"exists({rule}@{count})\", rule, expansion))\n",
" name = f\"exists({rule}@{count})\"\n",
" friendly_name = f\"{rule} == {repr(expansion)}\"\n",
" feature = ExistenceFeature(name, rule, expansion,\n",
" friendly_name=friendly_name)\n",
" features.append(feature)\n",
"\n",
" return features"
]
Expand Down Expand Up @@ -825,7 +835,11 @@
" for key in derivable_chars:\n",
" # Check if derivable chars contain only numeric chars\n",
" if len(derivable_chars[key] - numeric_chars) == 0:\n",
" features.append(NumericInterpretation(f\"num({key})\", key))\n",
" name = f\"num({key})\"\n",
" friendly_name = f\"{key}\"\n",
"\n",
" features.append(NumericInterpretation(f\"num({key})\", key,\n",
" friendly_name=friendly_name))\n",
"\n",
" return features"
]
Expand All @@ -849,6 +863,15 @@
"get_all_features(CALC_GRAMMAR)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"[f.friendly_name() for f in get_all_features(CALC_GRAMMAR)] "
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -2161,7 +2184,25 @@
" self.value = value\n",
"\n",
" def __str__(self):\n",
" return f\"Requirement({self.feature.name} {self.quant} {self.value})\""
" return f\"Requirement({self.feature.name} {self.quant} {self.value})\"\n",
"\n",
" def __repr__(self):\n",
" return f\"Requirement({self.feature.name}, {self.quant}, {self.value})\"\n",
"\n",
" def friendly(self):\n",
" def value(x):\n",
" try:\n",
" return float(x)\n",
" except Exception:\n",
" return None\n",
"\n",
" if isinstance(self.feature, ExistenceFeature):\n",
" if value(self.value) > 0:\n",
" return f\"{self.feature.friendly_name()}\"\n",
" elif value(self.value) < 0:\n",
" return f\"not {self.feature.friendly_name()}\"\n",
"\n",
" return f\"{self.feature.friendly_name()} {self.quant} {self.value}\""
]
},
{
Expand All @@ -2181,12 +2222,14 @@
" self.requirements: List[SpecRequirement] = requirements\n",
"\n",
" def __str__(self):\n",
" # Handle first element\n",
" s = f\"{str(self.requirements[0])}\"\n",
" for count in range(1, len(self.requirements)):\n",
" s += (\", \" + str(self.requirements[count]))\n",
" s = \", \".join(str(r) for r in self.requirements)\n",
" return f\"InputSpecification({s})\"\n",
"\n",
" return f\"InputSpecification({s})\""
" def friendly(self):\n",
" return \" and \".join(r.friendly() for r in self.requirements)\n",
"\n",
" def __repr__(self):\n",
" return self.__str__()"
]
},
{
Expand Down Expand Up @@ -2339,17 +2382,18 @@
"metadata": {},
"source": [
"We implement a _Grammar-Based Input Generator_ that generates new input samples from a List of `Input Specifications`.\n",
"The Input Specifications are extracted from the decision tree boundaries in the previous Activity 3: _RequirementExtraction_\n",
"The Input Specifications are extracted from the decision tree boundaries in the previous Activity 3: _RequirementExtraction_.\n",
"\n",
"An Input Specification consists of **1 to n** many predicates or requirements (e.g. feature '>=' value, or 'num(term) <= 13').\n",
"We generate a new input for each InputSpecification.\n",
"The new input fulfills all the given requirements of an IputSpecification."
"We generate a new input for each `InputSpecification`.\n",
"The new input fulfills all the given requirements of an InputSpecification."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Info:** For furter details, please refer to <b>Section 4.4 and 4.5</b> of the <a href=\"https://publications.cispa.saarland/3107/7/fse2020-alhazen.pdf\">paper</a> and the Chapter <b><a href=\"https://www.fuzzingbook.org/html/GrammarFuzzer.html\">Efficient Grammar Fuzzing</a></b> in the fuzzingbook."
"**Info:** For further details, please refer to <b>Section 4.4 and 4.5</b> of the <a href=\"https://publications.cispa.saarland/3107/7/fse2020-alhazen.pdf\">paper</a> and the Chapter <b><a href=\"https://www.fuzzingbook.org/html/GrammarFuzzer.html\">Efficient Grammar Fuzzing</a></b> in the fuzzingbook."
]
},
{
Expand Down Expand Up @@ -2679,15 +2723,14 @@
" self._data.drop(['oracle'], axis=1))\n",
" print(f\" New input specifications:\")\n",
" for spec in new_input_specifications:\n",
" print(f\" {str(spec)}\")\n",
" print(f\" {spec.friendly()}\")\n",
"\n",
" # generate new inputs according to the new input specifications\n",
" new_samples = generate_samples(self._grammar,\n",
" new_input_specifications,\n",
" self._generator_timeout)\n",
" print(f\" New samples:\")\n",
" for sample in new_samples:\n",
" print(f\" {str(sample)}\")\n",
" print(f\" {\", \".join(new_samples)}\")\n",
" self._previous_samples = new_samples"
]
},
Expand Down Expand Up @@ -2749,8 +2792,8 @@
"metadata": {},
"outputs": [],
"source": [
"all_features = extract_existence(CALC_GRAMMAR) + extract_numeric(CALC_GRAMMAR)\n",
"all_feature_names = [f.name for f in all_features]"
"all_features = get_all_features(CALC_GRAMMAR)\n",
"all_feature_names = [f.friendly_name() for f in all_features]"
]
},
{
Expand Down

0 comments on commit 57e23a4

Please sign in to comment.