-
Notifications
You must be signed in to change notification settings - Fork 3
[Model] SubsetProduct #852
Description
Motivation
SUBSET PRODUCT (P141) from Garey & Johnson, A3 SP14. Given a finite set A of positive integers and a target product B, determine whether there exists a subset whose product equals B. NP-complete in the strong sense (unlike Subset Sum, which is only weakly NP-complete), because the multiplicative structure prevents pseudo-polynomial dynamic programming. NP-completeness is established by transformation from Exact Cover by 3-Sets (Yao, 1978).
Associated rules:
- [Rule] EXACT COVER BY 3-SETS to SUBSET PRODUCT #858 / [Rule] EXACT COVER BY 3-SETS to SUBSET PRODUCT #388: ExactCoverBy3Sets → SubsetProduct (classical NP-completeness proof from G&J)
Definition
Name: SubsetProduct
Reference: Garey & Johnson, Computers and Intractability, A3 SP14
Mathematical definition:
INSTANCE: Finite set A, a size s(a) ∈ Z^+ for each a ∈ A, and a positive integer B.
QUESTION: Is there a subset A' ⊆ A such that the product of the sizes of the elements in A' is exactly B?
Variables
- Count: |A| (number of elements in the set)
- Per-variable domain: {0, 1}
- Meaning: Whether each element a ∈ A is included in the subset A'.
Schema (data type)
Type name: SubsetProduct
Variants: None (single variant).
| Field | Type | Description |
|---|---|---|
sizes |
Vec<BigUint> |
The sizes s(a) for each element a ∈ A |
target |
BigUint |
The target product B |
Notes:
- This is a feasibility (decision) problem:
Value = Or. - Key getter methods:
num_elements()(= |A|). - Uses
BigUintbecause products grow exponentially fast — even modest-sized instances can exceedu64::MAX. Consistent with the existingSubsetSumimplementation.
Complexity
- Decision complexity: NP-complete in the strong sense (Yao, 1978; transformation from Exact Cover by 3-Sets). Unlike Subset Sum, no pseudo-polynomial dynamic programming algorithm exists unless P = NP.
- Best known exact algorithm: O*(2^(n/2)) via meet-in-the-middle — enumerate all subset products of each half, then search for complementary pairs where p1 * p2 = B. This generalizes the Horowitz-Sahni (1974) approach for Subset Sum to the multiplicative case.
- Concrete complexity expression:
"2^(0.5 * num_elements)"(fordeclare_variants!) - References:
- A.C. Yao (1978). "On the complexity of comparison problems using linear functions." In Proc. 10th Annual ACM Symposium on Theory of Computing (STOC), pp. 85-89.
- E. Horowitz, S. Sahni (1974). "Computing partitions with applications to the knapsack problem." J. ACM 21(2), pp. 277-292.
- M.R. Garey and D.S. Johnson (1979). Computers and Intractability. W.H. Freeman.
Extra Remark
Full book text:
INSTANCE: Finite set A, a size s(a) ∈ Z^+ for each a ∈ A, and a positive integer B.
QUESTION: Is there a subset A' ⊆ A such that the product of the sizes of the elements in A' is exactly B?
Reference: [Yao, 1978b]. Transformation from X3C.
Comment: NP-complete in the strong sense.
How to solve
- It can be solved by (existing) bruteforce. (Enumerate all 2^|A| subsets; compute the product of each and check against B.)
- It can be solved by reducing to integer programming.
- Other: Meet-in-the-middle in O*(2^(n/2)).
Example Instance
Input:
A = {a_1, ..., a_6} with sizes s = [2, 3, 5, 7, 6, 10], target product B = 210.
Valid subset: A' = {a_1, a_2, a_3, a_4} with sizes {2, 3, 5, 7}.
Product: 2 × 3 × 5 × 7 = 210 = B. ✓
Answer: YES.
Note: The solution is not unique — {3, 10, 7} gives 3 × 10 × 7 = 210, and {5, 6, 7} gives 5 × 6 × 7 = 210. There are 3 valid subsets out of 64 total.
Negative example:
Same elements s = [2, 3, 5, 7, 6, 10], target product B = 211.
Since 211 is prime and does not appear in the element set, no subset product can equal 211. (Any subset product is a product of elements from {2,3,5,6,7,10}, which factors only over primes {2,3,5,7}. Since 211 is prime and not in {2,3,5,7}, it cannot be achieved.)
Answer: NO.
Python validation script
from itertools import combinations
from math import prod
sizes = [2, 3, 5, 7, 6, 10]
# Positive: B = 210
valid_210 = []
for r in range(len(sizes)+1):
for combo in combinations(range(len(sizes)), r):
if prod(sizes[i] for i in combo) == 210:
valid_210.append([sizes[i] for i in combo])
assert len(valid_210) == 3
print(f"B=210: {len(valid_210)} valid subsets: {valid_210}")
# Negative: B = 211
valid_211 = []
for r in range(len(sizes)+1):
for combo in combinations(range(len(sizes)), r):
if prod(sizes[i] for i in combo) == 211:
valid_211.append([sizes[i] for i in combo])
assert len(valid_211) == 0
print(f"B=211: {len(valid_211)} valid subsets (correct: NO)")Metadata
Metadata
Assignees
Labels
Type
Projects
Status