Skip to content

Commit

Permalink
UPDATE generating discrete solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
xzhang2523 committed Aug 20, 2024
1 parent e34c05f commit af0024d
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 123 deletions.
2 changes: 0 additions & 2 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']



# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

Expand Down
24 changes: 18 additions & 6 deletions libmoon/solver/gradient/methods/base_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(self, step_size, epoch, tol, core_solver):
self.epoch = epoch
self.tol = tol
self.core_solver = core_solver
self.is_agg = (self.core_solver.core_name == 'AggCore')

def solve(self, problem, x , prefs):
'''
Expand All @@ -26,9 +27,7 @@ def solve(self, problem, x , prefs):
:return:
is a dict with keys: x, y.
'''
# The abstract class cannot be implemented directly.
self.n_prob, self.n_obj = prefs.shape[0], prefs.shape[1]

xs_var = Variable(x, requires_grad=True)
optimizer = SGD([xs_var], lr=self.step_size)
ind = HV(ref_point=get_hv_ref(problem.problem_name))
Expand All @@ -41,11 +40,24 @@ def solve(self, problem, x , prefs):
Jacobian_arr = get_moo_Jacobian_batch(xs_var, fs_var, self.n_obj)
y_detach = fs_var.detach()
optimizer.zero_grad()
if self.core_solver.core_name in ['EPOCore', 'MGDAUBCore', 'RandomCore']:
weights = torch.stack([self.core_solver.get_alpha(Jacobian_arr[idx], y_detach[idx], idx) for idx in range( self.n_prob) ])
if self.is_agg:
agg_name = self.core_solver.solver_name.split('_')[-1]
agg_func = get_agg_func(agg_name)
agg_val = agg_func(fs_var, torch.Tensor(prefs).to(fs_var.device))
torch.sum(agg_val).backward()
else:
assert False, 'Unknown core_name'
torch.sum(weights * fs_var).backward()
if self.core_solver.core_name in ['EPOCore', 'MGDAUBCore', 'RandomCore']:
weights = torch.stack([self.core_solver.get_alpha(Jacobian_arr[idx], y_detach[idx], idx) for idx in range( self.n_prob) ])
# elif self.core_solver.core_name == 'AggCore':
elif self.core_solver.core_name in ['PMTLCore', 'MOOSVGDCore', 'HVGradCore']:
# assert False, 'Unknown core_name'
weights = self.core_solver.get_alpha_array(Jacobian_arr, y_detach)
else:
assert False, 'Unknown core_name'

torch.sum(weights * fs_var).backward()


optimizer.step()
if 'lbound' in dir(problem):
x.data = torch.clamp(x.data, torch.Tensor(problem.lbound) + solution_eps,
Expand Down
36 changes: 36 additions & 0 deletions libmoon/solver/gradient/methods/core/core_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,42 @@ def get_alpha(self, Jacobian, losses, idx):
n_obj = len(losses)
return torch.rand(n_obj)

class AggCore():
def __init__(self, n_var, prefs, solver_name):
self.core_name = 'AggCore'
self.solver_name = solver_name
self.agg_name = solver_name.split('_')[-1]

def get_alpha(self, Jacobian, losses, idx):
assert False, 'RandomCore does not have get_alpha method.'
return None



class MOOSVGDCore():
def __init__(self, n_var, prefs):
self.core_name = 'MOOSVGDCore'

def get_alpha_array(self, Jacobian_arr, losses_arr):
'''
Input:
Jacobian_arr: (n_prob, m, n)
losses_arr: (n_prob, m)
Return: (n_prob, m)
'''














if __name__ == '__main__':
#
Expand Down
21 changes: 15 additions & 6 deletions libmoon/tester/run_syn_discrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from libmoon.solver.gradient.methods.base_solver import GradAggSolver

from libmoon.solver.gradient.methods.base_solver import GradBaseSolver
from libmoon.solver.gradient.methods.core.core_solver import EPOCore, MGDAUBCore, RandomCore
from libmoon.solver.gradient.methods.core.core_solver import EPOCore, MGDAUBCore, RandomCore, AggCore, MOOSVGDCore



import os
Expand Down Expand Up @@ -70,9 +71,12 @@ def save_figures(folder_name):
# os.makedirs(folder_name, exist_ok=True)
fig_name = os.path.join(folder_name, 'res.pdf')
plt.savefig(fig_name, bbox_inches='tight')
fig_name_svg = os.path.join(folder_name, 'res.svg')
plt.savefig(fig_name_svg, bbox_inches='tight')
print('Save fig to {}'.format(fig_name))
plt.title(beautiful_dict[args.solver_name])


def save_pickles(folder_name):
import pickle
pickle_name = os.path.join(folder_name, 'res.pickle')
Expand All @@ -81,26 +85,26 @@ def save_pickles(folder_name):
print('Save pickle to {}'.format(pickle_name))



if __name__ == '__main__':
parser = argparse.ArgumentParser( description= 'example script' )
# solver_array: []
parser.add_argument('--solver-name', type=str, default='random')
# solver_name: ['hv_grad', 'pmtl', '']
parser.add_argument('--solver-name', type=str, default='moosvgd')
parser.add_argument( '--problem-name', type=str, default='VLMOP1')

parser.add_argument('--step-size', type=float, default=1e-2)
parser.add_argument('--tol', type=float, default=1e-2)
parser.add_argument('--draw-fig', type=str, default='True')
parser.add_argument('--use-plt', type=str, default='Y')
parser.add_argument('--h-tol', type=float, default=1e-3)
parser.add_argument('--sigma', type=float, default=0.9)
parser.add_argument('--n-prob', type=int, default=8 )
parser.add_argument('--epoch', type=int, default=500 )
parser.add_argument('--epoch', type=int, default=1000 )
parser.add_argument('--seed-idx', type=int, default=0)
parser.add_argument('--seed-num', type=int, default=3)
args = parser.parse_args()
np.random.seed(args.seed_idx)


print('Running {} on {}'.format(args.solver_name, args.problem_name) )
np.random.seed(args.seed_idx)
problem = get_problem(problem_name=args.problem_name, n_var=10)
Expand All @@ -117,10 +121,15 @@ def save_pickles(folder_name):
core_solver = MGDAUBCore(n_var=problem.n_var, prefs=prefs)
elif args.solver_name == 'random':
core_solver = RandomCore(n_var=problem.n_var, prefs=prefs)
elif args.solver_name.startswith('agg'):
core_solver = AggCore(n_var=problem.n_var, prefs=prefs, solver_name=args.solver_name)
elif args.solver_name.startswith('moosvgd'):
core_solver = MOOSVGDCore(n_var=problem.n_var, prefs=prefs)
else:
assert False, 'Unknown solver'

solver = GradBaseSolver(step_size=1e-2, epoch=args.epoch, tol=args.tol, core_solver=core_solver)
solver = GradBaseSolver(step_size=args.step_size, epoch=args.epoch, tol=args.tol, core_solver=core_solver)

res = solver.solve(problem=problem, x=synthetic_init(problem, prefs), prefs=prefs )
res['prefs'] = prefs

Expand Down
8 changes: 5 additions & 3 deletions libmoon/tester/run_syn_discrete.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

problem=VLMOP1

for seed in {1..2}
# mgdaub random epo

for seed in {0..1}
do
for solver_name in mgdaub random epo
for solver_name in agg_ls agg_tche agg_pbi agg_cosmos
do
python run_syn_discrete.py --solver-name $solver_name --draw-fig False --epoch 200 --problem-name $problem --seed-idx $seed
python run_syn_discrete.py --solver-name $solver_name --draw-fig False --epoch 1000 --problem-name $problem --seed-idx $seed
done
done
sleep 100
8 changes: 6 additions & 2 deletions libmoon/util_global/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,13 @@ def get_agg_func(agg, cosmos_hp=8.0):
'igd': 'IGD',
'spacing': 'Spacing',
'sparsity': 'Sparsity',
'uniform': 'Uniform',
'soft uniform': 'SUniform',
'lmin': 'Lmin',
'soft_lmin': 'Soft Lmin',
'maxgd': 'MaxGD',
'inner_product': 'IP',
'cross_angle': 'Cross Angle',
'pbi' : 'PBI'

}

scale_dict = {
Expand Down
54 changes: 49 additions & 5 deletions script/rebuttal/merge_std.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@

import pickle
from libmoon.metrics import compute_indicators




import pandas as pd
import numpy as np
from libmoon.util_global.constant import beautiful_dict, beautiful_ind_dict


if __name__ == '__main__':
problem_name = 'VLMOP1'
seed_num=2

pickle_name_template = 'D:\\pycharm_project\\libmoon\\Output\\discrete\\{}\\{}\\seed_{}\\res.pickle'
mtd_arr = ['epo', 'mgdaub', 'random']
mtd_arr = ['epo', 'mgdaub', 'random', 'agg_ls', 'agg_tche', 'agg_pbi', 'agg_cosmos']

mtd_mean_dict = {}
mtd_std_dict = {}

for mtd in mtd_arr:
indicator_arr = [0,] * seed_num
for seed_idx in range(seed_num):
Expand All @@ -22,3 +25,44 @@
objs = res['y']
prefs = res['prefs']
indicator_dict = compute_indicators(objs, prefs)
indicator_arr[seed_idx] = indicator_dict
mean_dict = {}
std_dict = {}
for key in indicator_arr[0].keys():
values = [indicator_arr[seed_idx][key] for seed_idx in range(seed_num)]
mean_dict[key] = np.mean(values)
std_dict[key] = np.std(values)

mtd_mean_dict[mtd] = mean_dict
mtd_std_dict[mtd] = std_dict



# Initialize an empty list to store the final rows
final_rows = []

# Populate the rows for the final DataFrame
for mtd in mtd_arr:
combined_row = {'Method': beautiful_dict[mtd]}

for key in mtd_mean_dict[mtd].keys():

mean_value = mtd_mean_dict[mtd][ key ]
std_value = mtd_std_dict[mtd][key ]
combined_row[beautiful_ind_dict[key] ] = f'{mean_value:.4f} ({std_value:.4f})'

final_rows.append(combined_row)

# Convert the list of rows to a DataFrame
df_final = pd.DataFrame(final_rows)

# Save the DataFrame to a CSV file
csv_file_path = 'D:\\pycharm_project\\libmoon\\Output\\discrete\\indicator_mean_std.csv'
df_final.to_csv(csv_file_path, index=False)

print(f'Data saved to {csv_file_path}')





33 changes: 0 additions & 33 deletions test.py

This file was deleted.

66 changes: 0 additions & 66 deletions vedio.html

This file was deleted.

0 comments on commit af0024d

Please sign in to comment.