ক্ষেত্রের ভিত্তিতে অবজেক্টের বৃহত তালিকার সর্বাধিক দক্ষ সংমিশ্রণ পান


9

আমি একটি নির্দিষ্ট বাজেট এবং সংমিশ্রণের সর্বাধিক সীমা প্রদত্ত তারার সংখ্যা সর্বাধিক করতে দেখছি।

উদাহরণ প্রশ্ন:

500 ইউরোর বাজেট সহ, কেবলমাত্র সর্বাধিক অনুমোদিত অনুমোদিত রেস্তোরাঁ বা তার চেয়ে কম পরিদর্শন করা, সর্বাধিক নক্ষত্রের খাবার এবং সংগ্রহ করা।

আমি একটি দক্ষ অ্যালগরিদম লিখতে চাই, এটি সম্ভাব্য 10 মিলিয়ন রেস্তোঁরাগুলির জন্য 1 মিলিয়ন রেস্তোঁরাগুলির উদাহরণগুলি প্রক্রিয়া করতে পারে।

দ্রষ্টব্য, আমি গতকাল যে প্রশ্নটি জিজ্ঞাসা করেছি তার একটি ক্রস পোস্ট এটি: জাভা: একটি ক্ষেত্রের উপর ভিত্তি করে অবজেক্টের একটি বৃহত তালিকার সর্বাধিক দক্ষ সংমিশ্রণ পান

নীচের সমাধানটি r8রেস্তোঁরাগুলিতে প্রতি তারা 15 ডলার অর্পণ করবে , যার অর্থ তালিকা তৈরি করার সময় এটি প্রথমে তালিকায় রাখে এবং বাকী 70 with এর সাথে এটি আরও 2 টি তারা পেতে পারে মোট 4 তারা দেয়। তবে, যদি r8রেস্তোঁরাটি এড়ানো যথেষ্ট স্মার্ট হয় (যদিও এটি তারকা অনুপাতের তুলনায় সেরা ডলার) r1রেস্তোঁরাটি বাজেটের জন্য আসলে আরও ভাল পছন্দ হবে, কারণ এটি 100 $ ব্যয় এবং 5 তারা stars

সমস্যার সমাধান এবং বর্তমান সমাধানকে কেউ মারতে পারে?

import itertools

class Restaurant():
  def __init__(self, cost, stars):
    self.cost = cost
    self.stars = stars
    self.ratio = cost / stars

  def display(self):
    print("Cost: $" + str(self.cost))
    print("Stars: " + str(self.stars))
    print()

r1 = Restaurant(100, 5)
r2 = Restaurant(140, 3)
r3 = Restaurant(90, 4)
r4 = Restaurant(140, 3)
r5 = Restaurant(120, 4)
r6 = Restaurant(60, 1)
r7 = Restaurant(40, 1)
r8 = Restaurant(30, 2)
r9 = Restaurant(70, 2)
r10 = Restaurant(250, 5)

print()
print("***************")
print("** Unsorted: **")
print("***************")
print()

restaurants = [r1, r2, r3, r4, r5, r6, r7, r8, r9, r10]

for restaurant in restaurants:
  print(restaurant.ratio, restaurant.stars)

print()
print("***************")
print("**  Sorted:  **")
print("***************")
print()

sorted_restaurants = sorted(restaurants, key = lambda x: x.ratio, reverse = True)

for restaurant in sorted_restaurants:
  print(restaurant.ratio, restaurant.stars)

print()
print("*********************")
print("** Begin Rucksack: **")
print("*********************")
print()

max = 5
budget = 100

spent = 0
quantity = 0

rucksack = []

for i in itertools.count():

  if len(rucksack) >= max or i == len(sorted_restaurants):
    break

  sorted_restaurants[i].display()

  if sorted_restaurants[i].cost + spent <= budget:
    spent = spent + sorted_restaurants[i].cost
    rucksack.append(sorted_restaurants[i])

print("Total Cost: $" + str(sum([x.cost for x in rucksack])))
print("Total Stars: " + str(sum([x.stars for x in rucksack])))

print()
print("*****************")
print("** Final List: **")
print("*****************")
print()

for restaurant in rucksack:
  restaurant.display()

2
এই ন্যাপস্যাক? আমাকে ক্ষমা করুন, আমি লাঞ্ছিত।
কেনি অস্ট্রোম

1
এটি ন্যাপস্যাকের একই ধারণা - budget= সর্বোচ্চ রুকস্যাক ওজন কেজি, maxন্যাপস্যাকটি ধরে রাখতে পারে starsএমন আইটেমের সংখ্যা cost= আইটেমের কিছু মূল্য এবং কেজি আইটেমের ওজন
47

3
এবং পোস্ট করা কোড নিয়ে সমস্যা কী?
ক্রিকেট_007

1
আদেশের ভিত্তিতে @ ক্রিকেট_007, এটি r8রেস্তোঁরাগুলিতে প্রতি তারা 15% নির্ধারণ করে , যার অর্থ তালিকাটি তৈরি করার সময়, এটি প্রথমে তালিকায় রাখে এবং বাকী 70 with এর সাথে এটি আরও 2 টি তারা পেতে পারে। যাইহোক, যদি এটি এড়াতে যথেষ্ট স্মার্ট হয় (যদিও এটি তারকা অনুপাতের তুলনায় সেরা ডলার, r1রেস্তোঁরাটি বাজেটের জন্য আসলে আরও ভাল পছন্দ হবে, কারণ এটি 100 $ ব্যয় এবং 5 তারা
47

উত্তর:


5

আপনার সমস্যার মতো সাউন্ডটি ন্যাপস্যাক সমস্যার মতো প্রায় একই রকম: নির্দিষ্ট ওজন এবং ভলিউমের সীমাবদ্ধতায় মান বাড়িয়ে তোলা। মূলত মান = মোট তারা, ওজন = দাম, রুকস্যাক সীমা = মোট বাজেট। এখন মোট "আইটেম" (রেস্তোঁরা ভিজিট) এর অতিরিক্ত বাধা রয়েছে তবে তা মুষ্টির পরিবর্তন করে না।

আপনি যেমন জানেন বা নাও জানেন, ন্যাপস্যাক সমস্যাটি এনপি হার্ড, যার অর্থ বহুপদী সময় স্কেলিং সহ কোনও অ্যালগরিদম জানা যায় না।

তবে, ডায়নামিক প্রোগ্রামিং ব্যবহার করে দক্ষ সিউডোপলিনোমিয়াল অ্যালগরিদম থাকতে পারে এবং অবশ্যই দক্ষ হুরিস্টিকস যেমন "লোভী" হিউরিস্টিক যেমন আপনি আবিষ্কার করেছেন বলে মনে হয়। এই হিউরিস্টিকের মধ্যে প্রথমে সর্বাধিক "ঘনত্ব" আইটেম (বাক্সে বেশিরভাগ তারকা) পূরণ করা শুরু হয়। যেমনটি আপনি দেখেছেন, এই ধর্মতাত্ত্বিক কিছু ক্ষেত্রে প্রকৃত সর্বোত্তম খুঁজে পেতে ব্যর্থ।

গতিশীল প্রোগ্রামিং পদ্ধতির এখানে বেশ ভাল হওয়া উচিত। এটি একটি পুনরাবৃত্তির উপর ভিত্তি করে: একটি বাজেট বি এবং বাকি অনেকগুলি ভি ভি দেওয়া হয়েছে, মোট রেস্তোঁরা আর এর মোট সেটগুলির মধ্যে পরিদর্শন করার জন্য রেস্তোঁরাগুলির সেরা সেটটি কী?

এখানে দেখুন: https://en.wikedia.org/wiki/Knapsack_problem#0/1_knapsack_problem

মূলত আমরা m"সর্বাধিক তারকাদের" জন্য একটি অ্যারের সংজ্ঞা দিই , m[i, b, v]যখন আমাদের রেস্তোঁরা নম্বর (এবং অন্তর্ভুক্ত) পর্যন্ত রেস্তোঁরা পরিদর্শন করার অনুমতি দেওয়া হয় i, সর্বাধিক ব্যয় করা হয় bএবং বেশিরভাগ vরেস্তোঁরাগুলিতে (সীমা) পরিদর্শন করার অনুমতি দেওয়া হয় তখন আমরা সর্বোচ্চ পরিমাণে তারকারা পেতে পারি ।

এখন, আমরা নীচে আপ এই অ্যারে পূরণ করুন। উদাহরণস্বরূপ, m[0, b, v] = 0সমস্ত মানগুলির জন্য bএবং vকারণ যদি আমরা কোনও রেস্তোঁরায় যেতে না পারি তবে আমরা কোনও তারা পেতে পারি না।

এছাড়াও, m[i, b, 0] = 0সমস্ত মানগুলির জন্য iএবং bকারণ যদি আমরা আমাদের সমস্ত দর্শন ব্যবহার করি তবে আমরা আর কোনও তারা পেতে পারি না।

পরের লাইনটি খুব শক্ত নয়:

m[i, b, v] = m[i - 1, b, v] if p[i] > bp[i]রেস্তোঁরায় খাবারের দাম কোথায় i? এই লাইনটি কী বলে? ঠিক আছে, রেস্তোঁরা যদি iআমাদের কাছে টাকা বেশি থাকে ( b) বেশি ব্যয়বহুল হয় তবে আমরা সেখানে যেতে পারি না। যার অর্থ আমরা সর্বোচ্চ পরিমাণে তারা পেতে পারি তা আমরা একইভাবে রেস্তোঁরাগুলিতে অন্তর্ভুক্ত থাকি iবা না আপ পর্যন্ত সমান i - 1

পরবর্তী লাইনটি কিছুটা জটিল:

m[i, b, v] = max(m[i-1, b, v]), m[i-1, b - p[i], v-1] + s[i]) if p[i] <= b

ইসস। s[i]রেস্তোঁরা iবিটিডব্লিউ থেকে প্রাপ্ত তারার পরিমাণ ।

এই লাইনটি কী বলে? এটি গতিশীল প্রোগ্রামিং পদ্ধতির প্রাণকেন্দ্র। রেস্তোঁরাগুলি পর্যন্ত সন্ধান এবং অন্তর্ভুক্ত করার সময় আমরা যে সর্বাধিক পরিমাণে তারা পেতে পারি তা বিবেচনা করার iপরে, তারপরে সমাধানের সমাধানের ফলে আমরা হয় সেখানে যাই বা আমরা না থাকি এবং এই "দুটি পথের মধ্যে কোনটি আরও বেশি দিকে নিয়ে যায়" আমাদের কেবল "ঠিক" দেখতে হবে তারা,

যদি আমরা রেস্তোঁরায় না যাই i, তবে আমরা একই পরিমাণ অর্থ এবং অবশিষ্ট ভিজিট রাখি। এই পথে আমরা যে পরিমাণ সর্বোচ্চ তারা পেতে পারি তা হ'ল আমরা এমনকি রেস্তোঁরাটির দিকে তাকাইনি i। এটি প্রথম অংশ max

তবে আমরা যদি রেস্তোঁরায় যাই i, তবে আমাদের p[i]কম অর্থ, একটি কম ভিজিট এবং s[i]আরও বেশি তারা রেখে গেছে। এটি দ্বিতীয় অংশ max

এখন প্রশ্নটি সহজ: দুজনের মধ্যে কোনটি বড়।

আপনি এই অ্যারেটি তৈরি করতে এবং লুপের জন্য তুলনামূলকভাবে সহজ (উইকির কাছ থেকে অনুপ্রেরণা নিতে পারেন) দিয়ে এটি পূরণ করতে পারেন। এটি কেবলমাত্র আপনাকে তারার পরিমাণ দেয়, দেখার জন্য রেস্তোঁরাগুলির আসল তালিকা নয়। তার জন্য, গণনাতে কিছু অতিরিক্ত বুককিপিং যুক্ত করুন w


আমি আশা করি যে তথ্য আপনাকে সঠিক দিকে চালিত করার জন্য যথেষ্ট।

বিকল্পভাবে, আপনি বাইনারি ভেরিয়েবল এবং একটি চতুর্ভুজ উদ্দেশ্যমূলক ফাংশনের ক্ষেত্রে আপনার সমস্যাটি লিখতে পারেন এবং এটি ডি-ওয়েভ কোয়ান্টাম অ্যানিলিয়ারে সমাধান করতে পারেন :-p আপনি যদি এই বিষয়ে আরও জানতে চান তবে আমাকে বার্তা দিন।


বহুবর্ষের সময় সম্পর্কে, সর্বোচ্চ 10 টি রেস্তোরাঁর অর্থ হ'ল ও (এন ^ 10) সময়ে 10 টির মতো রেস্তোরাঁয় সমস্ত সংমিশ্রণ ঘটাতে এবং সেরাটিকে ধরে রেখে ব্রুট ফোর্স দ্বারা সমস্যার সমাধান করা যেতে পারে। এখন, আমি n = 10 ^ 6 এর সাথে কোনও ও (এন ^ 10) অ্যালগরিদম চালাতে চাই না তবে এটি বহু-কালীন সময়।
কেয়া 3

"10 রেস্তোঁরাগুলি" কি সত্যই নির্দিষ্ট সংখ্যক সংখ্যা, বা উপরের উদাহরণে স্রেফ ফিক্সড, এবং আলাদা উদাহরণের জন্য আরও বড় হতে পারে?
লেজারবেয়ার

এটি একটি ভাল প্রশ্ন এবং চলমান সময় বিশ্লেষণ করার সময় সমস্যার কোন পরামিতিগুলি সাধারণ করা হবে তা পরিষ্কার নয়। অবশ্যই, কে-তে বহুপক্ষীয় কোনও জ্ঞাত সমাধান নেই, আমি কেবলমাত্র এটি বোঝাতে চাইছি এটি একটি দুর্বল উপসংহার যদি আমরা কেবল ছোট কে এর জন্য সমস্যাটিতে আগ্রহী।
কেয়া

রেস্তোঁরাগুলির "সর্বাধিক" সংখ্যা পরিবর্তন হতে পারে। এই পুনরাবৃত্তিটি 10 ​​হতে পারে এবং এর পরে এটি 5 হতে পারে
47

@ একে 47 যাই হোক না কেন, আমি উপরে উল্লিখিত অ্যালগরিদমটি খুব ঝরঝরে হওয়া উচিত। বহুমাত্রিক অ্যারের আকারটি আপনার বাজেট, রেস্তোঁরাগুলির সংখ্যা এবং ভিজিটের সংখ্যা দ্বারা দেওয়া হয়েছে এবং অ্যারেতে একটি প্রবেশিকা পূরণ করতে ও (1) লাগে, সুতরাং আলগো সময়মতো চালিত হয় হে (আর) ভি)।
লেগারবায়ের

2

আমার উত্তর হিসাবে একই ধারণা ব্যবহার এখানে :

এন পর্যন্ত ধনাত্মক সংখ্যাগুলির সংকলনে, এস এর মধ্যে কমপক্ষে একটি এন (এস / এন) দ্বারা বিভক্ত এসের চেয়ে কম হবে

আপনি সম্ভাব্য "সস্তার" রেস্তোরাঁ থেকে শুরু করে তালিকাটি তৈরি করতে পারেন ।

অ্যালগরিদমের পদক্ষেপগুলি:

  • <500/10 দামের জন্য 5 টি রেস্তোঁরা সন্ধান করুন, প্রতিটি বিভিন্ন তারার সাথে এবং প্রতিটি তারার জন্য সর্বনিম্ন ব্যয় । যেমন r1, r2, r3, r4, r5
  • উপরের প্রতিটি মানের জন্য, ব্যয় <(500 - খরচ (এক্স)) / 9 এবং বিভিন্ন তারা সহ আরও 5 টি রেস্তোঁরা সন্ধান করুন । আবার প্রতিটি তারার জন্য সর্বনিম্ন ব্যয় নির্বাচন করুন
  • 10 টি রেস্তোঁরা না পৌঁছানো এবং আপনি আপনার বাজেটের বেশি না হওয়া পর্যন্ত এটি করুন।
  • 1 - 9 রেস্তোঁরা সীমাতে উপরের 3 টি পদক্ষেপটি পুনরায় চালু করুন।
  • সর্বাধিক তারা উত্পাদন করে এমন সমাধান রাখুন

অবশ্যই, আপনি কোনও রেস্তোঁরা পুনরায় নির্ধারণ করতে পারবেন না।

আমি মনে করি সবচেয়ে খারাপ ক্ষেত্রে, আপনাকে 5x5x5 গণনা করতে হবে ... = 5 ^ 10 + 5 ^ 9 + ... + 5 ^ 2 + 5 (= প্রায় 12 মিলিয়ন) সমাধান।

জাভাস্ক্রিপ্টে

function Restaurant(name, cost, stars) {
    this.name = name;
    this.cost = cost;
    this.stars = stars;
}

function RestaurantCollection() {
    var restaurants = [];
    var cost = 0;
    this.stars = 0;

    this.addRestaurant = function(restaurant) {
        restaurants.push(restaurant);
        cost += restaurant.cost;
        this.stars += restaurant.stars;
    };

    this.setRestaurants = function(clonedRestaurants, nCost, nStars) {
        restaurants = clonedRestaurants;
        cost = nCost;
        this.stars += nStars;
    };
    this.getAll = function() {
        return restaurants;
    };

    this.getCost = function() {
        return cost;
    };
    this.setCost = function(clonedCost) {
        cost = clonedCost;
    };

    this.findNext5Restaurants = function(restaurants, budget, totalGoal) {
        var existingRestaurants = this.getAll();
        var maxCost = (budget - cost) / (totalGoal - existingRestaurants.length);
        var cheapestRestaurantPerStarRating = [];
        for(var stars = 5; stars > 0; stars--) {
            var found = findCheapestRestaurant(restaurants, stars, maxCost, existingRestaurants);
            if(found) {
                cheapestRestaurantPerStarRating.push(found);
            }
        }
        return cheapestRestaurantPerStarRating;
    };

    this.clone = function() {
        var restaurantCollection = new RestaurantCollection();
        restaurantCollection.setRestaurants([...restaurants], this.getCost(), this.stars);
        return restaurantCollection;
    };
}

function findCheapestRestaurant(restaurants, stars, maxCost, excludeRestaurants) {
     var excludeRestaurantNames = excludeRestaurants.map(restaurant => restaurant.name);
     var found = restaurants.find(restaurant => restaurant.stars == stars && restaurant.cost <= maxCost && !excludeRestaurantNames.includes(restaurant.name));
     return found;
}

function calculateNextCollections(restaurants, collections, budget, totalGoal) {
    var newCollections = [];
    collections.forEach(collection => {
        var nextRestaurants = collection.findNext5Restaurants(restaurants, budget, totalGoal);
        nextRestaurants.forEach(restaurant => {
            var newCollection = collection.clone();
            newCollection.addRestaurant(restaurant);
            if(newCollection.getCost() <= budget) {
                 newCollections.push(newCollection);
            }
        });
    });
    return newCollections;
};

var restaurants = [];
restaurants.push(new Restaurant('r1', 100, 5));
restaurants.push(new Restaurant('r2',140, 3));
restaurants.push(new Restaurant('r3',90, 4));
restaurants.push(new Restaurant('r4',140, 3));
restaurants.push(new Restaurant('r5',120, 4));
restaurants.push(new Restaurant('r6',60, 1));
restaurants.push(new Restaurant('r7',40, 1));
restaurants.push(new Restaurant('r8',30, 2));
restaurants.push(new Restaurant('r9',70, 2));
restaurants.push(new Restaurant('r10',250, 5));

restaurants.sort((a, b) => a.cost - b.cost);
var max = 5;
var budget = 100;

var total = max;
var totalCollections = [];

for(var totalGoal = total; totalGoal > 0; totalGoal--) {
    var collections = [new RestaurantCollection()];

    for(var i = totalGoal; i > 0; i--) {
        collections = calculateNextCollections(restaurants, collections, budget, totalGoal);
    }
    totalCollections = totalCollections.concat(collections);
}

var totalCollections = totalCollections.map(collection => { 
      return {
          name: collection.getAll().map(restaurant => restaurant.name),
          stars: collection.stars,
          cost: collection.getCost()
      }
});

console.log("Solutions found:\n");
console.log(totalCollections);

totalCollections.sort((a, b) => b.stars - a.stars);
console.log("Best solution:\n");
console.log(totalCollections[0]);


আরে @ জানেস বোটিস, এটি 100000 রেস্তোঁরাগুলির জন্য 27 সেকেন্ড সময় নিয়েছে: repl.it/repls/ স্ট্রিপডমোরালঅ্যাপটিমাইজেশন আপনি কি মনে করেন যে এটি 1 মিলিয়ন রেকর্ডের সাথে কাজ করতে অপ্টিমাইজ করা সম্ভব?
একে 47

বাধাটি হ'ল ফাইন্ডেস্টেস্টেস্টট্রান্স () এর অভ্যন্তরে। ফিল্টার () ফাংশন, আপনি যে রেস্তোঁরাগুলি তৈরি করার পরে ব্যয় করে বাছাই করতে পারেন (ফিল্টার () পরিবর্তে ফাইন্ড () ব্যবহার করুন যেহেতু কেবলমাত্র 1 ম পাওয়া গেছে সবচেয়ে সস্তা হবে। আমি লিঙ্কটি পরিবর্তন করেছি। তবে আমি মনে করি সর্বোত্তম সমাধান হ'ল দামের জন্য একটি সূচক সহ রেস্তোঁরাগুলির জন্য একটি ডাটাবেস (উদাহরণস্বরূপ মাইএসকিএল) ব্যবহার করা, যাতে আপনি শর্তাধীন নির্বাচনের সাথে .filter () প্রতিস্থাপন করতে পারেন।
জেনেস বোটিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.