| |||||||||||||
Capital budgeting - Using multi-objective optimization Description Capital budgeting example, solved using three multi-objective approaches:
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Capbgt2l.cpp #include <xpress.hpp> #include <stdexcept> // For throwing exceptions using namespace xpress; using namespace xpress::objects; using xpress::objects::utils::sum; /* * Capital budgeting problem. Illustrates: Logical conditions, Formulation using logic constraints */ // A project. class Project { public: const std::string name; // The name of this project. const double payout; // Payout for the project. const double investment; // Capital investment for the project. const int personnel; // Number of personnel required for the project. Project(std::string name, double payout, double investment, int personnel) : name(name), payout(payout), investment(investment), personnel(personnel) {} // For printing std::string toString() const { return name; } }; // The projects used in this example. const std::vector<Project> projectArray = { Project("Alpha", 124000.0, 104000.0, 22), Project("Beta", 74000.0, 53000.0, 12), Project("Gamma", 42000.0, 29000.0, 7), Project("Delta", 188000.0, 187000.0, 36), Project("Epsilon", 108000.0, 98000.0, 24), Project("Zeta", 56000.0, 32000.0, 10), Project("Eta", 88000.0, 75000.0, 20), Project("Theta", 225000.0, 200000.0, 41) }; // The resource constraints used in this example. const double budget = 478000.0; const int workforce = 106; int main() { try { // Create a problem instance with or without verbose messages printed to Console XpressProblem prob; // prob.callbacks.addMessageCallback(XpressProblem::console); /* VARIABLES */ // Whether each project should be invested in or not std::vector<Variable> x = prob.addVariables(static_cast<int>(projectArray.size())) .withType(ColumnType::Binary) .withName("x%d") .toArray(); /* RESOURCE AVAILABILITY CONSTRAINTS */ // Investment limit: sum of investments of all undertaken projects should not exceed budget Expression requiredInvestment = sum(static_cast<int>(projectArray.size()), [&](int i) { return x[i].mul(projectArray[i].investment); }); Inequality investmentLimit = prob.addConstraint(requiredInvestment <= budget); // Workforce limit: sum of personnel committed of all undertaken projects should not exceed workforce LinExpression requiredWorkforce = LinExpression::create(); for (std::size_t i=0; i<projectArray.size(); i++) { requiredWorkforce.addTerm(x[i], projectArray[i].personnel); } Inequality workforceLimit = prob.addConstraint(requiredWorkforce <= workforce); // Project alpha can only be done if both gamma and zeta happen prob.addConstraint(x[0] <= x[2]); prob.addConstraint(x[0] <= x[5]); // Project zeta can only be done if project epsilon happens prob.addConstraint(x[5] <= x[4]); // Projects alpha and beta as well as gamma and delta can only happen together prob.addConstraint(x[0] == x[1]); prob.addConstraint(x[2] == x[3]); // Exactly one of those pairs should be invested in, i.e., if project alpha is // performed, neither gamma nor delta can be invested in, and if project alpha // does not happen, then projects gamma and delta have to be performed prob.addConstraint(x[0].ifThen(sum(x[2], x[3]) == 0.0)); prob.addConstraint(x[0].ifNotThen(sum(x[2], x[3]) == 2.0)); /* OBJECTIVE */ // Objective function: sum of payouts of all undertaken projects Expression totalProfit = sum(static_cast<int>(projectArray.size()), [&](int i) { return x[i].mul(projectArray[i].payout); }); prob.setObjective(totalProfit, xpress::ObjSense::Maximize); /* INSPECT, SOLVE & PRINT */ // Dump the problem to disk so that we can inspect it. prob.writeProb("capbgt2l.lp"); // Solve prob.optimize(); // Check the solution status if (prob.attributes.getSolStatus() != SolStatus::Optimal && prob.attributes.getSolStatus() != SolStatus::Feasible) { std::ostringstream oss; oss << prob.attributes.getSolStatus(); // Convert xpress::SolStatus to String throw std::runtime_error("Optimization failed with status " + oss.str()); } // Get the solution and print it std::vector<double> sol = prob.getSolution(); std::cout << std::endl << "*** Solution ***" << std::endl; std::cout << "Objective: " << prob.attributes.getObjVal() << std::endl;; // Print the interesting slacks std::cout << "Remaining Budget: " << investmentLimit.getSlack() << " (out of " << budget << ")" << std::endl; std::cout << "Remaining Workers: " << workforceLimit.getSlack() << " (out of " << workforce << ")" << std::endl; // Print out the variables for (std::size_t i = 0; i < projectArray.size(); ++i) { if (x[i].getValue(sol) > 0.0) { std::cout << "Undertaking project " << projectArray[i].toString() << std::endl; } } return 0; } catch (std::exception& e) { std::cout << "Exception: " << e.what() << std::endl; return -1; } } | |||||||||||||
© Copyright 2024 Fair Isaac Corporation. |