Gameplaying in a Multi-Agent Environment (2): Exploration vs Exploitation

Most automatic game playing involves some sort of algorithm or model that can manage and use limited resources to attain the goal of the game without human guidance. The limited resource may be lives (e.g. Super Mario), playing pieces (e.g. Chess), number of turns or time. Usually we choose one or more actions which use one or more resources (e.g. using our turn move a piece in Chess). To train the model usually the same game is played multiple times to build up the knowledge. See this post for a more detailed description of automated game playing.

The automated game player’s (AGP) primary task is to balance exploration of the state space of the game with exploiting (i.e. taking specific actions) to ‘win’ the game.

Exploration

The exploration task deals mainly with finding information about the state space, the value associated with each state and how actions influence state transitions. This allows us to select the optimum actions in the Exploitation stage. Exploration is not just about about movement actions. The AGP may want to spend a turn ‘exploring’ a new action like extracting a resource or attacking an enemy and assessing the corresponding reward.

Exploitation

Exploitation is about using the information we have gained from exploration and choosing one or more actions. Since exploitation also uses up resources we want to balance information gathering with information use. For example, in many games there is a choice between ‘fight or flee’, the AGP could adopt a policy of ‘flee’ all the time or it could choose to explore the fight action and update its policy to be a mixture of both or it could find that exploring the fight action led to much better outcomes therefore it may decide to have a pure fight policy. But in a game there are limited opportunities to choose what to do, potentially infinite state space and state transitions that are not deterministic. Lets pick these apart one at a time using the Knights and Dragon game.

State Space and State Transition from the Knights and Dragon Game

State pace is a set of values that can be used by AGP to reason about the game environment. State space can directly represent the game (e.g. chess grid with players pieces) or indirectly (e.g. field of view in first-person games like Doom).

To explain this we can look at the Knights and Dragon game. The game is now a simple 10×10 grid with green squares representing farmland. There are two knights and a dragon. The dragon is controlled by a set of simple rules: detect nearby players, move towards closest player then attack closest player if in range.

The knights are controlled by the AGP. The knights don’t know anything about the state space to begin with. They have the following actions available: rest, grow food, search for food, attack, move (up, down, left, right) based on the current state.

The state space for a knight is made up of the following six values: knight’s health (max 10), knight has food (Boolean 1/0), current position of the knight (x and y), food on the current tile (max 10), dragon’s health (max 30).

Actions transition the knights from one point in the 6d space to another point. For example take a knight with state space: (10,1,5,5,10,30). If the knight takes a ‘search for food’ action then it moves to (10,1,5,5,8,30) because that action extracted 2 food from the current cell (represented by the 10 in the first point).

In general the state transition for Knight 1 in current state S1 taking action ‘move’ can be defined as a mapping.

Figure 1: One-to-Many State Transitions

The picture above shows the one-to-many nature of state transitions in this game where S1 to S6 are states in the game. Taking the ‘move’ action when in state S1 can take us to states S3, S5 or S6. This is due to the dynamic nature of the cell state (representing the food resource).

Initially Knight 1 has no idea about state transition mappings. Therefore there is no option but to explore and build up the state transition map before the AGP has enough information to start exploiting.

State Value

As the state transition map is built up we need a way to attach a value to each state so that we can start exploiting it in selecting the best action to take. In the current environment the reward is simply survival at the end of each turn. Each Knight gets +1 reward if they end their turn with full health (= 10). We can use Monte-Carlo or Temporal Difference (TD)methods to iteratively build up the value of each state.

Since in this case we do not have 1-1 mapping between ‘before’ and ‘after’ states, the AGP cannot directly evaluate the utility of taking an action. If there was 1 to 1 mapping then the value of taking an action would be same as the value of the ‘after’ state. One way of finding a combined value of an action is to take an average of the value of the states [S1, …, Sn] reachable by taking that action. For example, going back to Figure 1, if we have built up State values for S1, S2,.., S6 using TD method then when we are in State S1 we can evaluate the utility of taking the ‘Move’ action by averaging State values of S3, S5 and S6 because so far the AGP has learnt these three possible next states associated with this current state and action.

The expression so far I used above is important to explain. Typically the AGP has only one task – to ‘win’. The AGP should not need to know every state transition to ‘win’ because that would be quite difficult for anything but the simplest of games. Therefore, as AGP plays and discovers more of the transitions it will reach a point where it will be able to ‘win’ by utilizing what it has explored. Before that point the AGP can only decide based on what transactions have been explored. After that point there is no real incentive to explore unless the reward function is modified.

Figure 2:

Looking at Figure 2, we may find that ‘winning’ requires the AGP to transition to State S7 – which at this point we are not aware of as we have not come across a combination of current state and action that takes us to S7. Once we discover S7 (in this example from S2 taking the ‘Move Down’ action) we will quickly build up its value using methods like TD.

Another important element for the AGP is memory. If the AGP forgets the state information between each game then we will be forever exploring and never reach a state where we can exploit, unless the games are long enough to build up transition mapping every time we play. But that would like learning from scratch the different strategies of Chess every time we start to play.

Sample of three states with corresponding state values:
(10, 1, 10, 30, 1, 1): 9.6557
(10, 0, 10, 30, 1, 1): 7.9430
(10, 1, 8, 30, 1, 1): 7.9784

TD Update Equation:
V(s) <- V(s) + a*{(R + g*V(s')) - V(s)}

V(s): Value of current state (s)
V(s'): Value of new state (s')
R: reward when transitioning to new state (s')
a: alpha - constant
g: gamma - reward discount

Above we can see a sample of three states with corresponding state values. Also the TD Update Equation is provided. All state values are initialised to 0. Reward (R) is +1 for every step that ends with full health. Over time, as we explore more of the state transitions, the state values converge. We keep following the chain of states till we reach a terminal states defined as:

  1. Failure: Health of any Knight drops to 0
  2. Success: Knights survive 250 turns each

Results

To see the exploration vs exploitation in action we can run some easy experiments with our Knights. We start without any state information. We prioritise exploration by ensuring all actions are tried from the current state.

Once the AGP finishes exploring all the actions for a state, the next time it encounters that state it will start using estimated next state value to select the action. This estimation becomes more accurate as the state values converge over games.

We can tune this by adding a probability that the highest valued action will be disregarded and another action is chosen randomly.

Figure 3: Game lengths as we increase randomness

In Figure 3 we can see different probabilities of disregarding the highest valued action and how it impacts the game outcome. The game length in number of turns is given on the Y axis and number of games on the X axis. Whenever game length reaches 500 we assume that the AGP (controlling the Knights) won the game.

No Randomness: In the case where we never disregard the highest value action (blue line) we see after exploring and learning the state transitions (around the 19th time it plays the game) the AGP discovers a good solution and continues to exploit it. Following this discovery all the games reach the full 500 turns required to win.

1% Chance of Ignoring Highest Value Action: In this case we discard the highest value action 1% of the time (orange line). We see that the learning approaches the winning tactic but the randomness does not allow the AGP to settle into a winning routine.

10% and 50% Change of Ignoring Highest Value Action: As expected in this case (red and green lines) the learning is completely overshadowed by the randomness and AGP does not settle into any winning routine.

Finally, the winning tactic

So what is this winning tactic that the Knights have converged on? The winning tactic is to ignore all the actions except grow food and search for food. This is a farmer strategy where the Knights settle down and don’t move, don’t get close enough for the dragon to detect them. Its a perfect loop where following this strategy ensures all games are won. That is why we see the perfect success record (blue line) once this strategy is ‘discovered’. No other state value will come close to beating this.

Figure 4: Steady state win solution – Knights stay put and become a farmer – grow food and consume it

Code:

Code can be found at: https://github.com/amachwe/pgame/tree/mdp

rl1.py – contains the state transition building logic and the ‘brain’ for the AGP: https://github.com/amachwe/pgame/blob/mdp/rl1.py

player_ga.py – contains a simple fully informed version of the ‘brain’ where we can workout the exact consequence of taking an action as the transition functions are available: https://github.com/amachwe/pgame/blob/mdp/player_ga.py

I have not cleaned the code but if you are interested I will be happy to explain the basics! Just leave a comment.

Gameplaying and Reinforcement Learning in a Multi-Agent Environment (1)

Gameplaying is no child’s play! Simple games can have deep tactical and strategic choices that can have a big impact on the end result. Modern board games include multiple different gameplay mechanics like dice rolling for probabilistic decision making, decision making under incomplete information, resource management and so on. They have now given way to games that can be played by a single player where either a set of rules (e.g. Legend of Drizzt) or a smartphone app (e.g. Mansions of Madness) play the role of the Game Keeper/director.

Each game has a target/goal that helps define the win/loss conditions. This may be static (kill your opponents ‘king’), evolving (find something then do something with that object) or time-based (e.g. survive 10 turns).

Game turns are usually divided into phases which groups behaviour different class of agents (such as human players, monsters, world effects). So each game turn might begin with a preparation phase, a hero-action phase, a monster-action phase and so on. In the hero-action phase (usually) the human players can choose one or more actions from a set of actions (e.g. move, explore/search, attack etc.) and execute it by spending some limited resource (e.g. action point, potion, item etc.). This is where the tactics and strategy come into the picture. Similarly, during the monster-action phase we may use some rule-based mechanic to decide what the monster does (e.g. monster moves one square closer to the nearest hero) or this can be decided by the Game Keeper/director. Finally there are always constraint mechanisms that help decide the reward signal (e.g. health, turns left) as a consequence of our actions. For example – my hero can choose to fight a monster or attempt to sneak away – what should I choose? We might make a tactical choice to sneak away if our health is low or risk an encounter if we feel we are much stronger than the monster. Games can also have a time-constraint where once the time runs out something good/bad happens.

Game environment usually consist of some grid system which allows for exploration and a set of agents and game elements (e.g. resources, locations) that are oriented on the grid. Grid system may provide complete information (i.e. all parts of the grid are visible) or incomplete information (i.e. the grid is built up as we play and make choices).

Similar concepts also exist in video-games. But they are lot less discreet. For example when we play a shooting game like Doom we move in a continuous way. There is no grid (or a the grid has infinitely small squares). We still have mechanics around action choices and reward signals.

As an example for a common game: Chess –

target is to kill your opponents king

grid is the chess board

agents are the two players (or 1 player and 1 AI) – chess pieces are the tokens used to play the game

phase in chess consists of a phase for each player to move

action just one basic action of movement – this includes the action to ‘kill’ an opposing piece

reward win/loss, number of pieces left etc.

constraints number of pieces left, in some fixed length games – the number of turns etc., number of squares on the chess board

Game Playing Gym

So why this lengthy discussion around this topic? I want to explore concepts around automated-gameplaying. I was also interested in building a game environment. Therefore, I built a ‘gym’ environment using python and PyGame where I can play around with different automated game-playing methods.

target is for both knights to survive 250 game turns per knight

grid is the environment consisting of mountain, water and grass squares

agents are two knights and a dragon. The dragon operates on a fixed rule-set (scan, move and attack nearest). Knights will be controlled by automated gameplaying methods.

phase – there is a hero phase for each knight followed by a monster phase for the dragon

action seven actions to choose from: move (x4 up, down, left, right), search (for food), farm (grow food), rest (heal)

reward food quantity, health quantity, amount of area explored

constraints health, food – if food goes to zero health starts to drop – all actions cost 1 food


Figure 1: Example of the Game Environment

In Figure 1 we can see the game environment. Green blocks are grasslands where food is available and farming can be done. Brown blocks are mountains and blue blocks are water. The yellow block is a grassland block exhausted by searching for food. Exhausted block can be regenerated by using the ‘farm’ action.

Two white blocks below the barren block are the two knights and the white block to the right of it is the dragon. Against each Knight we can see their food (uncapped) and health value (capped at 10).

Reward Maximisation – No Constraints

Video 1: Basic survival – gather and move

In the above video you can see the dragon is taking a snooze and the knights are busy exploring the land. You might think that the knights have been ‘programmed’ to avoid mountains and navigate through. But that is not the case. We use reward signals for deciding where the knights should go.

As we know in any kind of agent-based system we have a loop like below:

  1. Agent reads state of the environment (or observes the environment)
  2. Agent reads the reward signal (zero for first loop)
  3. Agent decides and executes next action on the environment
  4. This causes the state of the environment to change and a reward signal to be generated
  5. Check state/observation for Termination condition, if not met then go to (1)

In our case the knights are getting the full state of the environment as opposed to observing/sampling the state indirectly. The environment state consists of their health, their food and their location (which includes cell type and the food available if a grassland type of cell).

Since state transitions are not stochastic and the knights have full access to the state transition functions they can evaluate each of the seven actions at each stage and select the action that maximises the reward (in which health is the most important component) in the next step. This simple rule can lead to a lot of sophisticated behaviour that you see in the above video. Even there note how there are absolutely no constraints on the knights and they can keep moving, searching and stockpiling the food (see the food number go up!). These knights are just greedy!

We can make the state transition stochastic by randomly changing the amount of food the agent gets when searching or the direction of movement when selecting a move action.

Again if we have the transition graph (generated by Markov Decision Process) available then we can easily use Value Iteration or Policy Iteration to come up with an optimum policy for each state. I will show an example of this in the next post.

Reward Maximisation with Constraints

Let us make life slightly difficult for our greedy knights (well at least for one of them). In the video below we just change the starting position of the dragon. Now the dragon is going to continuously harass one of the knights.

Remember we have not changed anything else in the program! Just moved the dragon closer to one of the knights so that it enters the dragons area of awareness. The simple rule-based AI of the dragon will ensure it tracks the knight.

Survival under constraints

Now our knight has to be slightly cleverer than before! It can no longer just gather food. It now has to gather food, loose food to heal (if dragon has attacked successfully) and move. It may also choose to regenerate an area if it can afford to. Remember again reward signal has health as the most important component. The knight, using reward maximisation, automatically starts doing this in a sequence. We see that it keeps moving and surviving (keeping health > 0) while it collects food to heal. This adds a big constraint to its food gathering capability and doesn’t allow it to stockpile any food. The other knight – not bothered by a dragon – is able to continue its greedy behavior. We can tune the aggressiveness of the dragon by tuning its attack probability.

We can see in Figure 2, for a high attack probability (0.9), the knight under attack (knight 2) is overwhelmed and killed (compare with knight 1 that is steadily stockpiling food). This means that knight 2 is not able to gather, heal and move fast enough under the relentless attack of the dragon. We may improve survival chances if we had an ‘attack’ action?

severe attack by dragon - food
Figure 2: Knight food levels under heavy attack

We can see in Figure 3, for a lower attack probability (0.6), the knight under attack (knight 1) is not overwhelmed. Whilst it still starts falling behind the other knight it is far from any real danger of death. In this case the dragon is a bit lazy about attacking!

low constraints on food low attack
Figure 3: Knight food levels with lower attack probability

TicTacToe: Playing Against the Machine

TicTacToe is a simple game but it does have some tactical depth. With limited moves and turns it can be easy to create exhaustive search based solutions to implement the logic for a Player vs Computer game.

It is also the perfect game for anyone who wants to start with AI programming (e.g. Reinforcement Learning). Keeping this in mind I created a test-bed with two ‘brains’ – one that uses Induction (taking advantage of the finite state-space) and the other that uses Pattern Matching (taking advantage of the fixed grid nature of the game).

The code in python can be found on github:

https://github.com/amachwe/tictactoe

Here is the readme that explains how to use it:

https://github.com/amachwe/tictactoe/blob/main/README.md

Currently neither the Induction or Pattern Matching brain really learn anything. This is because we can do an active search of the full state space to plan each move (given the relatively small size of the state space).

Patterns in the Pattern Matching brain are provided as ‘knowledge’ but these can just as well be learnt using Reinforcement Learning methods.

Have fun playing the game or using it as a test-bed for your own AI Tic Tac Toe playing brain!

Feel free to comment to ask questions/provide suggestions!

Almost a Customer!

Letting people know that you have something interesting to ‘sell’ is just the first step. Once they learn about your product there is still the small matter of completing the sale and delivering the service/item purchased to the customer.

I wanted to share a recent experience I had as a potential customer. I learnt about a product through an ad on a social media platform. They were also advertising an offer on the product for £7.50. This was a small vendor selling a speciality product.

When I clicked through to the checkout I got a rude shock. The total price was now showing as £11.50! They had added £4 for delivery. I could get free delivery if my order was more than £20 but I didn’t want to order that many items! I decided that the value I was getting was not matching the total cost I would have to pay (so called ‘net value’ = – £4). So I decided to abandon my ‘full’ basket.

This is called the ‘Abandoned Basket’ problem – and it is seen in bricks-and-mortar stores as well where people simply leave a shopping basket with items and leave the store.

So one might have thought that is the end of the story? But no! Things have become a lot more ‘technical’.

A few hours later I got an email. Before showing me the real price or anything that might scare me away they had taken my contact details! That means they could try and change my mind at a later date. Unlike in a bricks-and-mortar store an e-retailer can chase after prospective customers (GDPR notwithstanding).

The email was not a normal ‘you have items in your basket – click here to complete your purchase’. No way. They were a lot cleverer than that. They had done their research. The email identified high-delivery costs as a common reason why people don’t complete their purchase. It also attempted to justify £4 worth of shipping costs when the item was coming from within UK (I don’t know why?).

But I was still not convinced and I ignored the email. Then a few hours later I received another email. This one was offering me £3 off if I spent at least £10. This meant my net value went from – £4 to -£1 and I did not need to spend a lot more than what I was willing to.

In the end they successfully converted an abandoned basket into a sale and I received the items on time and in good condition!

We can see three main elements in this ‘success’ story:

  1. Getting a foot in the door by capturing customers details before they can ‘run away’ – this gives them a second chance at converting the customer
  2. Understanding what made the customer run away in the first place and attempting to arrive at an acceptable ‘middle-point’
  3. Ensuring that the product/service delivery is pain free to encourage the customer to order again

The Brave New World of Debt-to-GDP Ratio!

What is the Debt-to-GDP Ratio?

Simply put, it is the ratio of all the government debt carried by a country divided by the productive capacity of the country. This is similar to the debt-to-earnings ratio used to evaluate the financial worth of companies as well as individuals.

Typically if an individual or a company has a bad debt-to-earnings ratio they will find it tough to get a loan or attract investment. But debt-to-GDP doesn’t work the same way because not all countries are the same!

How does the Debt-to-GDP Ratio work?

Debt by itself is not bad. Similarly, a rising debt-to-GDP ratio may not be a bad thing. Why? Because borrowing is not bad if it leads to a growth in productivity. Productivity here is linked with one or more objective measures like income growth, we are not talking about subjective measures like ‘personal’ growth.

For example, if you as an individual borrow money to buy a car that you will drive as a taxi during the weekends as a second job, then while your debt has increased so has your income (assuming everything goes well). As long as your income (which can be used to measure productivity) increases faster than your debt, things will be fine. Obviously, individuals are limited by how much they can increase their income within the time frame of the borrowing. But when it comes to a country the limits are lot more relaxed. A country can always find productive uses for the money it borrows. Some examples include: strengthening infrastructure, improving education and improving connectivity (both national and international).

If productivity of an individual or a country increases faster than debt then they become an attractive target for future loans.

The flip side is more interesting! If a person spends the borrowed money in meeting day-to-day expenses then it is unlikely their income will rise faster than the debt, if it rises at all. Such an individual will find themselves in trouble very quickly with their creditors. When it comes to a country this logic starts to fail. Some countries end up attracting money even if things are bad all over. In fact, they keep attracting money even if they are not doing so well and are at the heart of a global financial crisis!

We can see this clearly in Figure 1 where USA and GBR (UK) have been borrowing heavily. Their debt-to-GDP ratio has a ‘step up’ right after both countries started borrowing to spend their way out of the 2008 Financial Crisis. The interesting thing is that this data is mostly till 2018 and we expect a similar (perhaps larger) ‘step up’ due to Covid-19 relief spending when we review the data for 2020!

Figure 1: Debt-to-GDP ratio for several countries and the Average debt-to-GDP ratio of major developed countries + India, China and South Africa

A Question of Trust

‘In God we Trust’ is the official motto of the USA. For the financial world it is ‘In the Dollar we Trust’. That explains why, where other countries have had massive backlash to high debt-to-GDP ratios in terms of no access to cheap borrowing, rating downgrades and currency devaluations we can see time after time, during a crisis, funds from all over the world flowing into the US financial system allowing it (the US govt.) to borrow cheaply! This is similar to how when facing a storm all fishing boats rush back into the harbour. This is one reason why it was relatively easy for the US to propose borrowing massive amounts of money (some $3 trillion) to support its economy through the Covid-related lockdown and beyond.

There is a similar narrative of stability and productivity around the UK. Always seen as a strong player in the world of financial services and second only to the USA in the financial sector. UK has similarly been borrowing a lot more without the corresponding growth in GDP. The first Conservative Government of David Cameron (2010 onwards) sought to stem the tide of borrowing by introducing ‘austerity’ and ending the massive spending spree of the previous government that was dealing with the 2008 financial crisis. There were all kinds of positive signs that despite the impact of Brexit on growth, the debt growth was coming under control and ‘austerity’ would end for good. All this was before Covid-related lockdown.

Only the data from 2020 will tell the scale of ‘step-up’ in the debt-to-GDP graph.

The Future

If you look at Figure 1 the debt-to-GDP ratio of all countries presented is heading only in one direction – ‘up’! It is either a gentle slop of a hill or a steep step of a plateau. As a point India (orange dots) may seem like the odd-one-out but that is not the case as in the recent budgets the Govt. has been forced to let the deficit widen (data is only till 2018) and also there are doubts as to the true figure of the Govt. debt.

The big tip of the iceberg question is ‘what happens next’? If the US/UK are the safe-harbours what happens when they become less and less safe, especially after Covid? Would that reduce their appeal? What ‘safe harbour’ will all that money seek? When does it become unsustainable? Who are the debt-holders who will take the decision to declare the situation unsustainable? Does a smaller population help in faster recovery?

To give an example, the cash rich economies like China, who have a massive surplus, behave like a fast-food chain. They want you to keep eating more of their food but also not fall ill. Their food is money and the delivery mechanism is through the world of finance. It is in their interest that their target markets are healthy so that they can continue buying from China. Where China cannot find a big market they plant the seeds of one by financing infrastructure projects to improve its access to trade routes. So it will be interesting to see how the net-exporting countries behave over the next 1 year. This also makes the current UK 5G ban on Huawei equipment very interesting.

Blast from the Past

As a final remark I need to mention what one of my favourite economists John Maynard Keynes said about this topic. Politicians remember the first half of his advice: it is fine to run a deficit (i.e. spend more than what you can earn) in times of great need (e.g. the Great Depression). But they forget the rest of his advice that the Govt. must balance the budgets during the times of plenty.

This is common sense. When you have good income levels it is logical to use that to reduce your debts so that in the time of scarcity you have a lower debt burden and more money left for your personal needs.

But this is also political suicide – no elected Govt. would survive if it told people that it was going into austerity mode when things were going well [1]. This is one of the big reasons we see a constant increase in debt-to-GDP across the world as shocks and crisis are never in short supply and it is unpopular to claw-back when things are going well. The thinking here is that if you grow your productivity (e.g. measured by income) fast enough you can always keep getting a bigger loan and stay one step ahead of the debt-collector.

Or if you are ‘big enough and transparent enough’ as a country, people will always be willing to lend to you (what else will they do with their money?).

Sources of Data:

https://data.oecd.org/gga/general-government-debt.htm, https://tradingeconomics.com/india/government-debt-to-gdp, https://tradingeconomics.com/china/government-debt-to-gdp, https://tradingeconomics.com/south-africa/government-debt-to-gdp

Notes:

[1] Two examples where this did not happen from the World’s largest democracy India: demonetisation and maintaining high domestic fuel price when internationally crude oil prices have fallen. In both the cases strong steps were taken by the elected Govt. and they still came back to power with a larger majority. Unfortunately, in both the cases Govt. managed to loose the advantage gained from these tough steps due to mismanagement.

Let’s Not Waste a Crisis!

The ongoing COVID-19 related suppression of economic activity will impact incomes across the board. Irrespective of how the income is generated (e.g. business, employment, self-employment) the impact can be either positive, negative or uncertain.

  • Positive for those whose incomes are not disrupted or are increased due to demand (e.g. PPE manufacturers, health-care staff, delivery drivers).
  • Negative for those whose incomes have been disrupted without any relief in sight (e.g. restaurants, people who have been laid off with bad prospects for getting another job).
  • Uncertain for those who have been furloughed or laid off but with good prospects for getting a job.

With anything between 6-11% contraction predicted, the majority of the cases should fall in the ‘Uncertain’ category (I predict 4-7%) who will move to either Positive or Negative category over the next year or so.

Why do I say that?

I say it because there will be different responses to the challenges, from restructuring, process improvements to failing fast and even retraining/reskilling (both at individual level and at an organisational level). Depending on how effective a business is at transforming itself to survive, a lot of the people in the ‘Uncertain’ category will quickly transition to the ‘Negative’ category.

One of the main transformation patterns is to carry out process improvements/restructuring with increased automation so that costs decrease and production/service elasticity increases as incomes fall initially but then recover over the medium and long term.

This group of people who jump from Uncertain to Negative is the BIG problem as this can trigger a long term contraction in consumption. How can we help these people reskill and retrain so that they can re-enter the job market? What can we do to support people as the pressure to automate increases as business income contracts?

Universal Basic Income

One possible answer to many of these questions is Universal Basic Income. If we provide people guaranteed support with basics (e.g. food, rent) then we are not only cutting them some slack but also decoupling ‘survival’ with ‘growth’.

Universal Basic Income (UBI) is a simple concept to understand: all citizens get a basic income every month irrespective of how much they earn. This is guaranteed from the day they turn 18 till the day they die. They may also get a smaller percentage from the day they are born to help their parents with their upkeep.

See this TED Talk by Rutger Bregman for more on this: https://www.youtube.com/watch?v=aIL_Y9g7Tg0

With UBI a recession will not impact the basics of any household. It will provide a safety net for families and individuals. It will also allow people to develop their skills and innovate.

There are a few wrinkles in this. Firstly, how should we prevent inflation as ‘free money’ is handed out to people? One proposed mechanism is to use a different class of money from the currency of the country. This UBI money cannot be used as a store of value (i.e. can’t be lent for interest), just for limited exchange (e.g. food, rent). This is similar to the US Supplemental Nutrition Assistance Program (SNAP) – also known as ‘food stamps’ (https://en.wikipedia.org/wiki/Supplemental_Nutrition_Assistance_Program)which can be exchanged for certain types of food. Many other countries have tried this experiment (such as Finland, USA, Canada etc.). This form of money should also ‘expire’ periodically so that people don’t start using them in a ‘money-like’ way.

Another challenge is how do you convert the ‘temporary’ UBI money into ‘permanent’ currency. This is required for the businesses accepting UBI money to be able to pass it down the supply chain (both locally and internationally). For example if you buy all your groceries with UBI money and it is not convertible to currency then how will the grocery shop pay it’s staff and suppliers. What if the suppliers were importing groceries from other countries – how would they convert UBI money to any international currency. In SNAP, the stamps are equivalent to money. It doesn’t have the same impact as UBI as its cost is a fraction of the total US GDP (0.5%).

Still, one should never let a good crisis go to waste! Time to think differently.

What Happens Next?

In this post let us think about what happens next as we start to come out of the Covid-19 related lockdown.

No country can claim to be immune from the economic effects of the Covid-related lockdown. However, as countries start to emerge from the lockdown some will rebound faster than others.

What is happening now?

Let us next look at where we are today. Today, large number of people and businesses have seen the flow of money reduce to zero. The expectation of a return on investment is low for a large section of the economy. That said, certain sectors are doing quite well or as normal (e.g. groceries, online retail) as they are getting overflow business.

In this situation with little or no money going to people / businesses someone has to step in and be that ‘credible borrower’ and borrow on behalf of those who are struggling. This is the Government as the ‘credible borrower’ which then passes the borrowed money on to its citizens in a low-waste manner one hopes. One point here is that it is easy for a Government to print money rather than borrow, but that can lead to inflation without actual growth – so called ‘jobless growth’.

We can take the current situation as artificial suppression of demand and supply (as people loose incomes and stores are forced to close/reduce visitors).

This can also be understood as a scenario where blood supply to an organ in the body has been blocked. The body reacts in the very short term by reducing the function of that organ and rushing out chemical support to suppress pain but in the long term the body is severely impacted unless the block can be removed and/or another path can be found to deliver the required quantity of blood.

What happens Next and How to Deal with it?

It all comes down to effective planning and effective use of people, processes and tools.

Businesses that have or are able to quickly get the required plans in place for short and long term changes to how they work will benefit from overflow business.

People who are able to re-skill or move from impacted areas to areas of new opportunity will be able to benefit from continued employment during the rebuilding period.

Both the above things should allow some blood to flow to the organ but it does not restore normal supply nor fixed the original damage that resulted in a block.

Repairing the Damage

The repair will start once the lockdown ends. Those countries that release the lockdown earliest (and are able to ride the second wave of infections) will have ‘first movers’ advantage towards normalisation. This should also promote local business that step in to fill the gap from imports where possible.

The key point to keep in mind here is that we will not go back to status quo. Just as scar tissue is never as smooth as the torn skin it replaces. We will loose some businesses. Some people will fall into debt and be unable to recover without help.

Due to loss of incomes, social distancing and widespread work-from-home we will find demand continues to be suppressed for some time to come. This will be especially true for ‘non-essential’ goods. This means the suppressed demand must be unlocked using some of the options we will discuss below.

Who sinks/swims is down to how they prepared during the crisis for the post-crisis period (i.e. if they did not look to change business-as-usual and let a good crisis go to waste then they will sink) and how effectively they can implement those strategic plans in the coming months. This is a good example of Darwin’s Survival of the Fittest.

Who will survive:

  1. Those who are quick to plan and implement new processes that allows them to generate revenue.
  2. Those who have deep pockets to fall back on, for the next 12 months (at least)
  3. Those who are able to focus on their strengths and optimise resources – when we look at (2) we must remember “Markets can remain irrational for longer than you can remain solvent” (by John Maynard Keynes)
  4. Those who are directly benefiting from the crisis (short term survival)
  5. Those who enjoy a good name in the market or are ‘expected’ by the market to bounce back quickly

But what is the Recipe for Success? What should we do more of as a business?

  1. Advertise: Replace front-office with a slick website, smartphone app and/or virtual agent (even a chat-bot helps handle the first level of queries)
  2. Process transformation: Reduce the need for manual processes in business operations – this is not something only multi-million pound business need to do! In fact this is something everyone needs to do!
  3. Digitise and Automate as much as possible – from fundamental building block apps (e.g. billing) to more advanced planning, optimisation and prediction apps (Here is a golden chance for AI at the lower price-point. Or even local AI consultancy)
  4. Concentrate on strengths and focus your resources on the service/product that provides the greatest rewards – enable home delivery where possible – smart phones + hybrid/electric vehicles should reduce cost of operations and bring home delivery to the same price point as in-store
  5. Don’t stop innovating.. innovation is the hidden strength of any business (large or small!)

As an individual, facing an uncertain future in terms of employment, lot of the above points are just as relevant (once the context is changed):

  1. Advertise your existing skills and experience (make a website, LinkedIn profile), talk about your interests and hobbies! Blog!
  2. Look inward: Look at all the good stuff you have done, all the mistakes you have made and the lessons you have learnt. Try changing something small about yourself that you feel will improve the way you feel about yourself. For me this was ensuring I take in a lot of outdoor play time with my kids!
  3. Prepare your tools: make a CV, take stock of where you have been and where you want to get too! You won’t get another chance like this to plan your career!
  4. Concentrate on your strengths: reduce expenditure, improve efficiency by doing the important things and ignoring things that lead to waste of time, money or both. One personal example: we started cooking more at home which resulted in not only money saving but also us discovering new things that we could make at home!
  5. Don’t stop learning! Now is the time to take a risk. Make sure you use all the tools available to engage with people who are leaders in your field of learning as well as fellow students – this can be anything – from cooking to a language
  6. Don’t stop thinking and creating. Write a short story, create a new dish, draw a picture, change the layout of your living room! These act as massive confidence boosters

Additional Thoughts: Automation

Automation was on the rise before Covid. The bigger players have already moved online and use automation enabled IT therefore continue to sell effectively (albeit within constraints). But the contact-less nature of the solution to this problem will push app/online interaction even more. As this happens, it makes it easier to automate the interaction. Two small examples:

  1. Pizza shops now only support cashless delivery, no collection. Therefore, all my interaction with the pizza shop is through their website or an app (e.g. JustEat). The pizza is placed on my doorstep and I hardly even see the delivery person as they back away more than 2 meters and leave as soon as they see me pick-up the pizza.
  2. Food stalls in various food markets have started home deliveries (again cashless and contact-less). Earlier they would hire staff to manage long queues, today they operate behind a slick website (that you can throw up in a few hours), a scheduling tool, and WhatsApp messaging to personalise the interaction.

This effect when combined with the long term trend of more people working from home (which is bound to accelerate now) is an opportunity for small business to deliver local services through different app-based platforms involving lots of automation (to make it cheaper). The smaller players have to make use of the same force-multiplier tools, platforms and channels as the bigger players right now! The most basic one is the ability to accept online orders and payments.

Now that people don’t travel for work then they no longer form a captive market for food vendors, coffee shops and bars. But these things can come to their doorstep! With automation enabled IT the cost of home delivery can be managed especially with the added benefits of scale.

Finally: I am still waiting for the day I can order Starbucks coffee to my home for the same price (if not cheaper) as what I get in the stores. Starbucks could open coffee-making kitchens in different areas and serve the area from there. Automation will help by providing seamless links between different stages, AI-based planning and prediction of demand.

The Advantage of Covid-19

Covid-19 has been wreaking havoc across the globe. But this was also expected given the fact that we have not been the best of tenants for Mother Earth.

All the doom and gloom aside, Covid-19 and the mass lockdowns are teaching us a very important lesson about the future of automation and technology.

In a single line:

A secure future requires smart people working on smart devices using smart infrastructure!

Figure 1: Relation between Smart People, Things and Infrastructure.

Figure 1 shows the interactions between Smart People, Things and Infrastructure.

The Covid-19 crisis, which has brought life to a standstill, has exposed the weakness of our automation maturity. Services from haircutting to garbage collection have been trimmed back, mostly as a proactive step. Whatever automation we do have, has helped tremendously (e.g. online grocery shopping) even as people’s behaviour changed overnight as panic set in.

So what is the panic about? What are the basics that we need? The panic is about running out of resources like food due to a collapse of supply chains which have been optimised to reduce warehousing costs.

Supply chains (Logistics) are heavily dependent on people. From farmers growing crops, workers building stuff to drivers transporting the product to the shops (or directly to your home).

This is not the only critical system to break down if large number of people fall ill at the same time.

Healthcare is another area that has been impacted because of the lockdown. Care has to maintained to protect vulnerable people which means minimising contact. This increases the vulnerability due to isolation.

Education has also been impacted with schools closed and exams postponed or cancelled. This might not seem like a big problem but consider the impact in future results.

Another area of concern are the utility networks. Can we truly survive with disruptions to our electricity or water networks?

If the automation is improved in the above areas then we would become more resilient (but not immune) to such events in the future which is as difficult to achieve as it sounds!

Bottom-up Automation

Before a drone can be piloted remotely for hundreds of miles or a truck driven under human supervision from a port to a local warehouse we need robust telecom infrastructure to provide reliable, medium-high bandwidth, low-latency, temporary data connections.

This magic network has three basic ingredients:

  1. Programmable network – devices that can be treated like ‘software’ and provide the same agility > significant progress has already been made in this area.
  2. Network slicing – to efficiently provide the right resource to the requesting service > lot of work ongoing in context of 5G networks
  3. Closed-loop, light touch orchestration – to help people look after a complex network and help make changes quickly and safely when required (e.g. providing a reliable mobile data link to a drone carrying a shipment of food from a wholesaler to a shop, for remote piloting use-case) > significant progress has been made and lot of ongoing work

Using such a network we can build other parts of the puzzle such as smart roads, smart rails and then smart cities. All of these help improve automation and support increasingly light touch automation use-cases.

Smart Things

Once we have the Smart Infrastructure we need Smart Things to use them.

For Logistics and maintaining a robust supply chain during a pandemic we need a fleet of autonomous/remotely supervised/remotely piloted vehicles such as heavy-lift drones, self-driving trains/cars/ships/trucks. We also need similar assistance inside warehouses and factories with robots carrying out the operations with human supervision (so called Industry 4.0 / Lights-out factory use-case).

Healthcare – requires logistics as well as the development of autonomous personal health monitoring kits that augment the doctor by allowing them to virtually examine a patient. These kits need to become as common as a thermometer and should fulfil multiple functions.

For scenario related to caring for vulnerable people, semi-autonomous robots are required that can do lot of the work (e.g. serve dinner).

In case of a lockdown, a teacher should be able to create virtual classrooms with similar level of interactivity (e.g. via AR/VR) as in a real classroom.

To maintain water, electricity and other utilities we need sensors that provide a snapshot of the network as well as actuators, remote inspection and repair platforms etc.

For all of this to be done remotely (e.g. in a lockdown scenario) we need a robust telecoms network. Clearly, without a data connection people would no longer be able to deal with the economic, mental, physical and emotional shock caused by a lockdown.

Smart People

So who will be these people who can pilot/supervise a drone, carrying a crate of toilet rolls from a warehouse in Bristol to a shop in Bath from a remote location? Well trained people of course!

This requires two important things:

  1. Second Job: Everyone should be encouraged to take up a second discipline (of their interest) in a semi-professional capacity. This helps increase redundancy in a system. For example, if you are a taxi driver and have an interest in radio – maybe your second job can be of a maintenance technician.
  2. Thinking beyond data-science and AI: Tech is everywhere and AI is not the final word in hi-tech. People should receive everyday technology training and if possible advanced technology training in at least one topic. E.g. everyone should be taught how to operate a computer but they should also be allowed to choose a topic for deeper study, like security, software development, IT administration etc.

Augmentation technologies should be made more accessible, including providing basic-training in Augmented and Virtual Reality systems so that in case of a lockdown, human presence can be projected via a mobile platform such as a drone or integrated platform within say a forklift or a truck.

Adaptation: This is perhaps the most important. This means not leaving anyone behind in the tech race. Ensuring all technologies allow broad access. This will ensure that in times of trouble technology can be accessed not only by those who are most able to deal with the issues but also those who are the most vulnerable.

All of the above require the presence of smart things!

Conclusion

Thus we have four themes of Logistics, Healthcare, Education and Utilities running across three layers: Smart People -> Smart Things -> Smart Infrastructure. That is what Covid-19 has taught us. A very important lesson indeed, so that the next time around (and there WILL be a next time), we are better prepared!

Digitisation of Services and Automation of Labour

Digitisation of services is all around us. Where we used to call for food, taxi, hotels and flights we now have apps. This ‘app’ based economy has resulted in a large number of highly specialised jobs (e.g. app developers, web designers). It also impacts unskilled or lower skilled jobs as gaps in the digitisation are filled in with human labour (e.g. physical delivery of food, someone to drive the taxi).

The other side of digitisation is automation. Where manual steps are digitised, the data processing steps can involve human labour (e.g. you fill a form online, a human processes it, a response letter is generated and a human puts it in an envelope for posting it). 

In case of a fully automated and digitised service, processing your data would involve ’machine labour’ (with different levels of automation [see http://fisheyefocus.com/fisheyeview/?p=863]) and any communication would also be electronic (e.g. email, SMS). One very good example of this is motor insurance, where you enter your details via a website or app, risk models calculate the premium on the fly and once payment is made all insurance documents are emailed to you. Only involvement of human labour is in the processing of claims and physical validation of documents. This is called an ‘e-insurer’.

Machine Labour

Automation involves replacing or augmenting human labour with machine labour. Machines can work 24×7 and are not paid salaries – thus the cost savings. However, machines need electricity and infrastructure to work and they cannot self-assemble, self-program or self-maintain (so called Judgement Day scenario from the Terminator series). Human labour is still required to develop and maintain an increasingly large number of (complex) automated systems. Human labour is also required to develop and maintain the infrastructure (e.g. power grids, telecom networks, logistic supply chains) that works alongside the automated systems.

So humans earn indirectly from machine labour but in the end automation and digitisation help save large amounts of money for companies by reducing operational costs (in terms of salaries, office space rentals etc.). Another side-effect is that certain types of  jobs are no longer required as automation and digitisation pick up pace.

Impact on Consumption

Now we know from basic economics that all consumption results in someone earning an income. 

For a company, the income is the difference between the value of what they sell and their total costs (fixed + variable) in making and selling it.

A company will increase digitisation and automation with a view to increase their total income. This can happen by targeting automating processes that increase sales or decrease costs. A company will also automate to keep levels of service so as not to lose customers to competition but there will always be some element of income increase involved here as well.

If costs are reduced by digitisation (e.g. less requirement for a physical ‘front office’) and/or automation (e.g. less number of people for the same level of service), it can lead to loss or reduction of income as people are downsized or move to suboptimal roles (e.g. a bank teller working in a supermarket). This also contributes to the ‘gig’ economy where apps provide more ‘on-demand’ access to labour (e.g. Uber).

People consume either from what they earn (income) or from borrowing (e.g. credit cards and loans). If the incomes go down then it can either impact consumption or in the short term lead to increased borrowing. This decrease in consumption can impact the same companies that sought an increase in income by automation and digitisation.

To Summarise:

  1. Automation and Digitisation leads to cost savings by introducing electronic systems in place of a manual process. 
  2. If less people are required to do the same job/maintain a given level of output then employers are likely to hire fewer new workers and/or reduce the size of the workforce over time. 
  3. This will reduce the income of people who are impacted by redundancies and change of job roles. 
  4. This in turn will reduce the consumption of those people which may hit the very same companies that are introducing automation and digitisation
  5. This in turn will further push the margins and thereby force further reduction in costs or increase in consumption from some quarter…. 
  6. And we seem to be trapped in a vicious circle!

This Sounds Like Bad News!

So looking at the circular nature of flows in an economy, as described in the previous section, we can predict some sort of impact on consumption when large scale digitisation and automation takes place. 

As an aside, this is a major reason why ‘basic income’ or universal income is a very popular topic around the world (read more: https://en.wikipedia.org/wiki/Basic_income). With basic income we can guarantee everyone a minimum lifestyle and thereby promise a minimum level of consumption.

The actual manifestation of this issue is not as straightforward as our circular reasoning, from the previous section, would indicate. This is because the income of a company depends upon several factors:

  1. External Consumption (exports)
  2. Amount consumed by those whose income increases due to automation and digitisation
  3. Amount consumed by those whose income decreases due to automation and digitisation
  4. Labour costs attributed to those who implement and support automation and digitisation
  5. Labour costs attributed to those who are at risk of being made redundant due to automation and digitisation (a reducing value)
  6. Variable costs (e.g. resource costs)
  7. Fixed costs

Exports can help provide a net boost to income – this external consumption may not be directly impacted by automation and digitisation (A&D). It may be indirectly boosted if the A&D activities lead to imports from the same countries.

The two critical factors are (2) and (3): namely how much of the output (or service) is sold to people who benefit from A&D and how much is sold to those who do not benefit from A&D. 

If a company employs a large number of people who can be made redundant via A&D activities and a large portion of their consumers are those whose incomes will be impacted by A&D then we have a very tight feedback loop – which can lead to serious loss of income for the employer, especially if it ties in with an external shock (e.g. increase of a variable cost like petroleum).

On the other hand if a company caters to people whose incomes increase with A&D (e.g. software developers) then the impact to its income will be a lot less pronounced and it may even increase significantly.

What works best is when a company can sell to both and has enough space for both A&D activities and manual labour. This means they can make money from both sides of the market. A good example of this are companies like Amazon, McDonalds and Uber who have human components integrated with A&D which then acts as a force multiplier. 

Using this framework we can analyse any given company and figure out how automation will impact them. We can also understand that in the short term A&D can have a positive effect as it acts as a force multiplier, opening new avenues of work and creating demand for different skills.

Breaking Point

Real issues can arise if automation is stretched further to complex tasks such as driving, parcel delivery and cooking food. Or digitisation is taken to an extreme (e.g. e-banks where you have no physical branches). This will have a large scale impact on incomes leading to a direct reduction in demand.

One way to force a minimum level of consumption is for the government to levy special taxes and transfer that income as it is to those who need it. This will make sure those who are unskilled or have basic skills are not left behind. This is a ‘means tested’ version of basic income similar to a benefits system.

The next step will be to re-skill people to allow them to re-enter the job market or start their own business.

Exploring Stream Processing in Java

Java was a relatively late entrant in the functional programming game. Streams, lambdas and other functional programming constructs were introduced in Java 8. Scala and Clojure had already popularised functional programming while Java was stuck in in the Enterprise App space.

In this post we take a gentle drive through the world of Streams. This will make it easy for you to do quite a few interesting things with them!

Streams are a simple concept to understand. At their most basic they are a different way of processing a list structure with few restrictions on what we can do.

The list is treated as a stream/sequence of items, rather than an aggregate collection while:

  1. Hold no state in the pipeline except the current item
  2. Hold no external state (like counters)
  3. Don’t depend on the size of the stream, just know if it is a finite or infinite stream that you are dealing with
  4. Restrict yourself to a limited set of operators

To do this we do need to think that extra bit to recast our good old for loop into a pipeline of stream operations.

What benefits do we get if we do this? The main benefit, if we hold no state (internal or external) then we can seamlessly parallelize the stream processing. Really, a well written stream processing pipleline will run in parallel mode seamlessly. If it doesn’t then you have either made a mistake in pipeline design or have a use-case that is not suitable for using streams.

One consequence of parallel stream processing is that we may need to reduce the results from the different pipelines in the end to return the result. We can also process the resulting items without returning a single result.

Java Streams have what are called ‘terminal’ methods that do reduction for us. These methods behave differently when the streams are infinite that is why we have point (3) above. The methods are:

  • count(): used to count the number of elements in the stream; will never terminate for an infinite stream as you cannot ever finish counting to infinity
  • min()/max(): used to find the smallest or largest value using a comparator; will never terminate for an infinite stream
  • collect(): used to collect the stream items into a single collection (e.g. a list); will never terminate for an infinite stream
  • reduce(): used to combine stream into a single object (e.g. to sum a stream of integers); will never terminate for an infinite stream

There are other terminal methods that do not generate a result or are not guaranteed to return one:

  • forEach(): used to process all the stream items at the end of the pipeline (e.g. to write processed items into a file); not a reduction because no result is returned; will never terminate for an infinite stream
  • findAny()/findFirst(): used to return the first (in order) or any (first from any of the parallel streams); not a reduction because only a small set of items from the stream are processed; will terminate as we want first or any item (we don’t care to wait for it to terminate)
  • allMatch()/anyMatch()/noneMatch(): used to match on all, any or none of the items; not a reduction because it doesn’t really process the stream items; may not terminate

The code block at the end of this post has examples of all the different functions described above.

Real World Example

Image a marble making machine. It produces an infinite stream of marbles of slightly different sizes and weights. We need to perform certain actions based on weight and size of the marble (e.g. paint them different colours, remove ones that are not in the correct weight or size range) and then pack them based on colours into small boxes and then again pack those small boxes into bigger boxes (of the same colour) to send them to the wholesaler.

A simple linear pipeline looks something like this:

  1. check size and weight, if outside correct range: discard
  2. choose a colour based on weight: apply colour
  3. send them to a different box based on colour

Till step 3 there is no need to maintain any state because the size check and colouring steps do not depend on anything other than the marble being processed at that time. But at the terminal step of the pipeline we do need to maintain some state information about which box is associated with which colour to direct the marble to the correct box. Therefore, we can carry out steps 1 -> 3 in as many parallel pipelines as we want. This will give us a set of boxes (each representing a single colour) per pipeline. Step 1 is a ‘filter’ operation and Step 2 is a ‘map’ operation on the stream.

Since we have made full use of parallel streams to manufacture the marbles and put them into multiple boxes, now is the time to ‘pay the piper’ to get a single usable result that can be dispatched to the wholesaler. We need to ‘reduce’ the boxes by again holding little bit of state (the colour of the big box) but this time we are making a box of boxes.

Worked Example in Java

Assume we have a finite stream of unknown size (infinite streams require a bit more care) of whole numbers (i.e. positive integers) and we want to perform some processing like filtering out odd numbers, finding sum of all even numbers in the stream and so on.

While this is a dummy problem it does allow us to demonstrate all the different aspects of stream processing including two of the most common stream operation: filter and map.

We have a data generator function that takes in upper limit as a parameter and creates a stream of whole numbers (using Stream.iterate) from 1 to the upper limit in sequence. This is done so that we can easily validate the result. Full source code is provided at the end of the post that includes the data generator function.

Filter Operation

Filter operation is similar to writing a loop with an if condition inside it that executes the logic inside the loop only if certain conditions are met.

Java Example:

We want to find out the maximum even number in the stream. For this we use the filter method on the stream and pass a lambda to test the stream value if it is odd or even, all odd values are dropped and then we call the max terminal function.

System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).max((a,b) -> (int)(a-b)));

Output: We set maxItemCount to 100 therefore this will return the result of ‘100’ as that is the largest even number between 1 and 100.

Map Operation

Map operation is used to apply functions to a stream to transform. The apply function should not have any side effects (e.g. calling any APIs) and should produce a return value.

Java Example:

Assume that we want to process the even numbers that we identified in the previous example. In the example below we use map to transform a stream of even numbers (as is the output of filter) into a stream of square of even numbers.

System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).map(x -> {
            if(x%2 == 0) {
                x = x*x;
            }
            return x;
        }).collect(Collectors.toList()));

Output: Since we are using the collect terminal method at the end with a list collector (Collectors.toList) we get a list of square of even numbers between 1 and upper limit (in this case 100).

That’s all for this post! Thank you for reading.

Code for Examples

package test.Stream;

import java.util.stream.Collectors;
import java.util.stream.Stream;
  /*
        Test common stream functions
     */
public class TestStream {

  
    public static void main(String[] args) {

        final int maxItemCount = 100;

        System.out.println(generateData(maxItemCount).parallel().count()); // Result: 100 as we are generating whole numbers from 1 to 100 (inclusive)

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).min((a,b) -> (int)(a-b))); // Result: Optional <2> as 2 is the lowest even number between 1 and 100

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).max((a,b) -> (int)(a-b))); // Result: Optional <100> as 100 is the highest even number between 1 and 100

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).collect(Collectors.toList())); // Result: list of even numbers

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).map(x -> {
            if(x%2 == 0) {
                x = x*x;
            }
            return x;
        }).collect(Collectors.toList())); //  Result: List of squared even numbers

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).reduce(0, (n, m) -> n+ m)); // Result: 2550 - sum of first 50 even numbers = 50*(50+1)

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).findFirst()); // Result: Optional <2> as 2 is the first even number between 1 and 100

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).findAny()); // Result: Optional <some even number> as it will pick from any of the streams

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).allMatch(x -> x%2 == 0)); // Result: true as all numbers are even and therefore divisible by 2

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).anyMatch(x -> x%3 == 0)); // Result: true as there is at least one even number between 1 and 100 divisible by 3 (i.e. 6)

        System.out.println(generateData(maxItemCount).parallel().filter(x -> x%2 == 0).noneMatch(x -> x%101 == 0)); // Result: true as there is no number between 1 and 100 that is divisible by 101



    }
    /*
        Generates whole numbers from 1 to limit parameter
     */
    private static Stream<Integer> generateData(int limit) {
        return Stream.iterate(1, n->n+1).limit(limit);
    }
}