<jupyter_start><jupyter_text>Code to generate Figure 2A from the paper<jupyter_code># Copyright (C) to <NAME>, <NAME>, <NAME>. All Rights Reserved.

import numpy as np
import numpy.random as npr
import torch
import torch.nn.functional
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rcParams['figure.max_open_warning'] = 0
%matplotlib inline
import deep_inv_opt as io
import deep_inv_opt.plot as iop

as_tensor = io.as_tensor
as_numpy = io.as_numpy
as_str = io.as_str

# To save the figure images to disk, override this with something like "~/Downloads"  
FIGURE_SAVE_DIR = "C:/Users/Public/Downloads/"<jupyter_output><empty_output><jupyter_text>Figure 2APlot the feasible region and the central path of the initial cost vector.<jupyter_code>class Figure2A_LP(io.ParametricLP):
    
    def generate(self, u, w):
        (w0,) = w
        
        c = [[torch.cos(w0)],
             [torch.sin(w0)]]

        A_ub = [[-1.0,  0.0],  # x0 >= 0
                [ 0.0, -1.0],  # x1 >= 0
                [ 1.0,  0.0],  # x0 <= 1
                [ 0.0,  1.0],  # x1 <= 1
                [ 1.0,  1.5]]  # x0 + x1 <= ...

        b_ub = [[ 0.0 ],
                [ 0.0 ],
                [ 1.0 ],
                [ 0.75 ],
                [ 1.5]]
        
        return c, A_ub, b_ub, None, None
    
    def __call__(self, u=None):
        if u is None:
            u = as_tensor([[0.0]])  # Dummy u, not used
        return super().__call__(u)
    
    def plot(self, color='k', fig=None, linestyle=None, want_c=True, want_constraints=True):
        
        with torch.no_grad():
            # Set up the plot
            if fig is None:
                fig = plt.figure(dpi=100, figsize=(5, 5))
                ax = fig.add_subplot(111)
                ax.set_xlim(-0.35, 1.25)
                ax.set_ylim(-0.35, 1.25)
                
                ax.set_aspect('equal', 'box')
                ax.set_axis_off()
                fig.tight_layout()
            else:
                ax = fig.gca()
                

            # Plot each set of constraints
            c, A_ub, b_ub, _, _ = as_numpy(*self())            
            iop.plot_linprog_hull(0.25*c if want_c else None,
                                  A_ub if want_constraints else None,
                                  b_ub if want_constraints else None,
                                  color=color, linestyle=linestyle, cxy=(1.0, 1.0))
            return fig, ax

##########################################

# Define a utility callback that will collect all the distinct points on the IPM central path during linprog
LINPROG_CENTRAL_PATH_T = []
LINPROG_CENTRAL_PATH_X = []
def collect_central_path(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t):
    global LINPROG_CENTRAL_PATH_T
    global LINPROG_CENTRAL_PATH_X
    if not LINPROG_CENTRAL_PATH_T or LINPROG_CENTRAL_PATH_T[-1] != t:
        LINPROG_CENTRAL_PATH_T.append(t)
        LINPROG_CENTRAL_PATH_X.append(as_numpy(x).T)

# LP_true and LP_init
f_true = Figure2A_LP([np.pi*6/4+0.08])  # True c angle
f_init = Figure2A_LP([4.0])

# Record central path of linprog on LP_init
io.linprog(*f_init(), eps=0.00001, mu=2.0, t0=2.0, callback=collect_central_path)
x_path = np.vstack(LINPROG_CENTRAL_PATH_X)

# Compute target
x_train = io.linprog(*f_true(), eps=0.0000001)

# Plot c_true and constraints
fig, ax = f_true.plot(color='k', want_c=False)
ax.plot(*as_numpy(x_train), 'ok', markerfacecolor='white', markersize=14.0, markeredgewidth=1.5)

ax.plot(x_path[:,0], x_path[:,1], 'o', color=[0.1, 0.7, 0.0], markersize=4.0)

# Plot c_init
f_init.plot(color=[0.1, 0.7, 0.0], fig=fig, want_constraints=False)
ax.plot(*as_numpy(io.linprog(*f_init(), eps=0.0000001)), 'o', color=[0.1,0.7,0.0], markerfacecolor='white', markersize=10.0, markeredgewidth=1.5)

if FIGURE_SAVE_DIR:
    plt.savefig(FIGURE_SAVE_DIR + '/deepinverse_fig2_ipm_path.pdf', bbox_inches='tight', dpi=100)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.137624014245739, 'fraction_numerical': 0.03815822945815314, 'mean_word_length': 2.3578138343296327, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '374031', 'license': 'MIT', 'n_tokens_mistral': 1550, 'n_tokens_neox': 1450, 'n_words': 315, 'path': 'paper/Figure 2A.ipynb', 'repo_name': 'tankconcordia/deep_inv_opt', 'size': '3952'}