-
Notifications
You must be signed in to change notification settings - Fork 45
ML path selector #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
ML path selector #99
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
744418a
Buildable
a30845e
Fix style
498dc30
Fix some issues
b92813a
Add jvmArgs for framework tests
f584c83
Try to fix CI
f4811e9
Try to fix CI
6d007e7
Try to fix CI
90b580e
Try to fix CI
2c971f5
Try to fix CI
daa16b5
Try to fix CI
9382479
Try to fix CI
1429636
Try to fix CI
7e99470
Try to fix CI
3fc97d3
Try to fix CI
550ddcd
Try to fix CI
89c9d24
Revert non-path-selector changes
a293239
Revert non-path-selector changes
d26c13c
Try to fix CI
c908853
Try to fix CI
79360aa
Revert "Try to fix CI"
2e415b6
Revert "Try to fix CI"
9e063d7
Make parent optional
6c15857
Add docs
58087e7
Add versions in properties
36b8a6f
Fix issues
01ea455
Revert engine style
05c22ae
Fix spelling
02b5c17
Add predictor
97b0813
Fix issues
d6d0593
Add comments
c042024
Handle exceptional situations
088a5c9
Split methods and add comment
7258e33
Add parsing tests
7d61792
Fix issues
dc03799
Fix issues
bec49b0
Change predictor in ContestEstimator
93f93ec
Fix tests
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Changes in Execution State | ||
|
Atos1337 marked this conversation as resolved.
|
||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class StateAnalyticsProperties{ | ||
| +int depth | ||
| +int visitedAfterLastFork | ||
| +int visitedBeforeLastFork | ||
| +int stmtsSinceLastCovered | ||
| +ExecutionState? parent | ||
| +long executingTime | ||
| +double reward | ||
| +List~Double~ features | ||
| -boolean isFork | ||
| -boolean isVisitedNew | ||
| -int successorDepth | ||
| -int successorVisitedAfterLastFork | ||
| -int successorVisitedBeforeLastFork | ||
| -int successorStmtSinceLastCovered | ||
|
|
||
| +updateIsVisitedNew() | ||
| +updateIsFork() | ||
| } | ||
| ExecutionState o-- StateAnalyticsProperties | ||
| ``` | ||
|
|
||
| `StateAnalyticsProperties` maintains properties of `ExecutionState`, which don't need for symbolic execution, but need for `JLearch`. | ||
|
|
||
| * `depth: Int` - number of forks on the state's path excluded current state, if it is fork. In this case, fork is a state with more than one successor excluded implicit `NPE` branches. | ||
| * `visitedAfterLastFork: Int` - number of `stmt`, that was visited by `states` on this state's path after the last fork in first time. | ||
| * `visitedBeforeLastFork: Int` - number of `stmt`, that was visited by `states` on this state's path before the last fork in first time. | ||
| * `stmtsSinceLastCovered: Int` - number of `states` on this state's path after the last state that visited any `stmt` in first time. | ||
| * `parent: ExecutionState?` - parent of current `state`. If `UtSettings.featureProcess == false`, then it is always null, because we don't need this field in this case. If it is not null, then we can't delete `state` until all successors of this state will be deleted, which may cause memory issue. | ||
| * `executingTime: Long` - amount of time, during which this state was traversed. | ||
| * `reward: Double?` - calculated reward of this state | ||
| * `features: List<Double>` - list of extracted features for this state | ||
|
|
||
| Field with `successor` prefix is used for a constructor of successor properties. | ||
|
|
||
| * `updateIsFork()` - set `isFork` on true. This method is called when traversing of `stmt` produces more than one explicit state. Now it may be during the traversing of `IfStmt`, `SwitchStmt`, `AssignStmt` or `InvokeStmt`. | ||
| * `updateIsCoveredNew()` - set `isVisitedNew` on true, set `stmtsSinceLastCovered` on zero and increase `visitedAfterLastFork` on 1. This method is called in `UtBotSymbolicEngine` after new state `s` is polled and `s.stmt` was not visited yet. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Collecting features | ||
|
|
||
| Now we collect 13 features, that will be described in original [paper](https://files.sri.inf.ethz.ch/website/papers/ccs21-learch.pdf), except constraint representation, but it can be extended. | ||
|
|
||
| * `stack` - size of state’s current call stack. | ||
| * `successor` - number of successors of state’s current basic block. | ||
| * `testCase` - number of test cases generated so far | ||
| * `coverageByBranch` - number of instructions, which was covered first time on our last branch | ||
| * `coverageByPath` - number of instructions, which was covered first time on our path | ||
| * `depth` - number of forks already performed along state’s path. | ||
| * `cpicnt` - number of instructions visited in state's current function. | ||
| * `icnt` - number of times for which st ate’s current instruction has | ||
| been visited | ||
| * `covNew` - number of instructions executed by st ate since the last | ||
| time a new instruction is covered | ||
| * `subpath` - number of times for which st ate’s subpaths have been | ||
| visited. The length of the subpaths can be 1, 2, 4, or 8 respectively |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| # JLearch architecture | ||
|
|
||
| # Global Class Diagram | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class FeatureProcessor{ | ||
| dumpFeatures() | ||
| } | ||
| <<interface>> FeatureProcessor | ||
| class TraverseGraphStatistics{ | ||
| onVisit(ExecutionState) | ||
| onTraversed(ExecutionState) | ||
| } | ||
| class InterproceduralUnitGraph | ||
| class FeatureExtractorFactory | ||
| <<interface>> FeatureExtractorFactory | ||
| class FeatureProcessorFactory | ||
| <<interface>> FeatureProcessorFactory | ||
| class EngineAnalyticsContext | ||
| class UtBotSymbolicEngine | ||
| class NNRewardGuidedSelectorFactory | ||
| <<interface>> NNRewardGuidedSelectorFactory | ||
| class FeatureExtractor{ | ||
| extractFeatures(ExecutionState) | ||
| } | ||
| <<interface>> FeatureExtractor | ||
|
|
||
| UtBotSymbolicEngine ..> EngineAnalyticsContext | ||
| EngineAnalyticsContext o-- FeatureProcessorFactory | ||
| EngineAnalyticsContext o-- FeatureExtractorFactory | ||
| EngineAnalyticsContext o-- NNRewardGuidedSelectorFactory | ||
|
|
||
| FeatureProcessor --|> TraverseGraphStatistics | ||
| InterproceduralUnitGraph o-- TraverseGraphStatistics | ||
| UtBotSymbolicEngine *-- FeatureProcessor | ||
| UtBotSymbolicEngine *-- InterproceduralUnitGraph | ||
|
|
||
| class Predictors | ||
| class NNStateRewardPredictor | ||
| class NNRewardGuidedSelector | ||
|
|
||
|
|
||
| class GreedySearch | ||
|
|
||
| class BasePathSelector | ||
|
|
||
| GreedySearch --|> BasePathSelector | ||
| NNRewardGuidedSelector --|> GreedySearch | ||
|
|
||
| UtBotSymbolicEngine *-- BasePathSelector | ||
|
|
||
| Predictors o-- NNStateRewardPredictor | ||
| NNRewardGuidedSelector ..> Predictors | ||
| NNRewardGuidedSelector *-- FeatureExtractor | ||
|
|
||
| NNStateRewardPredictorSmile --|> NNStateRewardPredictor | ||
| NNStateRewardPredictorTorch --|> NNStateRewardPredictor | ||
|
|
||
| NNStateRewardGuidedSelectorWithRecalculationWeight --|> NNRewardGuidedSelector | ||
| NNStateRewardGuidedSelectorWithoutRecalculationWeight --|> NNRewardGuidedSelector | ||
| ``` | ||
|
|
||
| This diagram doesn't illustrate some details, so read them below. | ||
|
|
||
| # FeatureProcessor | ||
|
|
||
| It is interface in framework-module, that allows to use implementation from analytics module. | ||
|
|
||
| * `dumpFeatures(state: ExecutionState)` - dump features and rewards in some format on disk. Called at the end of traverse in `UtBotSymbolicEngine` | ||
|
|
||
| ## Implementation class diagram | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class FeatureProcessorWithStatesRepetition{ | ||
| -Map~Int, FeatureList~ dumpedStates | ||
| -Set~Stmt~ visitedStmts | ||
| -List~TestCase~ testCases | ||
| -int generatedTestCases | ||
| dumpFeatures() | ||
| } | ||
|
|
||
| class FeatureExtractor{ | ||
| extractFeatures(ExecutionState) | ||
| } | ||
|
|
||
| class TraverseGraphStatistics{ | ||
| onVisit(ExecutionState) | ||
| onTraversed(ExecutionState) | ||
| } | ||
|
|
||
| class RewardEstimator{ | ||
| calculateRewards(List~TestCase~) | ||
| } | ||
|
|
||
| class TestCase{ | ||
| +List<State> states | ||
| +int newCoverage | ||
| +int testIndex | ||
| } | ||
|
|
||
| FeatureProcessorWithStatesRepetition --|> TraverseGraphStatistics | ||
| FeatureProcessorWithStatesRepetition o-- FeatureExtractor | ||
| FeatureProcessorWithStatesRepetition o-- RewardEstimator | ||
| FeatureProcessorWithStatesRepetition ..> EngineAnalyticsContext | ||
|
|
||
| ``` | ||
|
|
||
| `State = Pair<Int, Long>` | ||
|
|
||
| `FeatureList = List<Double` | ||
|
|
||
| ## RewardEstimator | ||
|
|
||
| Maintains calculation of reward. | ||
|
|
||
| * `calculateRewards(List<TestCase>): Map<Int, Double>` - calculates `coverage` for each state and `time` for each state. `Coverage` - sum of `newCoverage` by `TestCase` that contains its state. `Time` - sum of `state.executingTime` by all states, that has this state on its path. Then calculates `reward(coverage, time)`. | ||
|
|
||
| ## FeatureProcessorWithStatesRepetition | ||
|
|
||
| * `onVisit(state: ExecutionState)` - extractFeatures for state | ||
| * `onTraversed(state: ExecutionState)` - create `TestCase`, so we go from `state` to `state.parent` while it is not root, for each `state` on path add its features to `dumpedStates`, calculate coverage of its `TestCase`, increment `generatedTestCases` on 1 and add new `TestCase` in `testCases`. | ||
| * `dumpFeatures()` - call `RewardEstimator.calculateRewards()` and write `csv` file for each `TestCase` in format: `newCov,features,reward` for each `state` in it. `newCov` - flag that indicates whether this `TestCase` cover something new or not. So in this approach, each `state` will be written as many times as the number of `TestCase` that has it. | ||
| For creating `FeatureExtractor`, it uses `FeatureExtractorFactory` from `EngineAnalyticsContext`. | ||
|
|
||
| # FeatureExtractor | ||
|
|
||
| It is interface in framework-module, that allows to use implementation from analytics module. | ||
| * `extractFeatures(state: ExecutionState)` - create features list for state and store it in `state.features`. Now we extract all features, which were described in [paper](https://files.sri.inf.ethz.ch/website/papers/ccs21-learch.pdf). In feature, we can extend the feature list by other features, for example, NeuroSMT. | ||
|
|
||
| # NNStateRewardPredictor | ||
|
|
||
| Interface for reward predictors. Now it has two implementations in `analytics` module: | ||
|
|
||
| * `NNStateRewardPredictorSmile`: it uses our own format to store feedforward neural network, and it uses `Smile` library to do multiplication of matrix. | ||
| * `NNStateRewardPredictorTorch`: it assumed that a model is any type of model in `pt` format. It uses the `Deep Java library` to use such models. | ||
|
|
||
| It should be created at the beginning of work and stored at `Predictors` class to be used in `NNRewardGuidedSelector` from the `framework` module. | ||
|
|
||
|
|
||
| # NNStateRewardGuidedSelector | ||
|
|
||
| It uses an `EngineAnalyticsContext` to create `FeatureExtractor`. | ||
| We override `ExecutionState.weight` as `NNStateRewardPredictor.predict(this.features)`. | ||
| We have two different implementantions: | ||
| * `NNStateRewardGuidedSelectorWithRecalculation`: we recalculate reward every time, so in `ExecutionState.weight` we extract features and call predict. | ||
| * `NNStateRewardGuidedSlectorWithoutRecalculation`: we extract features in `offerImpl`, calculate `reward` and store it in `ExecutionState.reward` without recalculation it every time. | ||
|
|
||
| # EngineAnalyticsContext | ||
|
|
||
| It is an object that should be filled by factories in the beginning of work to allow objects from the `framework` module using objects from `analytics` module. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| # GreedySearch | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class GreedySearch{ | ||
| -Set~ExecutionState~ states | ||
| +ExecutionState.weight | ||
| } | ||
| GreedySearch --|> BasePathSelector | ||
| ``` | ||
| Base methods such as `offer` or `remove` is implemented pretty simple and just a delegation to `states`. | ||
|
|
||
| In `peekImpl` we find the set of `states` with maximum `weight` and peek random among them, so to use this class in implementation of some `pathSelector`, you just need to override an `ExecutionState.weight`. | ||
|
|
||
| # SubpathStatistics | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class SubpathStatistics{ | ||
| +int index | ||
| -Map~Subpath, Int~ subpathCount | ||
| subpathCount(ExecutionState) | ||
| } | ||
| class TraverseGraphStatistics{ | ||
| onVisit(ExecutionState) | ||
| } | ||
|
|
||
| SubpathStatistics --|> TraverseGraphStatistics | ||
| TraverseGraphStatistics o-- InterProceduralUnitGraph | ||
| ``` | ||
| `Subpath` = `List<Edge>` | ||
|
|
||
| This class maintains frequency of each subpath with length `2^index`, which is presented as `List<Edge>`, in a certain instance of `InterproceduralUnitGraph` | ||
|
|
||
| * `onVisit(state: ExecutionState)` - we calculate subpath of this state and increment its frequency on `1` | ||
| * `subpathCount(state: ExecutionState)` - we calculate subpath of this state and return its frequency | ||
|
|
||
| # SubpathGuidedSelector | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| SubpathGuidedSelector o-- SubpathStatistics | ||
| SubpathGuidedSelector --|> GreedySearch | ||
| ``` | ||
|
|
||
| Inspired by [paper](http://pxzhang.cn/paper/concolic_testing/oopsla13-pgse.pdf). | ||
|
|
||
| We override `ExecutionState.weight` as `-StatementStatistics.subpathCount(this)`, so we pick the `state`, which `subpath` is less traveled. | ||
|
|
||
| # StatementStatistics | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| class StatementStatistics{ | ||
| -Map~Stmt, Int~ statementsCount | ||
| -Map~SootMethod, Int~ statementsInMethodCount | ||
| +statementCount(ExecutionState) | ||
| +statementsInMethodCount(ExecutionState) | ||
| } | ||
|
|
||
| class TraverseGraphStatistics{ | ||
| onVisit(ExecutionState) | ||
| } | ||
|
|
||
| StatementStatistics --|> TraverseGraphStatistics | ||
| TraverseGraphStatistics o-- InterProceduralUnitGraph | ||
| ``` | ||
|
|
||
| This class maintains frequency of each `Stmt` and number of `Stmt`, that was visited in some `SootMethod`, on a certain instance of `InterproceduralUnitGraph`. | ||
|
|
||
| * `onVisit(state: ExecutionState)` - increment frequency of state's `stmt` on 1. If we visit this `stmt` for the first time, then increment number of `Stmt`, that we visit in the current state's `method`, on 1. | ||
| * `statementCount(state: ExecutionState)` - get a frequency of state's `stmt` | ||
| * `statementsInMethodCount(state: ExecutionState)` - get number of `stmt`, that was visited in the current state's `method`. | ||
|
|
||
| # CPInstSelector | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| CPInstSelector o-- StatementStatistics | ||
| CPInstSelector --|> NonUniformRandomSearch | ||
| ``` | ||
|
|
||
| Override `ExecutionState.cost` as `StatementStatistics.statementInMethodCount(this)`, so we are more likely to explore the least explored `method`. | ||
|
|
||
| # ForkDepthSelector | ||
|
|
||
| ```mermaid | ||
| classDiagram | ||
| ForkDepthSelector --|> NonUniformRandomSearch | ||
| ``` | ||
|
|
||
| Override `ExecutionState.cost` as `ExecutionState.depth`, so we are more likely to explore the least deep `state` in terms of the number of forks on its path. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
utbot-analytics/src/main/kotlin/org/utbot/features/FeatureExtractorFactoryImpl.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package org.utbot.features | ||
|
|
||
| import org.utbot.analytics.FeatureExtractor | ||
| import org.utbot.analytics.FeatureExtractorFactory | ||
| import org.utbot.engine.InterProceduralUnitGraph | ||
|
|
||
| /** | ||
| * Implementation of feature extractor factory | ||
| */ | ||
| class FeatureExtractorFactoryImpl : FeatureExtractorFactory { | ||
| override operator fun invoke(graph: InterProceduralUnitGraph): FeatureExtractor = FeatureExtractorImpl(graph) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.