Omniscope Custom Blocks › Analytics/Linear-Optimisation

Linear Optimisation

Solves linear and integer programmes given as data (variables with objective and bounds, constraints in long format) with the HiGHS solver: optimal plan, slack, binding constraints and shadow prices.

Analytics › Prescriptive Python visokio-agents

Open the demo in Omniscope Download demo.ioz Sample data: products.csv Sample data: resource-usage.csv Source on GitHub

Items tagged visokio-agents are community examples built by Visokio's agents, to extend Omniscope's core blocks and views with popular, specialist and more unusual use cases, and to show what anyone, people or agents, can build on Omniscope. They are tested by automated tests and were run on a real Omniscope server. They were not reviewed by Omniscope's core team, so they are not on a par with the core blocks and views, which have years of manual, functional and unit tests behind them. About

Omniscope custom block · Analytics

The best plan under your constraints: product mix, allocation, blending or staffing, solved to optimality from a model kept as ordinary data, with the binding constraints and what extra capacity is worth.

Python · pandas, numpy, scipy · installs scipy automatically

The problem it solves

Many planning questions are optimisation problems in disguise: which mix of products makes the most profit with the machine hours, labour and materials available; which suppliers to buy from to meet demand at least cost; how many staff to roster per shift. Spreadsheets and rules of thumb get close but rarely to the best answer.

Linear Optimisation reads the model as data (variables in one table, constraints in another), solves it with the HiGHS solver, and reports the optimal plan, which constraints are binding and, for continuous models, the shadow price of each resource.

How it works

What goes in

Input 1: products (decision variables)

Product Profit Per Unit Minimum Units Maximum Demand Whole Units
Dining Table 180 0 60 Yes
Chair 45 120 400 Yes
Bookcase 95 0 80 Yes
Desk 140 10 70 Yes
Cabinet 120 0 50 Yes

5 rows in the sample file.

Input 2: resource usage (constraints, long format)

Hours and timber per unit for each product and resource, with weekly capacities. Two extra rows say every dining table needs four chairs.

Resource Product Usage Per Unit Sense Capacity
Carpentry hours Dining Table 6.0 <= 800
Carpentry hours Chair 1.5 <= 800
Carpentry hours Bookcase 4.0 <= 800
Carpentry hours Desk 5.0 <= 800
Carpentry hours Cabinet 5.0 <= 800
Finishing hours Dining Table 3.0 <= 420
Finishing hours Chair 1.0 <= 420
Finishing hours Bookcase 2.0 <= 420
Finishing hours Desk 2.5 <= 420
Finishing hours Cabinet 3.0 <= 420

22 rows in the sample file.

The options

Option Demo setting What it does
Goal Maximise (profit, output) Whether the best plan has the highest or the lowest objective.
Variable name Product Names each decision variable, such as a product to make.
Objective coefficient Profit Per Unit Profit or cost per unit.
Lower bound (optional) Minimum Units Minimum value; empty means 0.
Upper bound (optional) Maximum Demand Maximum value; empty means no limit.
Whole-number flag (optional) Whole Units Yes / true / 1 for variables that must be whole numbers.
Constraint name Resource Names each constraint, such as a resource; one row per variable that uses it.
Variable Product Must match the variable names in input 1.
Coefficient Usage Per Unit Amount of the constraint used by one unit of the variable.
Sense Sense <=, >= or = (also: at most, at least, exactly).
Limit Capacity Right-hand side, such as capacity.

What comes out

Solution

Product Profit Per Unit Minimum Units Maximum Demand Whole Units Optimal Value Objective Contribution At Bound Reduced Cost
Dining Table 180 0 60 Yes 35 6,300
Chair 45 120 400 Yes 140 6,300
Bookcase 95 0 80 Yes 0 0 Lower
Desk 140 10 70 Yes 70 9,800 Upper
Cabinet 120 0 50 Yes 0 0 Lower

Constraints

Constraint Sense Limit Used Slack Binding Shadow Price
Carpentry hours <= 800 770 30 No
Finishing hours <= 420 420 0 Yes
Oak timber (m3) <= 14 13.3 0.7 No
Assembly bay hours <= 190 140 50 No
Tables need 4 chairs >= 0 0 0 Yes

Summary

Status Objective Objective Value Variables Integer Variables Constraints Binding Constraints
Optimal Maximise 22,400 5 5 5 2

Shadow prices (same model with continuous units)

How much weekly profit would rise for one more unit of each binding resource: the business case for overtime or more timber.

Constraint Used Limit Shadow Price
Finishing hours 420 420 51.43
Tables need 4 chairs 0 0 -6.43
The profit-maximising weekly plan (synthetic data).
The profit-maximising weekly plan (synthetic data).

The profit-maximising weekly plan (synthetic data).

Capacity used per resource; orange bars are binding constraints, the bottlenecks.
Capacity used per resource; orange bars are binding constraints, the bottlenecks.

Capacity used per resource; orange bars are binding constraints, the bottlenecks.

Where it pays off

Manufacturing: Product mix and capacity planning

Maximise contribution within machine, labour and material limits, and see which bottleneck is worth investing in from its shadow price.

Logistics: Allocation and transport

Assign demand from customers to depots at least cost within depot capacities: a classic transportation problem in long-format data.

Food, chemicals and agriculture: Blending

Cheapest blend of ingredients that meets nutritional or specification limits, recalculated as ingredient prices change.

Retail and services: Staffing and budget allocation

Cover forecast demand per shift with the fewest staff hours, or split a marketing budget across channels with minimum and maximum spends.

Use cases describe typical scenarios and are illustrative.

Why do this in Omniscope

How it fits into an Omniscope workflow

Products / costs (Database) + Resource usage → Linear Optimisation → Report

Keep the model in ordinary tables (or build it with Omniscope blocks from operational data: prices from a pricing table, capacities from a planning sheet), so the plan refreshes as inputs change.

Show the plan and the binding constraints in a Report; add scenario parameters (capacity, prices) to compare plans.

In one step

A long-format constraint table that maps directly to resource-usage data, solved in one step with the open-source HiGHS solver through scipy; no licence needed.

Try it

  1. Open the demo project (demo.iox on the demo server, or import demo.ioz from this folder): five furniture products with profit per unit and demand limits, and a resource table of hours and timber per product.
  2. The question: what should the workshop make this week to earn the most?
  3. Open Linear Optimisation: maximise, map the variable and constraint fields. Run it.
  4. Look at the plan and the profit (£22,400), then the constraints output: the binding ones are the bottlenecks.
  5. Look at the shadow prices from the continuous model: what one more hour of the bottleneck resource is worth, which is the overtime business case.

Running in Omniscope

Omniscope workflow
Omniscope workflow

The demo project's workflow: the sample data, the block, and a Validate data check on its output.

Language and libraries

Python. It uses pandas, numpy and scipy.

pandas and numpy are part of Omniscope's Docker Python image, and the block was run in both host mode and Docker mode on an Omniscope server, with the same results. It also uses scipy's HiGHS solver (linear and mixed-integer programming). Omniscope installs scipy automatically from the block's dependencies; in Docker mode it builds an image for the block the first time it runs.

Tested

Run on an Omniscope server, the demo workflow finished without errors (5 records in Solution, 5 in Constraints and 1 in Summary). Automated tests also cover normal data, empty input, wrong types and large input.

Reference

Fields it reads

NameTypeWhat it does
Variable nameFieldNames each decision variable, such as a product to make.
Objective coefficientFieldProfit or cost per unit.
Lower bound (optional)FieldMinimum value; empty means 0.
Upper bound (optional)FieldMaximum value; empty means no limit.
Whole-number flag (optional)FieldYes / true / 1 for variables that must be whole numbers.
Constraint nameFieldNames each constraint, such as a resource; one row per variable that uses it.
VariableFieldMust match the variable names in input 1.
CoefficientFieldAmount of the constraint used by one unit of the variable.
SenseField<=, >= or = (also: at most, at least, exactly).
LimitFieldRight-hand side, such as capacity.

Options

NameTypeWhat it does
GoalChoiceWhether the best plan has the highest or the lowest objective.
All variables are whole numbersYes / no
Time limit (seconds)Number

Outputs

OutputWhat it holds
SolutionInput 1 with Optimal Value, Objective Contribution, At Bound, Reduced Cost.
ConstraintsPer constraint: sense, limit, used, slack, binding, shadow price.
SummaryStatus, objective value, variable and constraint counts, solver message.