Skip to content

Commit

Permalink
WIP flowshop
Browse files Browse the repository at this point in the history
  • Loading branch information
Lecrapouille committed May 15, 2024
1 parent ea49b55 commit 18820a4
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 90 deletions.
10 changes: 10 additions & 0 deletions data/examples/complex.flowshop
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Flowshop 6 8
Piece1 Piece2 Piece3 Piece4 Piece5 Piece6
Machine1 2.0 3.9 0.95 1.1 0.7 1.4
Machine2 nan nan 2.0 1.2 nan 1.7
Machine3 3.7 nan 2.2 nan 6.4 nan
Machine4 nan nan 2.0 nan 1.0 1.0
Machine5 1.7 3.1 3.0 nan 1.3 nan
Machine6 0.5 3.2 4.3 1.9 1.6 0.4
Machine7 1.0 1.0 1.0 1.0 1.0 1.0
Machine8 1.5 1.5 1.5 1.2 1.2 1.2
14 changes: 5 additions & 9 deletions data/examples/simple.flowshop
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
8 6
2 3.9 0.95 1.1 0.7 1.4
-Inf -Inf 2 1.2 -Inf 1.7
3.7 -Inf 2.2 -Inf 6.4 -Inf
-Inf -Inf 2 -Inf 1 1
1.7 3.1 3 -Inf 1.3 -Inf
0.5 3.2 4.3 1.9 1.6 0.4
1 1 1 1 1 1
1.5 1.5 1.5 1.2 1.2 1.2
Flowshop 3 3
Part1 Part2 Part3
Machine1 nan 1.0 5.0
Machine2 3.0 2.0 3.0
Machine3 4.0 3.0 nan
214 changes: 139 additions & 75 deletions src/Net/Imports/ImportFlowshop.cpp
Original file line number Diff line number Diff line change
@@ -1,107 +1,171 @@
//=============================================================================
// TimedPetriNetEditor: A timed Petri net editor.
// Copyright 2021 -- 2023 Quentin Quadrat <[email protected]>
//
// This file is part of TimedPetriNetEditor.
//
// TimedPetriNetEditor is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
//=============================================================================

#include "Imports.hpp"
#include "TimedPetriNetEditor/PetriNet.hpp"
#include <sstream>
#include <fstream>
#include <cstring>

namespace tpne {

//------------------------------------------------------------------------------
// See http://jpquadrat.free.fr/chine.pdf flowshop_graph() function
// TODO ./build/TimedPetriEditor foo.flowshop
bool PetriNet::importFlowshop(std::string const& filename)
std::vector<std::string> splitLine(std::ifstream& file)
{
static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 required");
std::string s;

std::getline(file, s);
std::cout << "Line " << s << std::endl;
std::stringstream ss(s);
std::vector<std::string> v;

std::ifstream ifs{ filename };
if (!ifs)
while (std::getline(ss, s))
{
std::cerr << "Could not open matrix file '"
<< filename << "' for reading"
<< std::endl;
return false;
std::cout << s << std::endl;
v.push_back(s);
}

// Dense matrix
std::vector<std::vector<double>> matrix;
size_t rows, columns;
return v;
}

//------------------------------------------------------------------------------
std::string importFlowshop(Net& net, std::string const& filename)
{
struct DataMatrix
{
std::vector<std::string> columnNames;
std::vector<std::string> rowNames;
std::vector<std::vector<float>> data;
};

DataMatrix matrix;
std::stringstream error;

// Read the number of rows and columns and resize the vector of data
if (!(ifs >> rows >> columns))
// Check if file exists
std::ifstream file(filename);
if (!file)
{
m_message.str("");
m_message << "Malformed matrix dimension. Needed rows columns information"
<< std::endl;
return false;
error << "Failed opening '" << filename << "'. Reason was '"
<< strerror(errno) << "'" << std::endl;
return error.str();
}

// Read all data and store them into the matrix
matrix.resize(rows, std::vector<double>(columns));
for (std::vector<double>& row : matrix)
// Extract number of transitions and number of lines
size_t transitions, lines, rows;
std::string type;

if (!(file >> type >> rows >> lines))
{
for (double& col : row)
{
std::string text;
ifs >> text;
col = std::stod(text.c_str());
std::cout << ' ' << col;
}
std::cout << std::endl;
error << "Malformed header. Needed 'Flowshop number_transitions number_lines'"
<< std::endl;
return error.str();
}
if (type != "Flowshop")
{
error << "Malformed token. Expected to extract token 'TimedEventGraph'"
<< std::endl;
return error.str();
}

// windows screen.
// FIXME: get the exact dimension Editor::viewSize()
// FIXME: initial frame iteration: the screen size is not at its final size
const size_t w = 600u; const size_t h = 600u;
const size_t margin = 50u;
// Since the file does not give position, we place them as square
size_t dx = (w - 2u * margin) / rows;
size_t dy = (h - 2u * margin) / lines;
size_t x = margin + dx; size_t y = margin + dy;

size_t id = 0u;
std::string line;

// End the current line
getline(file, line);

// Construct the flowshop
float x, y;
const size_t machines = rows;
const size_t pieces = columns;
const float SPACING = 100.0f;
size_t id = 0u; // Place unique identifier
size_t m, p; // iterators
std::vector<Place*> places;

// Add places of the matrix
x = 2.0f * SPACING; y = SPACING - 50.0f;
for (m = 0u; m < machines; ++m) // TODO inverser l'ordre
// Read the column names
if (getline(file, line))
{
x = 2.0f * SPACING;
for (p = 0u; p < pieces; ++p)
std::istringstream columnNamesStream(line);
std::string columnName;
while (columnNamesStream >> columnName)
{
if (matrix[m][p] != -std::numeric_limits<double>::infinity())
{
// Place caption "m1p2" for "Machine1--Piece2"
//std::string caption("m" + std::to_string(m) + "p" + std::to_string(p));
std::string caption(std::to_string(id) + ": " + std::to_string(m * pieces + p));
places.push_back(&addPlace(id++, caption, x, y, 0u));
}
x += SPACING;
matrix.columnNames.push_back(columnName);
}
y += SPACING;
}

// Link arcs between places: this will add the transitions
for (m = 0u; m < 2u/*machines - 1u*/; ++m)
// Read the following lines to obtain the row names and the data
while (getline(file, line))
{
for (p = 0u; p < pieces - 1u; ++p)
std::istringstream lineStream(line);
std::string rowName;
if (lineStream >> rowName)
{
size_t next = p + 1u;
while ((next < pieces - 1u) && (matrix[m][next] == -std::numeric_limits<double>::infinity()))
matrix.rowNames.push_back(rowName);

std::vector<float> row;
std::string value;
while (lineStream >> value)
{
next += 1u;
}
row.push_back(stof(value));

Node* from = findNode(places[m * pieces + p]->key);
Node* to = findNode(places[m * pieces + next]->key);
std::cout << "M" << m << ": " <<
addArc(*from, *to, float(matrix[m][p]), false);
if (value != "nan")
{
net.addPlace(id, Transition::to_str(id), x, y, 0);
id++;
}
x += dx;
}
matrix.data.push_back(row);
}
else
{
error << "Malformed line '" << line << "'" << std::endl;
return error.str();
}
x = margin + dx;
y += dy;
}

// Construct the flowshop: Place the machines (inputs)
x = SPACING; y = SPACING;
for (size_t i = 0u; i < machines; ++i)
float ymax = y;
float xmax = margin + dx + dx * rows;

// Place this code outside the getline() loop to have id of internal transitions
// starting from 0.
x = margin + dx - dx / 2.0f; y = margin;
for (const auto& columnName : matrix.columnNames)
{
addPlace(p++, "Machine " + std::to_string(i), x, y, 0u); // FIXME id
y += SPACING;
net.addPlace(id++, columnName, x, y, 0);
//net.addPlace(id++, columnName, x, ymax, 0);
x += dx;
}

// Construct the flowshop: Place the pieces (inputs)
x += SPACING / 2.0f;
for (size_t i = 0u; i < pieces; ++i)
x = margin; y = margin + dy + dy / 2.0f;
for (const auto& rowName : matrix.rowNames)
{
addPlace(p++, "Piece " + std::to_string(i), x, y, 0u); // FIXME id
x += SPACING;
net.addPlace(id++, rowName, x, y, 0);
//net.addPlace(id++, rowName, xmax, y, 0);
y += dy;
}

return true;
return {};
}

} // namespace tpne
2 changes: 1 addition & 1 deletion src/Net/Imports/Imports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ std::vector<Importer> const& importers()
static const std::vector<Importer> s_importers = {
{ "JSON", ".json", importFromJSON },
{ "Petri Net Markup Language", ".pnml", importFromPNML },
// FIXME add a filter to eliminate it in the case the net is not event graph
{ "Flowshop", ".flowshop", importFlowshop },
{ "Timed Event Graph", ".teg", importFromTimedEventGraph }
};

Expand Down
2 changes: 2 additions & 0 deletions src/Net/Imports/Imports.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ std::string importFromJSON(Net& net, std::string const& filename);
std::string importFromTimedEventGraph(Net& net, std::string const& filename);
//! \brief Import https://gitlab.com/porky11/pn-editor
std::string importFromPNML(Net& net, std::string const& filename);
//! \brief Import
std::string importFlowshop(Net& net, std::string const& filename);

//! \brief Interface for importing a Petri file.
//! \param[inout] net the net we are importing. Better to call net.clear()
Expand Down
10 changes: 5 additions & 5 deletions src/Net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ LINKER_FLAGS += -ldl -lpthread
###################################################
# Make the list of compiled files for the library
#
IMPORT_FORMATS += ImportJSON.o ImportPNML.o ImportTimedEventGraph.o ExportTimedEventGraph.o
EXPORT_FORMATS += ExportJSON.o ExportPNML.o ExportSymfony.o ExportPnEditor.o
EXPORT_FORMATS += ExportPetriLaTeX.o ExportJulia.o ExportGraphviz.o ExportDrawIO.o
EXPORT_FORMATS += ExportGrafcetCpp.o
LIB_OBJS += ImportJSON.o ImportPNML.o ImportTimedEventGraph.o ExportTimedEventGraph.o
LIB_OBJS += ExportJSON.o ExportPNML.o ExportSymfony.o ExportPnEditor.o
LIB_OBJS += ExportPetriLaTeX.o ExportJulia.o ExportGraphviz.o ExportDrawIO.o
LIB_OBJS += ExportGrafcetCpp.o ImportFlowshop.o
LIB_OBJS += Path.o Howard.o Utils.o TimedTokens.o Receptivities.o
LIB_OBJS += PetriNet.o Algorithms.o Simulation.o History.o
LIB_OBJS += $(IMPORT_FORMATS) Imports.o $(EXPORT_FORMATS) Exports.o
LIB_OBJS += Imports.o Exports.o

###################################################
# Compile the project, the static and shared libraries
Expand Down

0 comments on commit 18820a4

Please sign in to comment.