Generate random points satisfying linear constraints

553 Views Asked by At

In my problem, I have a vector x of len N. Where each element xi,j is the price of the product i in the country j. Let's say that I have 100 products and 20 countries, so N=100x20=2000.

The solution of X is subject to a set of linear constraints. For instance, minimum/maximum price for each product and maximum difference allowed for the same product between countries. Therefore, I can define the constraints as a matrix Ax<=b

I guess the problem would be like sampling points from a space bounded by hyperplanes defined by the constraints.

Assuming that the problem has multiple feasible solutions. How can I generate random points (solutions of the vector x) that satisfy the constraints? Or there is any library that could help me with that?

I tried with https://github.com/python-constraint/python-constraint, but it seems that because the number of solutions is very large, the algorithm gets stuck at some point or takes a long time to return the solution.

1

There are 1 best solutions below

1
gimix On

Maybe I'm missing something, or you simplified a bit too much your actual use case. But for the case as stated there's no need for Constraint Programming:

  • You have min_price, max_price, and max_diff for each product (I'm assuming max_diff <= max_price - min_price)
  • So the actual minimum price you can set will be anywhere between min_price and max_price - max_diff. Let's say you set it at random in that range
  • Accordingly the actual maximum price will be actual_min + max_diff
  • Now the price of that product for each country will simply be a value between actual_min and actual_max.

I implemented this in a 3-steps process: create (random) data for the product (you will skip this one); compute the actual min/max values; and finally assign the prices for each product/country. At about 1300 solutions per second on my old i5 windows notebook for 100 products and 20 countries, it is even not so slow as one could have expected

from dataclasses import dataclass
from random import choices, randint

@dataclass
class Product:
    min_price : int
    max_price : int
    max_diff : int
    actual_min : int = 0
    actual_max : int = 0

class Prices():
    def __init__(self, no_products, no_countries):
        self.products = {}
        for i in range(no_products):
            min_price = randint(100,200)
            max_price = min_price + randint(200,300)
            max_diff = randint(10,max_price - min_price)
            self.products[i] = Product(min_price, max_price, max_diff)
        self.countries = [c for c in range(no_countries)]
        self.prices = []

    def calc_actuals(self):
        for p in self.products.values():
            p.actual_min = randint(p.min_price, p.max_price - p.max_diff)
            p.actual_max = p.actual_min + p.max_diff

    def calc_prices(self):
        self.prices = []
        for p in self.products.values():
            self.prices.append([*choices(range(p.actual_min, p.actual_max+1),k=len(self.countries))])