Skip to content

[Model] SubsetProduct #852

@isPANN

Description

@isPANN

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:

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 BigUint because products grow exponentially fast — even modest-sized instances can exceed u64::MAX. Consistent with the existing SubsetSum implementation.

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)" (for declare_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

No one assigned

    Labels

    GoodAn issue passed all checks.modelA model problem to be implemented.

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions