Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@

This repository contains various benchmark instances for the Vector Bin Packing and one-dimensional Bin Packing problems.

One-dimensional instances
-------------------------

The `one_dimension` folder contains a BPPC benchmark dataset and an instance generator for the one-dimensional Bin Packing Problem with Conflicts.

**Folder content**

- Benchmark dataset: the `BPPC_dataset.tar.gz` archive contains instances generated from the classical one-dimensional Bin Packing Problem instances proposed by E. Falkenauer.
The dataset is organized into eight benchmark classes, two conflict-generation variants, and several conflict graph densities.
- Instance generator: the `BPPC_instance_generator` folder contains a standalone C++ program for generating random arbitrary conflict graphs for one-dimensional BPP instances.
The generator supports input formats consistent with the VBP format and Falkenauer's BPP format.

For further details on the dataset structure, generation process, and instance file format, please refer to the included `README.txt` file.

Multi-dimensional instances
---------------------------

Expand Down
Binary file added one_dimension/BPPC_dataset.tar.gz
Binary file not shown.
23 changes: 23 additions & 0 deletions one_dimension/BPPC_instance_generator/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++17

BUILD_DIR = build

TARGET = $(BUILD_DIR)/bppc_generator.exe

SRCS = generator.cpp main.cpp
OBJS = $(SRCS:%.cpp=$(BUILD_DIR)/%.o)

all: $(BUILD_DIR) $(TARGET)

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS)

$(BUILD_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@

clean:
rm -rf $(BUILD_DIR)
163 changes: 163 additions & 0 deletions one_dimension/BPPC_instance_generator/generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "generator.hpp"

#include <exception>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <variant>
#include <filesystem>

// PSEUDOCODE FOR THE p̂-generator
// Source: Gendreau et al. "Solving the maximum clique problem using a tabu search" Annals of Operations Research 41(1993) 385-403
// 0 <= a <= b <= 1
// begin
// for i := 1 to n do p[i] := uniform (a,b);
// for i := 1 to (n- 1) do
// for j := (i + 1) to n do
// generate edge (i, j) with probability ( p[i] + p[j] ) / 2;
// end

ArbitraryGraphGenerator::ArbitraryGraphGenerator(int N, float A, float B, int seed)
:verticesCount(N),
aBound(A),
bBound(B),
adjacencyLists(N),
gen(seed) { // Standard mersenne_twister_engine seeded with the given seed value

if (N <= 0)
throw std::invalid_argument("N must be > 0");
else if (A < 0 || B > 1 || A > B)
throw std::invalid_argument("A and B have to be real numbers in [0,1] & A <= B");
else {
// IMPORTANT: uniform_real_distribution generates a real value only from [min, max).
// The exact `max` value MAY, or MAY NOT be returned. This uncertainty is due to
// undeterministic floating-point rounding; see e.g. cppreference.com
std::uniform_real_distribution<> dist(A, B);

for(int i = 0; i < N; i++)
verticesProbs.push_back(dist(gen));
}
}

// This function generates an edge between two different vertices in arbitrary conflict graph,
// or a conflict between two different BPPC items, in other words.
// The function saves generated edges as adjacencyLists.
// Every vertex has its own adjacency list, which contains all its adjacent vertices in the context of arbitrary conflict graph
void ArbitraryGraphGenerator::generateEdges() {
double prob;
std::bernoulli_distribution edgeDist;
for (int i = 0; i < verticesCount - 1; i++)
for (int j = i + 1; j < verticesCount; j++) {
// Calculate the probability of an edge (conflict between two items)
prob = (static_cast<double>(verticesProbs.at(i)) + verticesProbs.at(j)) / 2.0;

// Next, Bernoulli Distribution makes a decision whether
// the vertices i and j should be connected with an edge
// with **prob** likelihood,
// or NOT, with (1 - prob) likelihood.
auto param = std::bernoulli_distribution::param_type(prob);
if (edgeDist(gen, param)) {
adjacencyLists.at(i).push_back(j);
//adjacencyLists.at(j).push_back(i); // Uncomment for symmetric adjacency matrix
}
}
// Sort IDs in vectors in ascending order
for(auto& v : adjacencyLists)
std::sort(v.begin(), v.end());
}

// Write all conflicts in a row for an item with ID = index
std::string writeConflicts(const ArbitraryGraphGenerator* g, int index, OutputFileType outputFileType) {
std::string conflictsList;
for (int id : g->adjacencyLists.at(index))
conflictsList += " " + (outputFileType == OutputFileType::Textfile ? std::to_string(id + 1) : std::to_string(id)); // Conversion to 1-based item ID's for text output file's format

return conflictsList;
}

// This function creates a single BPPC instance
// Make sure you have your input files format consistent with BPP or VBP instance format.
void ArbitraryGraphGenerator::createBPPCInstance(const std::string& inputFilename, const std::string& outputFilename, InputFileType inputFileType, OutputFileType outputFileType) {

std::string ext = inputFilename.substr(inputFilename.size() - 4);
if (inputFilename.size() < 4 || (ext != ".txt" && ext != ".vbp"))
throw std::runtime_error("Expected *.txt or *.vbp file");

std::ifstream fileIn(inputFilename);
if (!fileIn)
throw std::runtime_error("Cannot open file: " + inputFilename);

std::ofstream fileOut(outputFilename);
if (!fileOut)
throw std::runtime_error("Cannot create file: " + outputFilename);

if (inputFileType == InputFileType::FalkenauerBPP) {
int n, opt, capacity;
std::string line;
// Read the first line of an input file
std::getline(fileIn, line);
std::stringstream ss(line);
ss >> capacity >> n >> opt;

// Create 1-Dimensional BPPC instance text file
fileOut << '1' << std::endl; // Number of dimensions; the first line of a new file
fileOut << capacity << std::endl; // Bins capacity; the second line
fileOut << n << std::endl; // Number of items; the third line

// Then save a new line to the output file in the required format
if(outputFileType == OutputFileType::Textfile)
for (int i = 0; i < n; i++) {
fileIn >> line;
fileOut << std::to_string(i+1) + " " + line + writeConflicts(this, i, OutputFileType::Textfile) << std::endl;
}
else
for (int i = 0; i < n; i++) {
fileIn >> line;
fileOut << line + " 1" + writeConflicts(this, i, OutputFileType::VBPFormat) << std::endl;
}
}
else if (inputFileType == InputFileType::VBPFormat) {
std::string dimensionsLine;
std::string capacitiesLine;
std::string itemsCountLine;

std::getline(fileIn, dimensionsLine);
std::getline(fileIn, capacitiesLine);
std::getline(fileIn, itemsCountLine);

int dimensions = std::stoi(dimensionsLine);
if (dimensions <= 0)
throw std::runtime_error("VBP dimensions must be positive");

int n = std::stoi(itemsCountLine);

fileOut << dimensionsLine << std::endl;
fileOut << capacitiesLine << std::endl;
fileOut << itemsCountLine << std::endl;

if (outputFileType == OutputFileType::Textfile) {
for (int i = 0; i < n; i++) {
std::string itemSizesLine, temp;
std::getline(fileIn, itemSizesLine);
std::stringstream ss(itemSizesLine);
fileOut << std::to_string(i+1);
for (int j = 0; j < std::stoi(dimensionsLine); j++) {
ss >> temp;
fileOut << " " << temp;
}
fileOut << writeConflicts(this, i, OutputFileType::Textfile) << std::endl;
}
} else
for (int i = 0; i < n; i++) {
std::string itemSizesLine;
std::getline(fileIn, itemSizesLine);
fileOut << itemSizesLine << writeConflicts(this, i, OutputFileType::VBPFormat) << std::endl;
}
}
else {
throw std::runtime_error("Unsupported input file type");
}

fileIn.close();
fileOut.close();
}
29 changes: 29 additions & 0 deletions one_dimension/BPPC_instance_generator/generator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <random>
#include <vector>
#include <fstream>
#include <string>

enum class InputFileType {
FalkenauerBPP,
VBPFormat
};

enum class OutputFileType {
Textfile,
VBPFormat
};

class ArbitraryGraphGenerator {
private:
int verticesCount;
float aBound, bBound;
std::vector<std::vector<int>> adjacencyLists; // Lists of conflicts - consecutive indices correspond to items IDs (starting with 0)
std::mt19937 gen; // Equidistributed Uniform Pseudo-Random Number Generator
std::vector<float> verticesProbs; // Probability for each vertex of being in conflict with other vertices

public:
ArbitraryGraphGenerator(int N, float A, float B, int seed);
void generateEdges();
friend std::string writeConflicts(const ArbitraryGraphGenerator* g, int index, OutputFileType outputFileType);
void createBPPCInstance(const std::string& inputFilename, const std::string& outputFilename, InputFileType inputFileType, OutputFileType outputFileType);
};
Loading