Knapsack with continuous (non distinct) constraint

后端 未结 7 551
南方客
南方客 2021-02-03 12:05

I watched Dynamic Programming - Kapsack Problem (YouTube). However, I am solving a slightly different problem where the constraint is the budget, price, in double, not integer.

7条回答
  •  孤街浪徒
    2021-02-03 12:38

    This is not an answer to your question, but might as well be what you are looking for:

    Linear Programming

    I've used Microsoft's Solver Foundation 3 to make a simple code that solves the problem you described. It doesn't use the knapsack algorithm, but a simplex method.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.SolverFoundation.Common;
    using Microsoft.SolverFoundation.Services;
    
    namespace LPOptimizer
    {
        class Item
        {
            public String ItemName { get; set; }
            public double Price { get; set; }
            public double Satisfaction { get; set; }
    
            static void Main(string[] args)
            {
                //Our data, budget and items with respective satisfaction and price values
                double budget = 100.00;
                List items = new List()
                {
                    new Item(){
                        ItemName="Product_1", 
                        Price=20.1, 
                        Satisfaction=2.01
                    },
                    new Item(){
                        ItemName="Product_2", 
                        Price=1.4, 
                        Satisfaction=0.14
                    },
                    new Item(){
                        ItemName="Product_3", 
                        Price=22.1, 
                        Satisfaction=2.21
                    }
                };
    
                //variables for solving the problem.
                SolverContext context = SolverContext.GetContext();
                Model model = context.CreateModel();
                Term goal = 0; 
                Term constraint = 0; 
    
                foreach (Item i in items)
                {
                    Decision decision = new Decision(Domain.IntegerNonnegative, i.ItemName);
                    model.AddDecision(decision); //each item is a decision - should the algorithm increase this item or not?
    
                    goal += i.Satisfaction * decision; //decision will contain quantity.
                    constraint += i.Price * decision; 
                }
    
                constraint = constraint <= budget; //this now says: "item_1_price * item_1_quantity + ... + item_n_price * item_n_quantity <= budget";
    
                model.AddConstraints("Budget", constraint); 
    
                model.AddGoals("Satisfaction", GoalKind.Maximize, goal); //goal says: "Maximize: item_1_satisfaction * item_1_quantity + ... + item_n_satisfaction * item_n_quantity"
    
                Solution solution = context.Solve(new SimplexDirective());
                Report report = solution.GetReport();
                Console.Write("{0}", report);
                Console.ReadLine();
            }
        }
    }
    

    This finds the optimum max for the number of items (integers) with prices (doubles), with a budget constraint (double).

    From the code, it is obvious that you could have some items quantities in real values (double). This will probably also be faster than a knapsack with a large range (if you decide to use the *100 you mentioned).

    You can easily specify additional constraints (such as number of certain items, etc...). The code above is adapted from this MSDN How-to, where it shows how you can easily define constraints.

    Edit

    It has occurred to me that you may not be using C#, in this case I believe there are a number of libraries for linear programming in many languages, and are all relatively simple to use: You specify constraints and a goal.

    Edit2

    According to your Update 2, I've updated this code to include satisfaction.

提交回复
热议问题