US-China Trade War: Finding Paths of Least Resistance

5 minute read Published: 2025-05-11

The current trade situation between the US and China involves very high tariffs.

Table of Contents

A recent piece in the Washington Post1 discusses Chinese goods being diverted to other countries despite the high tariffs:

After Trump's first term, U.S. imports of Chinese goods that were subject to tariffs decreased, according to U.S. data. But trade was merely being diverted, not stopped: Researchers found that the countries to which Americans turned to make up for that shortfall — including Canada and Mexico as well as the European Union and Southeast Asian nations — saw an increase in imports of the same goods from China. 1

It's interesting to consider, then, how goods might still be moving between countries despite these barriers. Perhaps they find different paths. This thought led me to wonder if logic programming could be a simple way to look into such possibilities.

How to "navigate" tariffs?

When tariffs get this high, direct trading becomes pretty much impossible. But companies still find ways around it.

This makes for a really interesting puzzle that seems perfect for a logic programming approach like Prolog.

Think about what's happening here: products are finding the path of least resistance through a web of countries, tariffs, and manufacturing capabilities. That's exactly the kind of network problem where Prolog shines.

The "re-routing" trade model

Disclaimer 🚨

This model simply represents one way of thinking about this trade situation. International trade contains many nuances beyond what can be captured here, but sometimes looking at a problem through a different lens may reveal something worthwhile. Let's see what patterns might emerge.

First, let's establish our knowledge base – the facts about our trade world. I'll start by listing out the tariff rates I'm using in this model. Remember, these are simplified for our exploration!

% Tariff rates between countries
% tariff(Origin, Destination, Rate).
tariff(china, us, 145).        % US tariffs on Chinese goods
tariff(us, china, 125).        % Chinese tariffs on US goods
tariff(vietnam, us, 10).       % US general tariff on Vietnam
tariff(mexico, us, 12).        % US tariff on non-USMCA Mexican goods

% Additional tariffs needed for our network
tariff(china, vietnam, 5).     % Vietnam's tariff on Chinese goods
tariff(china, mexico, 7).      % Mexico's tariff on Chinese goods
tariff(vietnam, mexico, 8).    % Mexico's tariff on Vietnamese goods (for multi-hop)

Next up, let's define some major product categories and how hard they might be to transform or disguise. This will be important for our rules of origin later.

% Major product categories for export
% product_category(Category, TransformationDifficulty).
product_category(electronics, 3).        % Moderate difficulty to transform
product_category(industrial_equipment, 4). % Harder to disguise origin

Now, for some (again, simplified) trade volumes between countries for these products, in billions of USD.

% Trade volumes (in billions USD)
% trade_volume(Origin, Destination, Category, Amount).
trade_volume(china, us, electronics, 125).
trade_volume(china, us, industrial_equipment, 45).

Different countries are better at making different things. Here are some Prolog facts about manufacturing capabilities for our model countries and product categories.

% Manufacturing capability by country and product
% manufacturing_capability(Country, Category, Level).
manufacturing_capability(china, electronics, 5).
manufacturing_capability(china, industrial_equipment, 5).
manufacturing_capability(vietnam, electronics, 3).
manufacturing_capability(vietnam, industrial_equipment, 2).
manufacturing_capability(mexico, electronics, 3).
manufacturing_capability(mexico, industrial_equipment, 3).

Rules of origin are key! This is about how much a product needs to be transformed in a country to count as originating from there. I'm using a percentage of value-added.

% Rules of origin requirements by country
% rules_of_origin(Country, MinTransformationPct).
rules_of_origin(us, 35).       % 35% value must be added for origin change
rules_of_origin(vietnam, 25).  % 25% value must be added
rules_of_origin(mexico, 30).   % 30% value must be added

Finally, let's add some facts about direct shipping connections and a rough weekly cost. Not all countries will have direct, cheap routes to each other.

% Direct shipping connections (some routes may not have direct links)
% shipping_route(Origin, Destination, CostPerUnit). % Again, simplified cost
shipping_route(china, us, 50).
shipping_route(china, vietnam, 10).
shipping_route(china, mexico, 60).
shipping_route(vietnam, us, 40).
shipping_route(mexico, us, 20).
shipping_route(vietnam, mexico, 30). % For multi-hop

You might notice the shipping_route(vietnam, mexico, 30). line. This specific route, connecting two potential intermediary countries, is included so our Prolog model can explore more complex, two-hop re-routing paths (like China → Vietnam → Mexico → US). Without it, the model could only consider single-stop detours.

Building the re-routing analysis rules

Now for the fun part – writing Prolog rules that let us analyze potential re-routing patterns. Similar to approaching other problems with logic programming, we'll define what constitutes valid re-routing paths rather than detailing each calculation step.

First, let's define a rule to calculate the total direct cost of getting a product from an origin to a destination. This includes the tariffs and the direct shipping cost.

% Calculate total direct cost (tariffs + shipping)
direct_total_cost(Origin, Destination, Category, TotalCost) :-
    tariff(Origin, Destination, Rate), % Rate is a percentage, e.g., 145 for 145%
    trade_volume(Origin, Destination, Category, Volume), % Volume in billion USD
    shipping_route(Origin, Destination, ShippingCostPerUnit),
    TariffCost is (Rate * Volume / 100), % Standard percentage calculation
    TotalShippingCost is (ShippingCostPerUnit * Volume / 100), % ShippingCostPerUnit is also treated as a rate per 100 units of Volume here
    TotalCost is TariffCost + TotalShippingCost. % Result is in billion USD

can_transform_origin checks if an intermediary country can do enough work on a product (based on its manufacturing capability and the product's transformation difficulty) to satisfy that country's rules of origin.

% Calculate if a country can sufficiently transform a product to change its origin
can_transform_origin(Origin, Intermediary, Category, Result) :-
    product_category(Category, TransformDifficulty),
    manufacturing_capability(Intermediary, Category, Capability),
    rules_of_origin(Intermediary, TransformationRequired),
    Value is (Capability - TransformDifficulty) * 10,
    (Value >= TransformationRequired -> 
        Result = yes
    ; 
        Result = no
    ).

For the core re-routing logic, this rule, single_hop_reroute, looks for ways to send goods through one intermediary country. It calculates the total cost of this re-routed path (tariffs and shipping for both legs) and compares it to the direct_total_cost. We also check if the intermediary can actually transform the product enough.

% Find single-hop re-routing options and savings vs direct
single_hop_reroute(Origin, Destination, Category, Via, Savings, Feasibility) :-
    trade_volume(Origin, Destination, Category, Volume),
    direct_total_cost(Origin, Destination, Category, DirectTotalCost),

    % Intermediary route details
    tariff(Origin, Via, FirstLegTariffRate),
    shipping_route(Origin, Via, FirstLegShippingCostPerUnit),
    tariff(Via, Destination, SecondLegTariffRate),
    shipping_route(Via, Destination, SecondLegShippingCostPerUnit),
    Origin \= Via, Via \= Destination, % should be different countries

    % Calculate costs for the re-routed path
    FirstLegTariff is (FirstLegTariffRate * Volume / 100),
    FirstLegShipping is (FirstLegShippingCostPerUnit * Volume / 100),
    SecondLegTariff is (SecondLegTariffRate * Volume / 100),
    SecondLegShipping is (SecondLegShippingCostPerUnit * Volume / 100),
    ReRouteTotalCost is FirstLegTariff + FirstLegShipping + SecondLegTariff + SecondLegShipping,

    % Must have manufacturing capability
    manufacturing_capability(Via, Category, Capability),
    Capability > 1, % This is a simplified check: any capability is better than none for this model
    
    % Origin transformation check
    can_transform_origin(Origin, Via, Category, CanTransform),
    
    % Calculate savings
    Savings is DirectTotalCost - ReRouteTotalCost,
    Savings > 0, % we only consider cases where there are actual savings
    
    % Determine feasibility
    (CanTransform = yes -> Feasibility = high ; Feasibility = low).

Sometimes one hop isn't enough. So, here's two_hop_reroute which looks for paths through two intermediary countries, again calculating total costs and checking transformation capabilities.

% Find two-hop re-routing options and savings vs direct
two_hop_reroute(Origin, Destination, Category, [Via1, Via2], Savings, Feasibility) :-
    trade_volume(Origin, Destination, Category, Volume),
    direct_total_cost(Origin, Destination, Category, DirectTotalCost),

    % Intermediary route details
    tariff(Origin, Via1, FirstLegTariffRate),
    shipping_route(Origin, Via1, FirstLegShippingCostPerUnit),
    tariff(Via1, Via2, SecondLegTariffRate),
    shipping_route(Via1, Via2, SecondLegShippingCostPerUnit),
    tariff(Via2, Destination, ThirdLegTariffRate),
    shipping_route(Via2, Destination, ThirdLegShippingCostPerUnit),
    Origin \= Via1, Via1 \= Via2, Via2 \= Destination, Origin \= Via2,
    % Calculate costs for the re-routed path
    FirstLegTariff is (FirstLegTariffRate * Volume / 100),
    FirstLegShipping is (FirstLegShippingCostPerUnit * Volume / 100),
    SecondLegTariff is (SecondLegTariffRate * Volume / 100),
    SecondLegShipping is (SecondLegShippingCostPerUnit * Volume / 100),
    ThirdLegTariff is (ThirdLegTariffRate * Volume / 100),
    ThirdLegShipping is (ThirdLegShippingCostPerUnit * Volume / 100),
    ReRouteTotalCost is FirstLegTariff + FirstLegShipping + SecondLegTariff + SecondLegShipping + ThirdLegTariff + ThirdLegShipping,

    % Must have manufacturing capabilities
    manufacturing_capability(Via1, Category, Capability1),
    manufacturing_capability(Via2, Category, Capability2),
    Capability1 > 0, Capability2 > 0, % Simplified check

    % Origin transformation check for both hops
    can_transform_origin(Origin, Via1, Category, CanTransform1),
    can_transform_origin(Via1, Via2, Category, CanTransform2), % Check transformation from Via1 to Via2's perspective

    Savings is DirectTotalCost - ReRouteTotalCost,
    Savings > 0,

    % Determine feasibility
    ((CanTransform1 = yes, CanTransform2 = yes) -> Feasibility = high;
     (CanTransform1 = yes ; CanTransform2 = yes) -> Feasibility = medium;
     Feasibility = low).

Querying our re-routing model

Now that we've set up this simplified knowledge base and rules, let's ask our model some interesting questions. We'll focus on the Savings (how much cheaper the re-routed path is compared to direct shipping, including tariffs and shipping costs) and Feasibility (based on whether products can be transformed enough to meet rules of origin).

What are some single-hop re-routing options for Chinese electronics, and what are the potential savings?

?- single_hop_reroute(china, us, electronics, Via, Savings, Feasibility).
Via = vietnam, Savings = 162.5, Feasibility = low ;
Via = mexico, Savings = 120.0, Feasibility = low.

This shows that routing Chinese electronics through Vietnam could offer savings of around 162.5 billion dollars compared to direct shipping. Going via Mexico might save 120.0 billion dollars. Interestingly, the Feasibility is low for both. This suggests that while the cost savings are there, meeting the rules of origin for electronics in either Vietnam or Mexico might be challenging with their current manufacturing capabilities and the product's transformation difficulty as defined in our model. It highlights that cost isn't the only factor!

What about multi-hop routes for industrial equipment, which is harder to transform?

?- two_hop_reroute(china, us, industrial_equipment, [Via1, Via2], Savings, Feasibility).
Via1 = vietnam, Via2 = mexico, Savings = 49.5, Feasibility = low.

For industrial equipment, which is trickier, a two-hop route (China → Vietnam → Mexico → US) is found. It offers savings of 49.5 billion dollars. However, similar to the electronics case, the Feasibility is also low. This could mean that even with two transformation stops, meeting the origin requirements for both hops for this type of product is difficult within our model's parameters.

🚨 Real trade re-routing involves tons of additional factors like existing supply chains, political relationships, and industry-specific regulations.

Final words

I don't know if this is a good way to model trade re-routing, but it was a fun way to explore the concept.

The code is available here. Have fun!

References

1

The Washington Post. (2025, May 9). "Trump trade pressure, China exports." Retrieved from https://www.washingtonpost.com/world/2025/05/09/trump-trade-pressure-china-exports/