10b57cec5SDimitry Andric //===- DeltaAlgorithm.h - A Set Minimization Algorithm ---------*- C++ -*--===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 70b57cec5SDimitry Andric 80b57cec5SDimitry Andric #ifndef LLVM_ADT_DELTAALGORITHM_H 90b57cec5SDimitry Andric #define LLVM_ADT_DELTAALGORITHM_H 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include <set> 120b57cec5SDimitry Andric #include <vector> 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric namespace llvm { 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric /// DeltaAlgorithm - Implements the delta debugging algorithm (A. Zeller '99) 170b57cec5SDimitry Andric /// for minimizing arbitrary sets using a predicate function. 180b57cec5SDimitry Andric /// 190b57cec5SDimitry Andric /// The result of the algorithm is a subset of the input change set which is 200b57cec5SDimitry Andric /// guaranteed to satisfy the predicate, assuming that the input set did. For 210b57cec5SDimitry Andric /// well formed predicates, the result set is guaranteed to be such that 220b57cec5SDimitry Andric /// removing any single element would falsify the predicate. 230b57cec5SDimitry Andric /// 240b57cec5SDimitry Andric /// For best results the predicate function *should* (but need not) satisfy 250b57cec5SDimitry Andric /// certain properties, in particular: 260b57cec5SDimitry Andric /// (1) The predicate should return false on an empty set and true on the full 270b57cec5SDimitry Andric /// set. 280b57cec5SDimitry Andric /// (2) If the predicate returns true for a set of changes, it should return 290b57cec5SDimitry Andric /// true for all supersets of that set. 300b57cec5SDimitry Andric /// 310b57cec5SDimitry Andric /// It is not an error to provide a predicate that does not satisfy these 320b57cec5SDimitry Andric /// requirements, and the algorithm will generally produce reasonable 330b57cec5SDimitry Andric /// results. However, it may run substantially more tests than with a good 340b57cec5SDimitry Andric /// predicate. 350b57cec5SDimitry Andric class DeltaAlgorithm { 360b57cec5SDimitry Andric public: 370b57cec5SDimitry Andric using change_ty = unsigned; 380b57cec5SDimitry Andric // FIXME: Use a decent data structure. 390b57cec5SDimitry Andric using changeset_ty = std::set<change_ty>; 400b57cec5SDimitry Andric using changesetlist_ty = std::vector<changeset_ty>; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric private: 430b57cec5SDimitry Andric /// Cache of failed test results. Successful test results are never cached 440b57cec5SDimitry Andric /// since we always reduce following a success. 450b57cec5SDimitry Andric std::set<changeset_ty> FailedTestsCache; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric /// GetTestResult - Get the test result for the \p Changes from the 480b57cec5SDimitry Andric /// cache, executing the test if necessary. 490b57cec5SDimitry Andric /// 500b57cec5SDimitry Andric /// \param Changes - The change set to test. 510b57cec5SDimitry Andric /// \return - The test result. 520b57cec5SDimitry Andric bool GetTestResult(const changeset_ty &Changes); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric /// Split - Partition a set of changes \p S into one or two subsets. 550b57cec5SDimitry Andric void Split(const changeset_ty &S, changesetlist_ty &Res); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// Delta - Minimize a set of \p Changes which has been partitioned into 580b57cec5SDimitry Andric /// smaller sets, by attempting to remove individual subsets. 590b57cec5SDimitry Andric changeset_ty Delta(const changeset_ty &Changes, 600b57cec5SDimitry Andric const changesetlist_ty &Sets); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Search - Search for a subset (or subsets) in \p Sets which can be 630b57cec5SDimitry Andric /// removed from \p Changes while still satisfying the predicate. 640b57cec5SDimitry Andric /// 650b57cec5SDimitry Andric /// \param Res - On success, a subset of Changes which satisfies the 660b57cec5SDimitry Andric /// predicate. 670b57cec5SDimitry Andric /// \return - True on success. 680b57cec5SDimitry Andric bool Search(const changeset_ty &Changes, const changesetlist_ty &Sets, 690b57cec5SDimitry Andric changeset_ty &Res); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric protected: 720b57cec5SDimitry Andric /// UpdatedSearchState - Callback used when the search state changes. UpdatedSearchState(const changeset_ty & Changes,const changesetlist_ty & Sets)730b57cec5SDimitry Andric virtual void UpdatedSearchState(const changeset_ty &Changes, 740b57cec5SDimitry Andric const changesetlist_ty &Sets) {} 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric /// ExecuteOneTest - Execute a single test predicate on the change set \p S. 770b57cec5SDimitry Andric virtual bool ExecuteOneTest(const changeset_ty &S) = 0; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric public: 820b57cec5SDimitry Andric virtual ~DeltaAlgorithm(); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /// Run - Minimize the set \p Changes by executing \see ExecuteOneTest() on 850b57cec5SDimitry Andric /// subsets of changes and returning the smallest set which still satisfies 860b57cec5SDimitry Andric /// the test predicate. 870b57cec5SDimitry Andric changeset_ty Run(const changeset_ty &Changes); 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric } // end namespace llvm 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric #endif // LLVM_ADT_DELTAALGORITHM_H 93