首頁 >後端開發 >C++ >子集相等性是NP完全的

子集相等性是NP完全的

王林
王林轉載
2023-08-28 23:41:061456瀏覽

子集相等性是NP完全的

子集對應,也稱為「子集總計」問題,是示例性的 NP 完全計算問題。給定一堆數字和一個客觀價值,任務是確定是否存在其總數等於客觀價值的數字子集。這個問題的 NP 頂峰源於其透過多項式時間遞減來解決各種其他 NP 完全問題的能力。不管其簡單的定義如何,沒有一種有效的計算可以解決所有事件的“子集對應”,這使得它在假設的軟體工程和簡化中具有重要意義,並且在不同領域(如密碼學、資產分配和動態問題)具有功能應用。

使用的方法

  • 子集總和的減少

  • 從 3SAT 減少

從子集總和減少

處理「子集公平性」是 NP 完成問題的一種方法是顯示顯著的 NP 完成問題(「子集總數」問題)的減少。

演算法

  • 給定一個「子集聚合」問題的案例,它是一堆整數 S 和一個價值 T 的目標。

  • 使用類似的集合 S 和目標自尊 2T 來製作另一個「子集權益」問題的案例。

  • 如果在「子集聚合」問題中存在S 的子集匯總為T,那麼此時,「子集均勻性」問題中將存在一個匯總為T 的子集2T 透過添加與其自身相似的子集。

  • 假設在「子集總計」問題中不存在S 的子集匯總為T,那麼在「子集公平性」問題中也不存在匯總為2T 的子集,因為任何具有總計的子集低於2T的與其自身相加不能超過2T。

  • 這種下降表明解決「子集公平性」問題與解決「子集聚合」問題幾乎一樣困難,使其成為 NP 完全問題。

範例

#include <iostream>
#include <vector>
using namespace std;

bool isSubsetSum(vector<int>& set, int n, int sum) {
   if (sum == 0) return true;
   if (n == 0) return false;

   if (set[n - 1] > sum) return isSubsetSum(set, n - 1, sum);

   return isSubsetSum(set, n - 1, sum) || isSubsetSum(set, n - 1, sum - set[n - 1]);
}

bool isSubsetAggregateReduction(vector<int>& set, int n, int sum) {
   return !isSubsetSum(set, n, sum) && !isSubsetSum(set, n, 2 * sum);
}

int main() {
   vector<int> set = {3, 34, 4, 12, 5, 2};
   int sum = 18; 
   if (isSubsetAggregateReduction(set, set.size(), sum)) {
      cout << "No subset exists in Subset Aggregate issue that sums to " << sum << " and no subset exists that sums to " << 2 * sum << " by adding the same subset with itself." << endl;
   } else {
      cout << "There exists a subset in Subset Aggregate issue that sums to " << sum << " or a subset in Subset Equity issue that sums to " << 2 * sum << " by adding the same subset with itself." << endl;
   }

   return 0;
}

輸出

There exists a subset in Subset Aggregate issue that sums to 18 or a subset in Subset Equity issue that sums to 36 by adding the same subset with itself.

從 3SAT 減少

另一種方法是透過直接從一個已知的 NP 完全問題(例如 3SAT 問題)中減去它來證明「子集對應」是 NP 完成的。

演算法

  • 給出了 3SAT 問題的範例,其中包含一個聯合普通結構中的布林配方,每個條件有三個文字。

  • 用一堆整數和目標值再討論一下「子集均勻性」問題,如下:

  • a.對於 3SAT 方程中的每個變量,在集合中建立一個值為 1 的數字。

    b.對於 3SAT 方程中的每個附加條件,在集合中產生一個值為 2 的數字。

    c.將目標值設定為 3SAT 配方中的全部附加條件和所有因素的全部數量。

  • 如果 3SAT 方案可滿足,則「子集均勻性」問題中存在一個子集,該子集透過為每個已滿足的條件選擇一個變數來總結目標值。

  • 如果3SAT 配方無法滿足,那麼「子集對應」問題中就沒有子集可以概括為目標值,因為任何合法子集都必須包含不少於一個值為2 的整數,與已履行的條款相關。

  • 由於已知 3SAT 問題是 NP 完成的,因此這種下降表明「子集股權」的 NP 頂峰。

範例

#include <iostream>
#include <vector>
using namespace std;

bool ThreeSAT_Satisfiable(const vector<vector<int>>& clauses) {
   return false;
}

class SubsetUniformity {
private:
   vector<int> numbers;
   int targetValue;

public:
   SubsetUniformity(const vector<int>& vars, const vector<int>& clauses) {
      for (int v : vars) {
         numbers.push_back(1);
      }
      for (int c : clauses) {
         numbers.push_back(2);
      }
      targetValue = vars.size() + clauses.size();
   }

   bool isSubsetSumPossible(int idx, int sum) {
      if (sum == targetValue) {
         return true;
      }
      if (idx >= numbers.size() || sum > targetValue) {
         return false;
      }
      return isSubsetSumPossible(idx + 1, sum) || isSubsetSumPossible(idx + 1, sum + numbers[idx]);
   }

   bool hasSolution() {
      return isSubsetSumPossible(0, 0);
   }
};

int main() {
   vector<vector<int>> clauses = {
      {1, 2, -3},
      {-1, -2, 3},
      {-1, 2, 3}
   };

   bool isSatisfiable = ThreeSAT_Satisfiable(clauses);
   SubsetUniformity su(clauses[0], clauses[1]);

   cout << "3SAT Formula is " << (isSatisfiable ? "satisfiable." : "not satisfiable.") << endl;
   cout << "Subset Uniformity has " << (su.hasSolution() ? "a" : "no") << " solution." << endl;

   return 0;
}

輸出

3SAT Formula is not satisfiable.
Subset Uniformity has a solution.

結論

這兩種方法都表明「子集權益」或「子集聚合」問題是 NP 完成的,因此,追蹤有效的計算來解決所有範例的問題是不可能的。科學家經常利用動態規劃或其他估計程序來有效解決此問題的可行情況。

以上是子集相等性是NP完全的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:tutorialspoint.com。如有侵權,請聯絡admin@php.cn刪除