12
$\begingroup$

After carefully reading the answers to my previous post I decided to opt for developing and deploying an app as a web service.

I watched a talk on optimization apps. It suggests using the following architecture to build a Cutting Stock app - you need an account to try it :

enter image description here enter image description here

Several frameworks/tools were mentioned : React, NodeJs, MongoDB, Redis, WebSockets, AWS (and similar cloud services), Docker, etc.

But since I dont't have any background in CS (except for some coding), I am struggling a lot. Thus, I have several questions :

  1. Is there any way to make the architecture simpler. My goal is to build "prototype" apps to add in my portfolio/resume as a student (not to be deployed at a large scale).

  2. Depending on the architecture you will suggest, how to learn about the whole stack without going too deep, just enough to develop and deploy basic apps that are similar to what is presented in the talk ?

  3. Assuming that I want to use an open-source solver (Cbc, Clp) instead of Gurobi, what do I need to do to make the app available on the web, do you I need to use AWS (or a similar cloud service). But, is it cost-effective ? Any alternatives ?

$\endgroup$
  • 4
    $\begingroup$ I believe that the complexity of the architecture depends a lot on the audience of the deployed product. Is it only for 2-3 practitioners who use it rarely for planning purposes, or is it used for operation by 100s of users, or even embedded in some larger infrastructure? In the first case, or for prototypes, the architecture sketched in the Gurobi presentation could be simplified, IMHO. What is typical for OR applications is the long runtime of jobs. So you would need asynchronous, non-blocking calls in your API. $\endgroup$ – Robert Schwarz Aug 17 '19 at 18:14
  • $\begingroup$ @RobertSchwarz could you please be more specific by precising a simplified flow ? I did an attempt as an answer but I am not sure about it (and it's not simpler !). Thank you $\endgroup$ – Amira Zarglayoun Aug 17 '19 at 23:01
  • 4
    $\begingroup$ @Best_fit It seems you have inadvertently created two separate accounts on SE. Please use the contact form to request that the accounts be merged. Thanks! $\endgroup$ – LarrySnyder610 Aug 18 '19 at 0:53
  • 1
    $\begingroup$ @AmiraZarglayoun, I don't have a sketch at hand, for a simpler architecture, unfortunately. But, for example, if you already develop your model/algorithm in Python, why not also use Python for the web server part (e.g. Flask). Then, you could try to use Python for the "front-end" as well, using something like Dash. If you don't deal with many simultaneous users, you might be able to use SQLite in a file, instead of a separate DB process. The result would be a simpler code base, all Python, that would be easier to get started in. $\endgroup$ – Robert Schwarz Aug 19 '19 at 6:09
  • $\begingroup$ @RobertSchwarz I want to learn basic software engineering concepts in general. Meaning, I want to get an overview on APIs, databases, architectures etc without going too deep in any of them. Any recommended resources ? $\endgroup$ – Amira Zarglayoun Aug 19 '19 at 7:43
7
$\begingroup$

Earlier this year I needed a web application to let some Chinese students (with varying English language proficiencies) play around with models for Timetabling and Rolling Stock scheduling. I used an architecture much flatter than what Gurobi proposes, which did work in the small scale classroom setting (10~20 students). I first toyed around with a client-side only architecture, but since that was too limited and I do most of my stuff in Java with CPLEX, I ended up using Spring Boot for the backend. I'll discuss your questions based on my experience.

Question 1: there are definitely simpler architectures than the one proposed by Gurobi.

Option A: everything client-side: this is the simplest architecture you can have, in my opinion, but it has a large drawback: you need a solver in pure Javascript, so the high-quality commercial solvers are definitely out of scope. However, some people have used Emscripten to compile some of the open source solvers to Javascript. The example posted by fhk uses a Javascript compiled version of lp_solve, in my own attempts I ended up using a Javascript version of GLPK. Both solvers are fine for small linear programs, but for integer programs, you run into problems quickly. Also, running everything in the browser results in a lot of overhead, so even if the official version is able to solve a model, it is still possible the Javascript version runs into trouble. Also, the API's of these solvers are not extremely nice (at least there are quite different from the way I like to convert instance data into an LP/IP-model).

An important advantage of this approach is that deployment is dead simple: you just have to server static HTML, and you can do that from something like Github pages. Also, you can build everything in Javascript, so you need to focus on a single programming language.

Option B: call the solver in a request handler: this approach introduces a server-side but keeps the server-side minimal. In my case, the design of the back-end looked roughly as follows:

    // Return the .html template that contains the client side application
    @GetMapping("/tt")
    public String tt() {
       return "timetabling";
    }

    @PostMapping("/tt/solve")
    @ResponseBody
    public TTSolution ttSolve(@RequestBody TTInstance instance) throws IloException {
        // Check if the size of the instance is small enough to solve quickly
        // Build a CPLEX model based on the TTInstance object (set the number of threads used to 1)
        // Solve this model like you would in a regular Java program calling CPLEX
        // Obtain a TTSolution object from the solution found by the solver.
        return solution;
    }

The nice thing is that if you design your TTInstance and TTSolution classes properly (in particular in a way that they can be automatically converted to/from JSON by Spring), your client-side application only needs to send a properly structured instance data object as a web-request, and it will receive a nicely structured object with the solution after POSTing the instance data to the /tt/solve endpoint. I used Vue.js to make a nice front-end application where it is easy to edit model data in a guided manner and explore the resulting solution, Axios to POST the model data and receive a solution from the server, and Bootstrap to make things look nice. Creating the front-end was more effort than creating the backend, in this case.

Note that this architecture still has a number of drawbacks: your solutions times/memory usage should be reasonably low, and the number of concurrent users should be low as well. The first reason is that if a POST-request takes to long, the web-browser or web-server will typically cancel the request. Additionally, if the solver consumes too many resources, it can take the whole web application server down with it. This is the main reason why Gurobi proposes an architecture with separate worker processes: the web controller's request handlers, only need to send the data into a job queue, from where the workers retrieve their tasks. If a worker then takes too long or uses too many resources, it can be killed without any risk for the web application server (besides having a failed job).

However, the advantages of this design are pretty clear: by running the solver directly in the handler of a POST-request, you avoid the need for a job queue, separate worker processes and a database to store the instances and their solutions. In fact, there is no need to persist data at all, and if you want to do it anyway, you can opt to do it all in the browser, e.g. via localStorage, or by implementing import/export functionality based on Javascript's FileReader functionality and ability to create a local download.

So yes, you can flatten the architecture either to a single client-side application (html/css/javascript), or to a client-side application with a simple backend server that does the solving directly in the request handler. Both options do make sense for prototyping/demonstration purposes. For a backend, you need a language that offers both a web-framework and a good interface to a solver. For someone who is inexperienced, Python is probably the most convenient candidate (fhk mentions the Flask web framework), as I believe Python has nicer bindings with different solvers, in particular, the open source ones. From experience, I know Java is also up to the task.

Question 2: If your prototype is small enough to do everything in the browser, the only technology you need to understand is html/css/javascript. It is likely you need to learn these technologies anyway, as they are so fundamental to web applications. There are plenty of tutorials and guides for these technology stacks, just pick something modern that suits you well.

If you do need a better solver, but can still call in directly in a POST-request handler, the backend will be very easy to set up and a basic introduction to your web application framework of choice should probably cover what you need, as there is no need to work with databases/message queue/job workers. The main thing that needs to happen is to convert JSON data to object data, and you need to write code that does the actual optimization, but any REST-API tutorial should give you what you need.

Question 3: how easy it is to deploy something, depends on the web application framework and the architecture. The client-side only application can be made available on almost any place where you can put a static website, which is really easy. If you work with a backend, it is easier to do the actual development on your own computer before you deploy it to the internet. If you are satisfied with your application, you should read the documentation of your web application framework whether it has pointers on good ways to deploy an application. There are many cloud providers that can run these applications directly, but it is also an option to get a virtual private server and run the application yourself (although that is probably more of a hassle).

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ I now remember that I also developed a small tool for a workshop. In my case, it was focused on modeling, so users could edit the model text in a form on a website, but the solvers were executing on the server. All based on SCIP and Zimpl, it's implemented in Go, as a single process. $\endgroup$ – Robert Schwarz Aug 26 '19 at 7:42
4
$\begingroup$

OK so indeed there are many ways to cut this cake.

I'd suggest starting with something very simple (please pardon the self content posting).

e.g.

Create a REST end point

example

  • Use Python web framework flask
  • Write your formulation in pulp
    • This makes the whole solve environment creation free, both in terms of $ but also in terms of install overhead.
  • parse json request into formulation objects
  • create response solution json
  • deploy on heroku

Create a front end

example - purely front end app to solve models

  • Use a raw js or whatever framework (nodejs, Angular, React et al)
  • Call your API (be sure to enable CORS)
  • Create a way to upload and download data
  • Can also be deployed on heroku

Happy to talk through in more detail.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Is there any way to contact you ? $\endgroup$ – Amira Zarglayoun Aug 22 '19 at 18:02
  • $\begingroup$ Yes. You can email me f.kauker@gmail.com $\endgroup$ – fhk Aug 24 '19 at 16:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.