cfp/000074401206620011610000000000001102133441500142575ustar00tstephenmast_faculty00004050013607cfp/test_gen.m000070001206620011610000000060701061120757200162520ustar00tstephenmast_faculty00004050013607function test_gen(ds,name_gen) cont.randompick = 1; cont.enumstretch = 1; timeLimit = 900; for d = ds time_summary = []; iter_summary = []; record.randompick = {}; record.enumstretch = {}; NumCase = 1000; fprintf(['d = ' num2str(d) ' ']); NumBack=0; for i = 1:NumCase for c=1:NumBack fprintf('\b'); end NumBack = fprintf('i = %d', i); [Pts,ColorPartition,b]=feval(name_gen,d); if cont.randompick [x,info]=cfp_solver_randompick(Pts,b,ColorPartition); record.randompick{i}=info; end if cont.enumstretch [x,info]=cfp_solver_enumstretch(Pts,b,ColorPartition); record.enumstretch{i}=info; end end if cont.randompick iter_summary.randompick = get_iter_summary(record, 'randompick'); time_summary.randompick = get_time_summary(record, 'randompick'); cont.randompick = ... ((time_summary.randompick.total... /time_summary.randompick.validcases)summary.max) summary.max = info.iter; end if info.itersummary.max) summary.max = info.time; end if info.time=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it is the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. info is a struct that tells the exiting % state, following are its members. % info.iter: the number of inner iterations to solve the problem, which % indicates the number of colorful simplices tested in this % algorithm. % info.time: the number of seconds spent by the solver. % info.feasible: returns 1 if the problem is feasible, -1 if the problem % unknow whether problem is feasible or not because of % exceeding maximum loop limit. % % *** % * Algorithm * % *** % This algorithm test a random colorful set of points in each iteration % until a valid set is met. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % July 2005: First version. % August 2005: Added comments. % April 2007: Renamed to cfp_solver_randompick(). % Updated interface. % % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-10); % Allowed numerical error. LoopLimit = 100000000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % The iterations of updating the colorful set of points until the convex % hull of the set contains b. T = options.initT; LoopCnt = 0; while (1) % Test whether the colorful set is valid by trying to express b as a % convex combination. [tmp, recp_cond] = linsolve([Pts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check if b % is in the simplex. [tmp,LPfval,FeasibleFlag]... =linprog(sparse(zeros(d+1,1)),[],[],... [Pts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],optimset('Display','off','LargeScale','off')); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_randompick'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>10) x = zeros(NumPts, 1); info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; return end end % Changed: LoopCnt % Get another random colorful set base = 0; for i = 1:length(ColorPartition) T(i) = rand_int(1, 1, [(base+1) (base+ColorPartition(i))]); base = base + ColorPartition(i); end % Changed: T end returncfp/infeaGen.m000070001206620011610000000016651061551746000161670ustar00tstephenmast_faculty00004050013607function infeaGen(ds, name_gen) for d = ds record.sdprelax = {}; NumCase = 1000; if d>6 NumCase = 100; end fprintf(['d = ' num2str(d) ' ']); NumBack=0; i = 1; while (1) [Pts,ColorPartition,b]=feval(name_gen,d); filname=['infeasi_cases/infeasi' num2str(d) 'd' num2str(i) '.mat']; for c=1:NumBack fprintf('\b'); end NumBack = fprintf('i = %d', i); while (exist(filname,'file')==2) i = i+1; for c=1:NumBack fprintf('\b'); end NumBack = fprintf('i = %d', i); filname=['infeasi_cases/infeasi' num2str(d) 'd' num2str(i) '.mat']; end save(filname, 'Pts', 'b', 'ColorPartition'); i = i+1; if (i>NumCase) break; end end fprintf('\n'); end end NumBack = fprintf('i = %d', i); while (exist(filname,'file')cfp/cfp_solver_mbo2.m000070001206620011610000000367711065317317200175420ustar00tstephenmast_faculty00004050013607function [x,info] = cfp_solver_mbo2(Pts, b, ColorPartition, options) % % The Multi-update BARANY-ONN algorithm 2 to solve colorful linear % programming problem. % % % * Syntax * % % [x,info] = cfp_solver_mbo2(Pts) % [x,info] = cfp_solver_mbo2(Pts, b) % [x,info] = cfp_solver_mbo2(Pts, b, ColorPartition) % [x,info] = cfp_solver_mbo2(Pts, b, ColorPartition, options) % % % * Description * % % [x,info]=cfp_solver_mbo2(Pts,b,ColorPartition) % solves for x satisfying the constraints: % _ % | Pts*x = b % | if x(i) and x(j) have the same color, then x(i)*x(j)=0 % | sum(x)=1 % |_ x>=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -2 if % numerical error. % % *** % * Algorithm * % *** % This algorithm is a variance of algorithm 2 in the publication "Colourful % Linear Programming and its Relatives" by IMRE BARANY and SHMUEL ONN % (Math. Oper. Res. 22, 550-557, 1997). % The algorithm updates a colorful set of points T and a point xk on the % surface of conv(T) at each iteration. The algorithm finds a linear % combination transforming T into xk, such that some points in T has zero % as coefficients; then replaces all of the zero-coefficient points in the % following way: % Step 1: p = xk; % Step 2: for all zero-coefficient points in T % i) replace it with a point of the same color minimizing the % inner product with p, say t. % ii) let p become the projection of the origin on the line % segment between t and p. % After replacing the points, xk is updated to the point on the surface of % conv(T) in the following way: % Step 1: shrink p, such that p is on a facet of conv(T). % Step 2: find p0, which is the projection of origin on the affine % hyperplane generated by the facet holding p. % Step 3: shrink p towards p0, until p is moved to the boundary of % the facet holding it, or until p=p0. % Step 4: xk = p. % % There are some notes for this algorithm: % 1) It does not theoretically avoid the zigzagging phenomenon of % BARANY-ONN algorithm 2. % 2) The accumlation of numerical error on xk cannot be avoided, because % the update of xk depends on its previous value. % 3) The time complexity of each iteration is the same as BARANY-ONN % algorithm 2, since in current implementation the bottleneck is on % finding the entrance point of conv(T), which is O(d^3). % 4) For general cases, it updates two points in each iteration. % % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % Jul 2005: First version. % Aug 2005: Added comments. % Sep 2005: Let each iteration update 2 points. % May 2006: Fixed a bug in generating data structure ColorMap. % May 2007: Changed interface to cfp_solver_mbo2(). % % * % * Dependencies * % * % Following functions are not in basic MATLAB library, and this routine % depends them: % classic_caratheodory() % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % xk : A point in the colorful convex hull, whose distance to b is reduced % after each iteration. % LUM: A vector containing coefficients for points in the colorful set % indicated by T. LUM represents a linear combination mapping the % colorful set to xk. If there is no numerical error, LUM should has % these properties until the last iteration is finished: % i)all(LUM>=0); ii)any(LUM==0); iii)sum(LUM)==1. % p : A vector presenting a point belong to the convex hull of the % colorful set, notated conv(T). % a : A scalar between 0 and 1 to shrink a vector. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 1000000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/norm(Pts(:,cnt),2); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap % Initialize some variables for iterations. T = options.initT; % Represents a colorful set of points. LUM = zeros(NumColor, 1); % Coefficients mapping the points in T to xk. LUM(1) = 1; % Initialize LUM. xk = Pts(:,T(1)); % Initialize xk to the first point in T. iFree = 1; % A color index. LoopCnt = 0; % Counter of iterations. % Initialized: T LUM xk LoopCnt % Test if the initial colorful set is valid by trying to express b as a % convex combination of T. Gaussian elimination is used by the function % linsolve() to find the coefficients of mapping T to b. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % If any point has negative coefficient but T is affinely dependent, b % is still possible to be in conv(T). In this case the function % classic_caratheodory() using a pivoting algorithm can give another % attempt to express b as a convex combination of T. [tmp, FeasibleFlag] = classic_caratheodory(OriginPts(:,T), ... b, TOLERANCE); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % Valid solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % The iterations updating T until b is in conv(T). while any(abs(xk)>TOLERANCE) % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_mbo2'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>1000) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; x = zeros(NumPts, 1); return end end % Changed: LoopCnt % Find the color indices of zero-coefficient points to be replaced. color_out_list = find(abs(LUM)<=TOLERANCE)'; if isempty(color_out_list) % Finding the point of minimum size coefficient is equivalent to % finding a zero-coefficient point, since geometrically all the % coefficients are non-negative and at least one of them is zero. % This alternative method is to tolerate some numerical error. [dum, color_out_list] = min(abs(LUM)); end % Initialized: color_out_list % Replace all zero-coefficient points. p = xk; % Initialize the projection of % origin. for color_out_index = color_out_list minProd = TOLERANCE; % Initialize the minimum % inner product. for j=ColorMap(color_out_index).list % Search for the point of % minimum inner product p. Prod = dot(Pts(:,j), p); if (Prod < minProd) j_in = j; minProd = Prod; end end T(color_out_index) = j_in; % Replace one point. t = Pts(:,j_in); % t is the new point. p = (dot(t-p,t)*p + dot(p-t,p)*t) ... % p is the projection of / dot(t-p,t-p); % origin on a line segment. end % Changed: T % Shrink p to the surface of conv(T). The algorithm goes through all the % separating facets of conv(T). A separating facet generates a hyperplane % separating origin from conv(T) in the Euclidean space. Y = inv([Pts(:,T); ones(1,(d+1))]); % Each row of Y contains the normal % vector of a facet; the negative % elements in the last column % indicates separating facets. if any(any(~isfinite(Y))) % Test if b is in conv(T), and terminate the algorithm if yes. [LUM,FeasibleFlag]=classic_caratheodory(OriginPts(:,T),b,TOLERANCE); if (FeasibleFlag>0) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % When T is affinely dependent, classic_caratheodory() uses a % pivoting algorithm to express p as a convex combination of T. At % least one point in the convex combination has zero as its % coefficient. xk is updated to p without finding entrance point. xk = p; [LUM, dum] = classic_caratheodory(Pts(:,T), xk, TOLERANCE); if (dum<=0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts, 1); return end continue; else % Solves the linear optimization problem: % min a % such that: a*(Y(i,1:d)*p)<=Y(i,d+1) forall i; % where : _ % | if Y(i,d+1)<0, the function Y(i,1:d)*x=Y(i,d+1) is % | the affine hyperplane generated by a seperating % |_ facet. a = -Inf; for i = find(Y(:,(d+1))<(-TOLERANCE))' m = -(Y(i,1:d)*p); if ((abs(m) > TOLERANCE)&&((Y(i,d+1)/m) > a)) a = Y(i,d+1)/m; iFree = i; end end % If a is between 0 and 1 after scanning all the separating facets, b % is not in the convex hull of T. Otherwise b is already in the % convex hull of T and the algorithm can terminate. if (a>0) % The condition a<=1 is satisfied by the context that only % separating facets are scanned. p = a*p; else % Terminate the algorithm. break; end end % Changed: p iFree % Find p0, the projection of origin on the affine hyperplane holding p. t = Y(iFree,1:d)'; p0 = (-Y(iFree,d+1))*t/dot(t,t); % Initialized: p0 % Shrink p towards p0, such that p is on the boundary of the facet % holding it. Then update xk to p. This is done by solving the linear % optimization problem: % min a % such that: Y(i,1:d)*(p0+a*(p-p0))<=Y(i,d+1) forall i % where : _ % | the function Y(i,1:d)*x=Y(i,d+1) is the affine hyperplane % |_ seperating p0 from conv(T). a = -Inf; t = p - p0; for i = find(Y*[p0;1]<(-TOLERANCE))' s = -(Y(i,1:d)*p0); m = -(Y(i,1:d)*t); if ((abs(m)>TOLERANCE)&&(((Y(i,d+1)-s)/m)>a)) a = (Y(i,d+1)-s)/m; end end if (a>0) xk = p0 + a*t; else xk = p0; end % Changed: xk % Express xk as a convex combination of T. L = [ (1:(iFree-1)) ((iFree+1):NumColor) ]; [LUM(L), recp_cond] = linsolve(Pts(:, T(L)), xk); LUM(iFree) = 0; % Changed: LUM end % Changed: T % Prepare the results and terminate the algorithm. A = [OriginPts(:,T); ones(1,NumColor)]; [tmp, recp_cond] = linsolve(A, [b; 1]); if (recp_cond < TOLERANCE) [tmp, dum] = classic_caratheodory(OriginPts(:,T), ... b, TOLERANCE); if (FeasibleFlag<=0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); return end end info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; % Initialized: info x return cfp/cfp_init_maxdist.m000070001206620011610000000057331065052114000177640ustar00tstephenmast_faculty00004050013607function initT = cfp_init_maxdist(Pts, b, ColorPartition); % % A greedy algorithm to find a colorful set of points from given colorful % points. % % % * Syntax * % % initT = cfp_init_maxdist(Pts, ColorPartition , b) % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hull. % b is a column vector representing a point in the d-Euclidean space. % ColorPartition is a row vector of length (d+1). Each element is an % integer not less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. % % % * Output Arguments * % % initT is a row vector of length (d+1). Its elements are column indices of % Pts, specifying a colorful set of points (one point for each color). % % *** % * Algorithm * % *** % In each color, one point is selected and added to the colorful set, one % color after another. The method to choose a point is to maximize the % minimum distance of this point to the points already in the set. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % July 2007: Unified interface in the package for the thesis % "Colourful Feasibility Problem: Algorithm, Bounds and % Implications". % % Get the number of colors. l = length(ColorPartition); % Allocate memory for initT. initT = zeros(1, l); % Choose the first point for the first color. initT(1) = 1; % base helps to enumerate all the point indices of each colors. base = ColorPartition(1); % Choose one point from each of the rest colors. for i = 2:l % Get the maximum of the minimum distance and the corresponding point. max_min_dist = 0; for j = (base+1):(base+ColorPartition(i)) % Get the minimum distance to the points already in colorful set. min_dist = 2; for k = 1:(i-1) dist = norm( Pts(:,j)-Pts(:,initT(k)), 2 ); if (dist < min_dist) min_dist = dist; end end % Keep the best point by comparison. if (min_dist > max_min_dist) max_min_dist = min_dist; pt_index = j; end end % Insert the selected point into the set represented by initT. initT(i) = pt_index; % Prepare base for next color. base = base + ColorPartition(i); end return cfp/cfp_gen_random.m000070001206620011610000000075031060751221600174040ustar00tstephenmast_faculty00004050013607function [Pts,Partition,b]=cfp_gen_random(d,ColorPartition,options) % % A random generator for colorful feasibility problem. % % % * Syntax * % % [Pts,Partition,b]=cfp_gen_random(d) % [Pts,Partition,b]=cfp_gen_random(d,ColorPartition) % [Pts,Partition,b]=cfp_gen_random(d,ColorPartition,options) % % % * Description * % % [Pts,Partition,b]=cfp_gen_random(d,ColorPartition,options) randomly % generates a colorful feasibility problem. % % *** % * Input Argument * % *** % The input argument d is the dimension for Euclidean space. % The input ColorPartition a vector of length d+1 indicating the number % of points each color should have. For example, if ColorPartition=[2 4 4], % then the generated colorful feasibility problem should have two points % for the first color, four points for the second, and four points for the % last color. % The input options tells other properties the generated problem should % have. options.feasible=1 indicates that the generated problem must be % feasible, options.feasible=0 indicates that the generated problem may or % may not be feasible. % % % * Output Arguments * % % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hulls. All the colorful points are % unit vectors. Scaling the colorful points does not affect whether a % convex hull generated by them contain the origin, and b is the origin. % Hence, all the colorful points can be scaled to unit vectors. % b is a column vector representing a point, and it is always generated % as the origin. This output argument is for future potential update. % Partition is a row vector of length (d+1). Each element is an integer % no less than (d+1), specifying the number of points in a color. For % example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % April 2007 The first version. % %% apply the default input arguments if ((nargin<3)||isempty(options.feasible)) options.feasible = 1; end if ((nargin<2)||isempty(ColorPartition)) ColorPartition = rand_int(1, d+1, [1 d+1]); end %% assign some control variables NumColor = length(ColorPartition); NumPts = sum(ColorPartition); %% construct alternative data structure % ColorMap is an alternative data structure to present which point is in % which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap %% generate random points Pts = randn(d, NumPts); for i = 1:NumPts Pts(:,i) = Pts(:,i)/norm(Pts(:,i),2); end %% handle forced feasibility if (options.feasible==1) iA = rand_int(1, 1, [1 NumPts]); L = zeros(1, NumColor-1); j = 0; for i = 1:NumColor if (~ismember(iA, ColorMap(i).list)) j = j+1; L(j) = ... ColorMap(i).list(rand_int(1, 1, [1 ColorPartition(i)])); end end Pts(:, iA) = - (Pts(:, L) * rand_real(NumColor-1, 1, [0 1])); Pts(:, iA) = Pts(:, iA)/norm(Pts(:, iA)); end %% assign b to zero vector b = zeros(d,1); %% assign output for Partion Partition = ColorPartition; returncfp/test_gencore.m000070001206620011610000000163101062065374400171270ustar00tstephenmast_faculty00004050013607function test_gencore(ds, name_gencore) % cont struct tells which solver is tested and which is not cont.core_bo1 = 1; cont.core_bo2 = 1; cont.core_multiupdate = 1; cont.core_maxvolume = 1; cont.randompick = 1; cont.enumstretch = 1; timeLimit = 900; for d = ds if ((d>=24)&&isequal(name_gencore,'cfp_gencore_random')) % time too long cont.randompick = 0; end if ((d>=40)&&isequal(name_gencore,'cfp_gencore_random')) % time too long cont.enumstretch = 0; end if ((d>=300)&&isequal(name_gencore,'cfp_gencore_random')) % time too long cont.core_maxvolume = 0; end if ((d>=22)&&isequal(name_gencore,'cfp_gencore_tube_balanced')) % time too long cont.randompick = 0; cont.enumstretch = 0; end if ((d>=192)&&isequal(name_gencore,'cfp_gencore_tube_balanced')) % numerical error cont.core_multiupdate = 0; end if ((d>=300)&&isequal(name_gencore,'cfp_gencore_tube_balanced')) % numerical error cont.core_maxvolume = 0; end if ((d>=22)&&isequal(name_gencore,'cfp_gencore_tube_unbalanced')) % time too long cont.randompick = 0; cont.enumstretch = 0; end if ((d>=300)&&isequal(name_gencore,'cfp_gencore_tube_unbalanced')) % numerical error cont.core_maxvolume = 0; cont.core_multiupdate = 0; end if ((d>=12)&&isequal(name_gencore,'cfp_gencore_lowdensity')) % time too long cont.randompick = 0; end if ((d>=24)&&isequal(name_gencore,'cfp_gencore_lowdensity')) % time too long cont.enumstretch = 0; end if ((d>=192)&&isequal(name_gencore,'cfp_gencore_lowdensity')) % numerical error cont.core_maxvolume = 0; end if ((d>=24)&&isequal(name_gencore,'cfp_gencore_middensity')) % time too long cont.randompick = 0; end if ((d>=300)&&isequal(name_gencore,'cfp_gencore_middensity')) % time too long % numerical error cont.core_maxvolume = 0; end time_summary = []; iter_summary = []; record.core_bo1 = {}; record.core_bo2 = {}; record.core_multiupdate = {}; record.core_maxvolume = {}; record.randompick = {}; record.enumstretch = {}; NumCase = 1000; if (d>=48) NumCase = 50; end fprintf(['d = ' num2str(d) ' ']); NumBack=0; for i = 1:NumCase for c=1:NumBack fprintf('\b'); end NumBack = fprintf('i = %d', i); [Pts,ColorPartition,b]=feval(name_gencore,d); if cont.core_bo1 [x,info]=cfp_solver_bo1(Pts,b,ColorPartition); record.core_bo1{i}=info; end if cont.core_bo2 [x,info]=cfp_solver_bo2(Pts,b,ColorPartition); record.core_bo2{i}=info; end if cont.core_multiupdate [x,info]=cfp_solver_multiupdate(Pts,b,ColorPartition); record.core_multiupdate{i}=info; end if cont.core_maxvolume [x,info]=cfp_solver_maxvolume(Pts,b,ColorPartition); record.core_maxvolume{i}=info; end if cont.randompick [x,info]=cfp_solver_randompick(Pts,b,ColorPartition); record.randompick{i}=info; end if cont.enumstretch [x,info]=cfp_solver_enumstretch(Pts,b,ColorPartition); record.enumstretch{i}=info; end end if cont.core_bo1 iter_summary.core_bo1 = get_iter_summary(record, 'core_bo1'); time_summary.core_bo1 = get_time_summary(record, 'core_bo1'); cont.core_bo1 = ... ((time_summary.core_bo1.total... /time_summary.core_bo1.validcases)summary.max) summary.max = info.iter; end if info.itersummary.max) summary.max = info.time; end if info.time=48) NumCase = 50; end fprintf(['d = ' num2str(d) ' ']); NumBack=0; for i = 1:NumCase focfp/cfp_gencore_lowdensity.m000070001206620011610000000216551060752275000212060ustar00tstephenmast_faculty00004050013607function [Pts,Partition,b] = cfp_gencore_lowdensity(d, equAngle, poleAngle) % % A random generator of colorful feasibility problem core cases with a % small number of feasible solutions. These random problems are essentially % some particular structured configurations up to perturbation and % shuffling of the order of points. % % % * Syntax * % % [Pts,Partition,b]=cfp_gencore_lowdensity(d) % [Pts,Partition,b]=cfp_gencore_lowdensity(d,equAngle) % [Pts,Partition,b]=cfp_gencore_lowdensity(d,equAngle,poleAngle) % % % * Description * % % [Pts,Partition,b]=cfp_gencore_lowdensity(d,equAngle,poleAngle) randomly % generates a colorful feasibility problem core case with a small number of % feasible solutions. There is significant chance to get only d^2+1 % feasible solutions. % % *** % * Input Argument * % *** % The input argument d is the dimension for Euclidean space. This routine % requires d>=2. % The optional arguments equAngle and poleAngle define how close are the % colorful points to the equator (points with the last coordinate zero) of % hypersphere and the south/north pole (points with the last coordinate % 1/-1). The smaller the values, the colser. The defaults of them are both % 0.05*pi/d. These angles must be positive and no larger than pi/4. % % % * Output Arguments * % % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hulls. All the colorful points are % unit vectors. Scaling the colorful points does not affect whether a % convex hull generated by them contain the origin, and b is the origin. % Hence, all the colorful points can be scaled to unit vectors. % b is a column vector representing a point, and it is always generated % as the origin. This output argument is for future potential update. % Partition is a row vector of length (d+1). Each element is an integer % no less than (d+1), specifying the number of points in a color. For % example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. This % function only assigns (d+1) points to each color, since in practice a % subset of size (d+1) containing b in the convex hull can always be found % when there are more than (d+1) points. Partition is an output argument % for future potential update. % % **** % * References * % **** % [1] A Deza, S Huang, T Stephen and T Terlaky, "Colourful Simplicial % Depth", Discrete & Computational Geometry, Volume 35, 597-615. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % Named clp_gen_sminus.m % August 2005: Added comments. % May 2006: Handled the case of d=2. % Added CoreViolate parameter. % Mar 2007 Handle the exception of d=1 % April 2007 Renamed to cfp_gencore_lowdensity.m % Removed CoreViolate parameter. %% Apply default input arguments. if ((nargin<3)||isempty(poleAngle)) poleAngle = 0.05*pi/d; end if ((nargin<2)||isempty(equAngle)) equAngle = 0.05*pi/d; end %% Input error check if (d<=1) error('d must be at least 2'); end %% Generate reference points for d colors on equator. EquRef = regular_simplex(d-1); % General a regular simplex c = sum(EquRef,2)/(d); % The center of regular simplex n = norm(EquRef(:,1)-c, 2); % Distance between vertices and % center for i=1:(d) % Translate and normalize the EquRef(:,i) = EquRef(:,i) - c; % regular simplex vertices EquRef(:,i) = EquRef(:,i)/n; end %% Buffer some reusable calculation results. sin_poleAngle = sin(poleAngle); cos_poleAngle = cos(poleAngle); sin_equAngle = sin(equAngle); cos_equAngle = cos(equAngle); sin_2equAngle = sin(2*equAngle); cos_2equAngle = cos(2*equAngle); %% Assign some control variables over the routine. unsymmColor = rand_int(1,1,[1 (d+1)]); % Indicate which color is the % last color. baseList = 0:(d+1):(d*d+d); % The sum of a baseList element % and an integer from [1 d+1] % covers all point indices in % Pts. mid_norm = norm([cos_2equAngle * sum(EquRef(:,1:(d-1)),2)/(d-1); ... - sin_2equAngle]); safeAngle=asin(sin_2equAngle/mid_norm); % The angle with equator for d % points of the last color. RefOrder = randperm(d); % The order of reference points % to be used. %% Generate the points of the first d colors. iRef = 0; % Initialize the index reference point order. Pts = zeros(d, (d+1)*(d+1)); % Allocate memory. for base = baseList([(1:(unsymmColor-1)) ((unsymmColor+1):(d+1))]); % Increment the index of reference point order. iRef = iRef + 1; % Get the index of equator point that is under equator. iD = rand_int(1,1,[1 (d+1)]); % Get the index of equator point that is above equator. iU = rand_int(1,1,[1 d]); iU = iU + (iU>=iD); % Get the equator points. Pts(:, base+iD) = [ cos_2equAngle * EquRef(:,RefOrder(iRef)); ... - sin_2equAngle ]; Pts(:, base+iU) = [ - cos_equAngle * EquRef(:,RefOrder(iRef)); ... sin_equAngle ]; % Get the other points of this color. if (d>2) if (iD=iD); iA = iA + (iA>=iU); else L1 = [((base+1):(base+iU-1)) ... ((base+iU+1):(base+iD-1)) ... ((base+iD+1):(base+d+1)) ]; iA = rand_int(1,1,[1 (d-1)]); L2 = L1([1:(iA-1) (iA+1):(d-1)]); iA = iA + (iA>=iU); iA = iA + (iA>=iD); end Pts(1:(d-1),L2) = randn(d-1,d-2); Pts(1:(d-1),base+iA) = - Pts(1:(d-1),L2) * rand_real(d-2,1,[0 1]); for j = L1 Pts(1:(d-1),j) = Pts(1:(d-1),j)/norm(Pts(1:(d-1),j),2); end Pts(1:(d-1),L1) = sin_poleAngle * Pts(1:(d-1),L1); Pts(d,L1) = cos_poleAngle; elseif (d==2) iA = setdiff(1:(d+1), [iU iD]); lati = rand_real(1,1,[-poleAngle poleAngle]); Pts(:, base+iA) = [sin(lati); cos(lati)]; elseif (d==1) error('this routine not defined for d==1'); end end %% Generate the points of the last color. % This section does not generate exactly the configuration of reference % [1]. It is only an approximation. base = baseList(unsymmColor); % the sum of base and % numbers in [1 (d+1)] % covers all point % indices of this % color. iD = rand_int(1,1,[1,d+1]); L = [(base+1):(base+iD-1) (base+iD+1):(base+d+1)]; % List of indices of % points distribute % above equator. Pts(1:(d-1), L) = randn(d-1,d); for j = L Pts(1:(d-1),j) = Pts(1:(d-1),j)/norm(Pts(1:(d-1),j),2); Pts(1:(d-1),j) = - cos(safeAngle) * Pts(1:(d-1),j); Pts(d,j) = sin(safeAngle); end W = rand_real(d,1,[0 1]); % Coefficients of a for i=1:d % linear combination. if (rand(d,1)<(1/d)) % By statistic the W(i) = d*W(i); % chance of only 1 end % element has large end % coefficient is % expected to be 1/d. Pts(:,base+iD) = -Pts(:,L)*W/sum(W); Pts(:,base+iD) = Pts(:,base+iD)/norm(Pts(:,base+iD),2); %% Generate b as the origin. b = zeros(d,1); %% Partition tells that each color has (d+1) points. Partition = (d+1)*ones(1,(d+1)); return tors. % b is a column vector representing a point, and it is always generated %cfp/cfp_gencore_random.m000070001206620011610000000100431060752650200202510ustar00tstephenmast_faculty00004050013607function [Pts, Partition, b] = cfp_gencore_random(d) % % A random generator of general colorful feasibility problem core cases. % % % * Syntax * % % [Pts, Partition, b] = cfp_gencore_random(d) % % % * Description * % % [Pts,Partition,b]=cfp_gencore_random(d) randomly generates a general % colorful feasibility problem core case. % % *** % * Input Argument * % *** % The input argument d is the dimension for Euclidean space. % % % * Output Arguments * % % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hulls. All the colorful points are % unit vectors. Scaling the colorful points does not affect whether a % convex hull generated by them contain the origin, and b is the origin. % Hence, all the colorful points can be scaled to unit vectors. % b is a column vector representing a point, and it is always generated % as the origin. This output argument is for future potential update. % Partition is a row vector of length (d+1). Each element is an % integer no less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. This % function only assigns (d+1) points to each color, since in practice a % subset of size (d+1) containing b in the convex hull can always be found % when there are more than (d+1) points. Partition is an output % argument for future potential update. % % *** % * Algorithm * % *** % For each color, d points on the hypersphere are selected randomly with % the uniform distribution on the surface of hypersphere, then the (d+1)th % point is generated as a random convex combination of the antipodes of the % first d points. % The method of generating a random point with the uniform distribution % on the surface of hypersphere is: generate a point whose coordinates are % random real numbers from normal distribution (mean is 0), then normalize % the point. The reason to choose this method is because MATLAB randn() % function to generate real number with normal distribution. This method % can be referred to reference [1]. % % **** % * References * % **** % [1] Muller, M. E. "A Note on a Method for Generating Points Uniformly on % N-Dimensional Spheres" Comm. Assoc. Comput. Mach. 2, 19-20, 1959. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % August 2005: Added comments. % May 2006: Added CoreViolate parameter. % April 2007: Removed CoreViolate parameter. % Renamed to cfp_gencore_random(). %% Allocate memory for Pts. Pts = zeros(d, (d+1)*(d+1)); %% Generate the points of each color. for base = 0:(d+1):(d*d+d) % Generate a random place to place a special point in the set. i = rand_int(1,1,[1 (d+1)]); % Generate d points on the surface of hypersphere with uniform % distribution, by using real numbers from normal distribution. L = [((base+1):(base+i-1)) ((base+i+1):(base+d+1))]; Pts(:, L) = randn(d,d); for j = L Pts(:,j) = Pts(:,j)/norm(Pts(:,j),2); end % Generate the last point of this color as a convex combination of the % antipodes of the first d points. Pts(:, (base+i)) = - Pts(:, L)* rand_real(d,1,[0 1]); Pts(:, (base+i)) = Pts(:, (base+i)) / norm(Pts(:, (base+i)),2); end %% Generate b as the origin. b = zeros(d,1); %% Partition tells that each color has (d+1) points. Partition = (d+1)*ones(1,(d+1)); return cfp/cfp_init_regular.m000070001206620011610000000061401065052112400177470ustar00tstephenmast_faculty00004050013607function initT = cfp_init_regular(Pts, b, ColorPartition) % % A greedy algorithm to find a colorful set of points from given colorful % points. % % % * Syntax * % % initT = cfp_init_regular(Pts, ColorPartition , b) % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hull. % b is a column vector representing a point in the d-Euclidean space. % ColorPartition is a row vector of length (d+1). Each element is an % integer not less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. % % % * Output Arguments * % % initT is a row vector of length (d+1). Its elements are column indices of % Pts, specifying a colorful set of points (one point for each color). % % *** % * Algorithm * % *** % The angle between two vertices of the regular simplex centered at origin % is calculated. Points of each color are selected to make the angle with % the other points as close to the ideal angle as possible. % % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % July 2007: Unified interface in the package for the thesis % "Colourful Feasibility Problem: Algorithm, Bounds and % Implications". % d = length(b); ideal_dot = -1/d; % Get the number of colors. l = length(ColorPartition); % Allocate memory for initT. initT = zeros(1, l); % Choose the first point for the first color. initT(1) = 1; % Initialize the projection point. p = Pts(:,1); % base helps to enumerate all the point indices of each colors. base = ColorPartition(1); % Choose one point from each of the rest colors. for i = 2:l % Get the maximum of the minimum distance and the corresponding point. min_max_dotdiff = 2; for j = (base+1):(base+ColorPartition(i)) % Get the minimum distance to the points already in colorful set. max_dotdiff = 0; for k = 1:(i-1) dotdiff = abs( sum(Pts(:,j).*Pts(:,initT(k))) - ideal_dot ); if (dotdiff > max_dotdiff) max_dotdiff = dotdiff; end end % Keep the best point by comparison. if (max_dotdiff < min_max_dotdiff) min_max_dotdiff = max_dotdiff; pt_index = j; end end % Insert the selected point into the set represented by initT. initT(i) = pt_index; % Prepare base for next color. base = base + ColorPartition(i); end returnctor representing a point in the d-Euclidean space. % ColorPartition is a row vector of length (d+1). Each element is an % integer not less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. % % % * Output Arguments * % cfp/readme.TXT000070001206620011610000000052071102133467300161220ustar00tstephenmast_faculty00004050013607** MATLAB code for the Colourful Feasibility Problem. Copyright (C) 2006 by Sui Huang. This code is licenced under the GNU General Public Licences, more details are contained in the file "licence.TXT". This package contains the code files for the thesis "Colourful Feasibility: Algorithms, Bounds, and Implications" ([1]) and the paper "The Colourful Feasibility Problem" ([2]) ** The features in this package depends on the following external components: MATLAB Optimization Toolbox http://www.mathworks.com/products/optimization/ SeDuMi http://sedumi.mcmaster.ca/ YALMIP http://control.ee.ethz.ch/~joloef/yalmip.php Following are the brief descriptions of files. The random generators of Colourful Feasibility Problems (for [1][2]): cfp_gencore_highdensity.m cfp_gencore_lowdensity.m cfp_gencore_middensity.m cfp_gencore_random.m cfp_gencore_tube.m cfp_gen_infeasible.m cfp_gen_random.m The solvers of Colourful Core Feasibility Problems (for [1][2]): cfp_solver_bo1.m (depends on Matlab Optimization Toolbox) cfp_solver_bo2.m (depends on Matlab Optimization Toolbox) cfp_solver_multiupdate.m (depends on Matlab Optimization Toolbox) cfp_solver_maxvolume.m cfp_solver_randompick.m cfp_solver_hybrid.m (for [2] only) cfp_solver_mbo2 (for [2] only) The solvers for general Colourful Feasibility Problems (for [1]): cfp_solver_enumstretch.m cfp_solver_sdprelax.m (for infeasibility detection, depends on SeDuMi and YALMIP) The test script of solvers and random generators (for [1]): test_gen.m test_gencore.m test_infeasible.m The utility subroutines used by random generators and solvers (for [1][2]): private/accdot.m uses heuristic to get numerically accurate dot product private/accnorm.m uses heuristic to get numerically accurate norm private/accsum.m uses heuristic to get numerically accurate sum private/rand_int.m generates matrix of random integers private/rand_real.m generates matrix of random real numbers private/regular_simplex.m generates the coordinates of regular simplices The script of generating and organizing infeasible cases (for [1]): infeaGen.m The initialization routines of colourful simplex (for [2]): cfp_init_random.m cfp_init_proj.m cfp_init_maxdist.m cfp_init_regular.m cfp/cfp_solver_sdprelax.m000070001206620011610000000154561062062363000205130ustar00tstephenmast_faculty00004050013607function [x,info] = cfp_solver_sdprelax(Pts, b, ColorPartition) % % The semidefinite relaxation solver to solve colorful feasibility problem. % This function relaxes the colorful linear feasibility problem to a % semidefinite programming problem and tries to obtain a feasible solution % of colorful feasibility problem. % % % * Syntax * % % [x,info] = cfp_solver_sdprelax(Pts) % [x,info] = cfp_solver_sdprelax(Pts, b) % [x,info] = cfp_solver_sdprelax(Pts, b, ColorPartition) % % % * Description * % % [x,info]=clp_solver_sdprelax(Pts,b,ColorPartition) % solves for x satisfying the constraints: % _ % | Pts*x = b % | if x(i) and x(j) have the same color, then x(i)*x(j)=0 % | sum(x)=1 % |_ x>=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it is the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.feasible: 1 if x is feasible for the input colorful feasibility % problem, 0 if infeasible, -1 if unknown. If this member % is 1, then the info.relaxfeasi relax must be 1. % info.relaxfeasi: 1 if the relaxed problem is feasible, 0 if not. If this % member is 0, then info.feasible must be 0. % info.time: the number of seconds spent by the solver. % % *** % * Algorithm * % *** % We use Q to notate a square matrix such that Q(i,j)=1 if x(i) and x(j) % are for the same color, and Q(i,j)=0 otherwise, X to notate a square % matrix of proper size. Then the colorful feasibility problem can be % formulated as the nondefinite QP: % % min x'Qx % such that Px = 0 % sum(x) = 0 % x >= 0 % % and it can be relaxed to the SDP: % % min QX % such that Px = 0 % sum(x) = 0 % x >= 0 % [1 x'; x X] is PSD and symmetric % X >= 0 % % If the SDP optimal objective value is grater than zero, then the colorful % feasibility problem is not feasible. If the SDP optimal objective value % is zero, then the colorful feasibility may or may not be feasible. % % * % * Dependencies * % * % This routine following toolboxes or libraries: % yalmip library at http://control.ee.ethz.ch/~joloef/yalmip.php % sedumi at http://sedumi.mcmaster.ca % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % April 2007: First version by Sui Huang % % **** % * Some Local Variables * % **** % F : an object obtained by yalmip toolbox to hold all the constraints % of an optimization problem. % xvar : An object obtained by yalmip toolbox to hold optimization % variables. % bigXvar: an object obtained by yalmip toolbox to hold optimization % variables. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-8); % Allowed numerical error. if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE ColorPartition b % Initialize the info struct for output. info.feasible = 1; info.relaxfeasi = 1; info.time = 0; % Initialized: initTime % Formulate and solve the SDP. Q=[]; for i=1:length(ColorPartition) Q=blkdiag(Q,~eye(ColorPartition(i))); end xvar = sdpvar(NumPts,1); bigXvar = sdpvar(NumPts, NumPts, 'symmetric'); F1 = set(Pts*xvar==b, 'x elements are cofficients to get b'); F2 = set(sum(xvar)==1, 'x elements sum up to 1'); F3 = set(xvar>=0, 'elements in x are non-negative'); F4 = set([1 xvar'; xvar bigXvar]>=0, '[1 x; x bigX] is PSD'); F5 = set(sum(sum(bigXvar))==1, 'bigX elements sum up to 1'); F6 = set(bigXvar(:)>=0, 'bigX elements are non-negatives'); F = F1+F2+F3+F4+F5+F6; solveroption = sdpsettings('solver','sedumi', 'verbose',0, ... 'sedumi.stepdif',2, 'sedumi.sdp',1, ... 'sedumi.cg.qprec', 1); diagnostics = solvesdp(F, sum(sum(Q.*bigXvar)), solveroption); x = double(xvar); bigX = double(bigXvar); % initialized: diagnostics x if (diagnostics.problem==1) % SDP is infeasible info.relaxfeasi = 0; info.feasible = 0; info.time = etime(clock,initTime); return; else % SDP is feasible if (bigX(:)'*Q(:)>TOLERANCE) % colorful feasibility problem is infeasible info.relaxfeasi = 1; info.feasible = 0; info.time = etime(clock,initTime); elseif iscolorful(x,ColorPartition,TOLERANCE) % fortunately the solution of SDP is also a solution of colorful % feasibility problem info.relaxfeasi = 1; info.feasible = 1; info.time = etime(clock,initTime); else % the solution of SDP is not a solution of colorful feasibility % problem info.relaxfeasi = 1; info.feasible = -1; info.time = etime(clock,initTime); end end return function flag = iscolorful(x, ColorPartition, TOLERANCE) base = 0; posFlag = x>TOLERANCE; for i=1:length(ColorPartition) if (sum(posFlag((base+1):(base+ColorPartition(i))))>1) flag = 0; return; end base = base + ColorPartition(i); end flag = 1; returns members. % info.feasible: 1 if x is feasible for the input colorful feasibility % problem, 0 if infeasible, -1 if unknown. If this member % is 1, then the info.relaxfeascfp/licence.TXT000060001206620011610000000012701102134115000162460ustar00tstephenmast_faculty00004050013607MATLAB code for the Colouful Feasibility Problem. Copyright (C) 2006 by Sui Huang, McMaster University This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The full licence is available on-line at: . cfp/cfp_solver_bo1.m000070001206620011610000000262701065046030600173500ustar00tstephenmast_faculty00004050013607function [x,info] = cfp_solver_bo1(Pts,b,ColorPartition,options) % % BARANY-ONN algorithm 1 to solve colorful linear programming problem. % % % * Syntax * % % [x, info] = cfp_solver_bo1(Pts) % [x, info] = cfp_solver_bo1(Pts, b) % [x, info] = cfp_solver_bo1(Pts, b, ColorPartition) % [x, info] = cfp_solver_bo1(Pts, b, ColorPartition, options) % % % * Description * % % [x, info] = cfp_solver_bo1(Pts, b, ColorPartition) % solves for x satisfying the constraints: % _ % | Pts*x = b % | if x(i) and x(j) have the same color, then x(i)*x(j)=0 % | sum(x)=1 % |_ x>=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -2 if % numerical error. % % *** % * Algorithm * % *** % More details about the algorithm can be found in the publication % "Colourful Linear Programming and its Relatives" by IMRE BARANY and % SHMUEL ONN (Math. Oper. Res. 22, 550-557, 1997). % In each iteration the algorithm finds the point xk in the convex hull % of the current colorful set of points with minimum distance to b % (considered as the origin). xk can be represented as a linear combination % of the points of the current colorful set, and some points have zero as % their coefficients. The algorithm replaces one of these points with a % point of the same color, which minimizes the inner product with xk. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % August 2005: Use linsolve() function for speed up. % May 2006: Fixed a bug in generating data structure ColorMap. % April 2007: Renamed to cfp_solver_bo1(). % % * % * Dependencies * % * % Following functions are not in basic MATLAB library, and this routine % depends on them: % linprog() optimization toolbox % quadprog() from MATLAB Optimization toolbox % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % xk : A point in the colorful convex hull, whose distance to b is minimum. % p : A vector presenting a point belong to the convex hull of the % colorful set, notated conv(T). % a : A scalar between 0 and 1 to shrink a vector. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 100000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/norm(Pts(:,cnt),2); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap % Initialize some variables for the iterations. T = options.initT; LoopCnt = 0; % Counter of iterations. % Initialized: T LoopCnt % The iterations of updating the colorful set of points until the convex % hull of the set contains b. while (1) % Test if the initial colorful set is feasible by trying to express b % as a convex combination of T. Gaussian elimination is used by the % function linsolve() to find the coefficients of mapping T to b. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check % if b is in the simplex. [tmp,LPfval,FeasibleFlag]... =linprog(sparse(zeros(d+1,1)),[],[],... [OriginPts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],optimset('Display','off')); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_bo1'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>1000) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; x = zeros(NumPts, 1); return; end end % Changed: LoopCnt % use quadratic optimization routine to obtain the minimum-norm-point % in conv(T). Following is the formulation of the problem in 2D, which % can be generalized to high dimensional space. % Let the vertices of simplex be (x11,x12,x13), (x21,x22,x23), % (x31,x32,x33). Let c1,c2,c3>=0 and c1+c2+c3=1 be the coefficients of % the vertices to generate a point in simplex. The square of 2-norm of % a point in simplex is (the objective function to be minimized): % c1*c1*(x11*x11+x12*x12+x13*x12) % + ... % + ci*cj*(xi1*xj1+xi2*xj2+xi3*xj3) % + ... % + c3*c3*(x31*x31+x32*x32+x33*x33) % The variables are c1,c2,c3. The constraints are c1,c2,c3>=0 and % c1+c2+c3=1. % Get the matrix for objective function. H = zeros(NumColor,NumColor); for i=1:NumColor for j=i:NumColor % Use a more numerically accurate way to calculate dot product, % since numerical stability is important. H(i,j) = accsum(Pts(:,T(i)).*Pts(:,T(j))); H(j,i) = H(i,j); end end % Get the optimal coefficients. [c,dummy,FeasibleFlag] ... = quadprog(H,[],[],[],ones(1,NumColor),... 1,zeros(NumColor,1),[],... ones(1,NumColor)/NumColor,... optimset('Display','off','LargeScale','off')); if (FeasibleFlag<=0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts,1); return end % Get the minimum-norm-point in the simplex. xk = zeros(d,1); for i = 1:d xk(i) = accdot(Pts(i,T), c'); end % Get the list of colors that the points can be replaced. color_out_list = find(abs(transpose(c))=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -2 if % numerical error. % % *** % * Algorithm * % *** % More details about the algorithm can be referred to the publication % "Colourful Linear Programming and its Relatives" by IMRE BARANY and % SHMUEL ONN (Math. Oper. Res. 22, 550-557, 1997). % The algorithm updates a colorful set of points T and a point xk on the % surface of conv(T) at each iteration. In each iteration, The algorithm % finds a linear combination transforming T into xk, such that some points % in T has zero as coefficients; then replaces one of the zero-coefficient % points with a point t of the same color, minimizing the inner product of % t and xk; then find p, which is the projection of b in the line segment % between t and xk; then shrink p to the surface of conv(T) and let xk=p. % There are some notes for this algorithm: % 1) This algorithm has zigzagging performance in some cases. % 2) The accumlation of numerical error on xk cannot be avoided, because % the update of xk depends on its previous value. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % Jul 2005: First version. % Aug 2005: Added comments. % Sep 2005: Update the algorithm to shrink p. % May 2006: Fixed a bug in generating data structure ColorMap. % April 2007: Renamed to cfp_solver_bo2(). % % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % xk : A point in the colorful convex hull, whose distance to b is reduced % after each iteration. % p : A vector presenting a point belong to the convex hull of the % colorful set, notated conv(T). % a : A scalar between 0 and 1 for shrinking p. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 1000000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/norm(Pts(:,cnt),2); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap % Initialize some variables for iterations. T = options.initT; xk = Pts(:,T(1)); % Initialize xk to the first point in T. iFree = 2; % A color index to be replaced. LoopCnt = 0; % Counter of iterations. % Initialized: T xk LoopCnt % Test if the initial colorful set is feasible by trying to express b as a % convex combination of T. Gaussian elimination is used by the function % linsolve() to find the coefficients of mapping T to b. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check if b % is in the simplex. [tmp,LPfval,FeasibleFlag]... =linprog(sparse(zeros(d+1,1)),[],[],... [OriginPts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],... optimset('Display','off', 'LargeScale', 'off')); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % The iterations updating T until b is in conv(T). while any(abs(xk)>TOLERANCE) % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_bo2'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>10) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; x = zeros(NumPts, 1); return; end end % Changed: LoopCnt % Replace one zero-coefficient points. p = xk; % Initialize the projection of origin minProd = TOLERANCE; % Initialize the minimum inner % product. for j=ColorMap(iFree).list % Search for the point of minimum % inner product p. Prod = dot(Pts(:,j), p); if (Prod < minProd) j_in = j; minProd = Prod; end end T(iFree) = j_in; % Replace one point. t = Pts(:,j_in); % t is the new point. p = (dot(t-p,t)*p + dot(p-t,p)*t) ... % p is the projection of / dot(t-p,t-p); % origin on a line segment. % Changed: T % Shrink p to the surface of conv(T), and let xk=p. The algorithm goes % through all the separating facets of conv(T). A separating facet % generates a hyperplane separating origin from conv(T) in the % Euclidean space. Y = inv([Pts(:,T); ones(1, NumColor)]); % Each row of Y contains the % normal vector of a facet; % the negative elements in the last column indicates % separating facets. if any(any(~isfinite(Y))) % When T is affinely dependent, use linprog() shrink p. [tmp,lambda,exitflag]=... linprog([zeros(d+1,1) 1], [], [], ... [Pts(:,T) -p; ones(1,d+1) 0], [zeros(d,1); 1], ... zeros(d+2,1), ones(d+2,1), ... [ones(d+1,1)/(d+1); 1], ... optimset('LargeScale', 'off', 'Display', 'off') ); if (exitflag<=0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts,1); return end if (aTOLERANCE) A = [Pts(:,T); ones(1, NumColor)]; iFree = 0; for i=1:(d+1) [tmp,lambda,exitflag] = linprog(zeros(d,1),[],[],... A(:,[1:(i-1) (i+1):(d+1)]),[xk;1],... zeros(d,1), ones(d,1),... ones(d,1)/d, ... optimset('Large Scale', 'off', 'Display', 'off')); if (exitflag>=1) iFree = i; break; end end if (iFree==0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts,1); return end end continue; else % Solves the linear optimization problem: % min a % such that: a*(Y(i,1:d)*p)<=Y(i,d+1) forall i; % where : _ % | if Y(i,d+1)<0, the function Y(i,1:d)*x=Y(i,d+1) is % | the affine hyperplane generated by a seperating % |_ facet. a = -Inf; for i = find(Y(:,(d+1))<(-TOLERANCE))' m = -(Y(i,1:d)*p); if ((abs(m) > TOLERANCE) && ((Y(i,d+1)/m) > a)) a = Y(i,d+1)/m; iFree = i; end end % If a is between 0 and 1 after scanning all the separating facets, % b is not in the convex hull of T. Otherwise b is already in the % convex hull of T and the algorithm can terminate. if (a>0) % The condition a<=1 is satisfied by the context that only % separating facets are scanned. xk = a*p; else % Terminate the algorithm. break; end end % Changed: xk iFree end % Changed: T % Prepare the results and terminate the algorithm. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check if b % is in the simplex. tmp = linprog(sparse(zeros(d+1,1)),[],[],... [OriginPts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],optimset('Display','off')); end info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts,1); x(T) = tmp; return cfp/cfp_solver_hybrid.m000070001206620011610000000431301065051763600201530ustar00tstephenmast_faculty00004050013607function [x,info]=cfp_solver_hybrid(Pts,b,ColorPartition,options) % % The hybrid of Multi-update algorithms and Barany-Onn-2 algorithm to solve % colourful feasibility problem. % % % * Syntax * % % [x, info] = cfp_solver_hybrid(Pts) % [x, into] = cfp_solver_hybrid(Pts, b) % [x, info] = cfp_solver_hybrid(Pts, b, ColorPartition) % [x, info] = cfp_solver_hybrid(Pts, b, ColorPartition, options) % % % * Description * % % [x, info] = cfp_solver_hybrid(Pts, b, ColorPartition) % solves for x satisfying the constraints: % _ % | Pts*x = b % | if x(i) and x(j) have the same color, then x(i)*x(j)=0 % |_ for all valid i, x(i)>=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.light: the number of light iterations (not need to break an % oscillation). % info.heavy: the number of heavy iterations (breaks an oscillation). % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -2 if % numerical error. % % *** % * Algorithm * % *** % The algorithm updates a colorful set of points T and a point xk on the % surface of conv(T) at each iteration. Normally the algorithm works % similar to Barany-Onn-2 algorithm but attempts to update multiple points % at each iteration. If oscillation is detected (the algorithm reaches a % previously reached colorful set), then a Multi-update step is used to % quit the oscillation. % There are some notes for this algorithm: % 1) It does not detect all the oscillations because it only records a % finite number of previous colorful sets. % 2) Some cases of oscillation may only take short times, but the algorithm % will still use Multi-update step to quit it. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % Sep 2005: First version. % Jly 2007: Unied with the other routines in the thesis: % "Colourful Feasibility: Algorithms, Bounds, and Implications". % % * % * Dependencies * % * % Following functions are not in basic MATLAB library, and this routine % depends them: % linprog() % quadprog() % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % xk : A point in the colorful convex hull, whose distance to b is reduced % after each iteration. % p : A vector presenting a point belong to the convex hull of the % colorful set, notated conv(T). % a : A scalar used to shrink vectors. % TRec: A data structure to record the previous colorful sets. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 1000000; % Allowed iterations. TRecLen = 2; % The number of previous % colorful to record. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % TRecLen options % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/norm(Pts(:,cnt),2); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % Construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; head = 1; tail = ColorPartition(1); for cnt=1:NumColor ColorMap(cnt).list = head : tail; head = head + ColorPartition(cnt); tail = tail + ColorPartition(cnt); end % Initialized: ColorMap % Initialize some variables for iterations. T = options.initT; % Represents a colorful set of points. TRec = zeros(TRecLen,d+1); % Initialize TRec. TRec(1,:) = T; % Record the initial colorful set. TRecPtr = 1; % The pointer to update TRec in the way of % "Round Robin". xk = Pts(:,T(1)); % Initialize xk to the first point in T. color_out_list = 2:NumColor; info.light = 0; % Counter of light iterations. info.heavy = 0; % Counter of heavy iterations. info.iter = 0; % Counter of total iterations. % Initialized: T TRec TRecPtr xk info % Test if the initial colorful set is feasible by trying to express b % as a convex combination of T. Gaussian elimination is used by the % function linsolve() to find the coefficients of mapping T to b. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check % if b is in the simplex. [tmp,LPfval,FeasibleFlag]... =linprog(sparse(zeros(d+1,1)),[],[],... [OriginPts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],optimset('Display','off')); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = 0; info.light = 0; info.heavy = 0; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % The iterations updating T until b is in conv(T). while any(abs(xk)>TOLERANCE) % Count the number of iterations. if ( ((info.light+info.heavy)>LoopLimit) ... &&(mod(info.light+info.heavy,LoopLimit)==1)) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_hybrid'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, info.light+info.heavy'); disp(sbuf); if (floor((info.light+info.heavy)/LoopLimit)>1000) info.feasbile = -1; x = zeros(1,NumPts); info.time = etime(clock,initTime); return; end end % Changed: info % Replace all zero-coefficient points. p = xk; % Initialize the projection % of origin. for color_out_index = color_out_list minProd = TOLERANCE; % Initialize the minimum % inner product. for j=ColorMap(color_out_index).list % Search for the point of % minimum inner product p. Prod = dot(Pts(:,j), p); if (Prod < minProd) j_in = j; minProd = Prod; end end T(color_out_index) = j_in; % Replace one point. t = Pts(:,j_in); % t is the new point. p = (dot(t-p,t)*p + dot(p-t,p)*t) ... % p is the projection of / dot(t-p,t-p); % origin on a line segment. end % Changed: T % Check if the current colorful set is previously reached, and decide % heavy or light iteration to perform in this iteration. IterType = 'L'; % The default is light. for i=1:TRecLen if all(T==TRec(i,:)) IterType = 'H'; % Perform heavy. break; end end % Initialized: IterType % Increment TRecPtr and record the current colorful set. if (TRecPtr TOLERANCE)&&((Y(i,d+1)/m) > a)) a = Y(i,d+1)/m; iFree = i; end end % If a is between 0 and 1 after scanning all the separating % facets, b is not in the convex hull of T. Otherwise b is % already in the convex hull of T and the algorithm can % terminate. if (a>0) % The condition a<=1 is satisfied by the context that only % separating facets are scanned. p = a*p; else % Terminate the algorithm. break; end end % Changed: p iFree % Find p0, the projection of origin on the affine hyperplane holding % p. t = Y(iFree,1:d)'; p0 = (-Y(iFree,d+1))*t/dot(t,t); % Initialized: p0 % Shrink p towards p0, such that p is on the boundary of the facet % holding it. Then update xk to p. This is done by solving the linear % optimization problem: % min a % such that: Y(i,1:d)*(p0+a*(p-p0))<=Y(i,d+1) forall i % where : _ % | the function Y(i,1:d)*x=Y(i,d+1) is the affine % |_ hyperplane seperating p0 from conv(T). color_out_list = iFree; a = -Inf; t = p - p0; for i = find(Y*[p0;1]<(-TOLERANCE))' s = -(Y(i,1:d)*p0); m = -(Y(i,1:d)*t); if ((abs(m)>TOLERANCE)&&(((Y(i,d+1)-s)/m)>a)) a = (Y(i,d+1)-s)/m; iFree = i; end end if (a>0) color_out_list = [color_out_list iFree]; xk = p0 + a*t; else xk = p0; end % Changed: xk color_out_list else % Increment the counter of heavy iterations. info.heavy = info.heavy + 1; info.iter = info.iter + 1; % Changed: LoopCnt % use quadratic optimization routine to obtain the minimum-norm-point % in conv(T). Following is the formulation of the problem in 2D, which % can be generalized to high dimensional space. % Let the vertices of simplex be (x11,x12,x13), (x21,x22,x23), % (x31,x32,x33). Let c1,c2,c3>=0 and c1+c2+c3=1 be the coefficients of % the vertices to generate a point in simplex. The square of 2-norm of % a point in simplex is (the objective function to be minimized): % c1*c1*(x11*x11+x12*x12+x13*x12) % + ... % + ci*cj*(xi1*xj1+xi2*xj2+xi3*xj3) % + ... % + c3*c3*(x31*x31+x32*x32+x33*x33) % The variables are c1,c2,c3. The constraints are c1,c2,c3>=0 and % c1+c2+c3=1. % Get the matrix for objective function. H = zeros(NumColor,NumColor); for i=1:NumColor for j=i:NumColor % Use a more numerically accurate way to calculate dot product, % since numerical stability is important. H(i,j) = accsum(Pts(:,T(i)).*Pts(:,T(j))); H(j,i) = H(i,j); end end % Get the optimal coefficients. [c,dummy,FeasibleFlag] ... = quadprog(H,[],[],[],ones(1,NumColor),... 1,zeros(NumColor,1),[],... ones(1,NumColor)/NumColor,... optimset('Display','off','LargeScale','off')); if (FeasibleFlag<=0) info.iter = info.light+info.heavy; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts,1); return end % Get the minimum-norm-point in the simplex. xk = zeros(d,1); for i = 1:d xk(i) = accdot(Pts(i,T), c'); end % Get the list of colors that the points can be replaced. color_out_list = find(abs(transpose(c))= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = 0;cfp/cfp_gencore_tube.m000070001206620011610000000120611061077153400177330ustar00tstephenmast_faculty00004050013607function [Pts,Partition,b]=cfp_gencore_tube(d,tubeAng,unbalancedFlag) % % A random generator of tube type colorful feasibility problem core cases. % % % * Syntax * % % [Pts,Partition,b]=cfp_gencore_tube(d) % [Pts,Partition,b]=cfp_gencore_tube(d,tubeAng) % [Pts,Partition,b]=cfp_gencore_tube(d,tubeAng,unbalancedFlag) % % % * Description * % % [Pts,Partition,b]=cfp_gencore_tube(d) randomly generates a tube type % colorful feasibility problem core case, whose colorful points cluster in % two opposite caps of a hypersphere. % % *** % * Input Argument * % *** % The input argument d is the dimension for Euclidean space. % The optional argument tubeAng is the maximum angle between a point and % the axis through the centers of the caps. 0=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -3 if % degenerated colorful simplex is encountered. % % *** % * Algorithm * % *** % This algorithm keeps a colorful set of points, and update the set at each % iteration. At each iteration, there is some point in the set separated % from b by its opposite facet. These seperated points indicates potential % replacements. Each potential replacement replaces a point in the set by a % point of the same color and not seperated from b by the opposite facet. % The algorithm performs one of these potential replacement such that the % hyper volume of the convex hull of the set is maximized. % An important point for the implementation and outcome of this algorithm % is: since the algorithm tries to keep the hyper volume of the simplex % large, the colorful set of points will not be affinely dependent. %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % August 2005: Used function linsolve() to solve linear equation system. % May 2006: Fixed a bug in generating data structure ColorMap. % Made vector M compatible abritary size of point sets. % April 2007: Renamed to cfp_solver_maxvolume(). % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. In the comment of code, T can be % used to denote a set of points according to the context. For % example, aff(T\{T{i}}) denotes the affine hyperplane generated by % the points indexed by T except the one of color i. % LUM: A row vector containing coefficients for points in the colorful set % indicated by T. LUM represents a linear combination mapping the % colorful set to b. Discarding numerical error, sum(LUM)=1 should be % true after each iteration, and all(LUM>=0) should also be true after % the last iteration. % M : A row vector recording the relative distance of all the points to % their corresponding affine hyperplanes. These conditions holds after % each iteration: among the points of the same color i, the distance % between point j and aff(T\{T(j)}) is proportional to M(j); the sign % of M(j) indicates which side of the hyperplane point j locates. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 1000000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/norm(Pts(:,cnt),2); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap % Initialize the state variables according to the initial colorful set. % After this section, it can be proved that the state variables satisfy the % following conditions: % Among the points of the same color i, the distance between point j and % aff(T\{T(j)}) is proportional to M(j). The sign of M(j) indicates which % side of the hyperplane point j locates. % NegColorList records the indices of elements in LUM that has negative % value. NumNegColor is the length of NegColorList. T = options.initT; A = [Pts(:, T); ones(1,NumColor)]; trail = 0; while (rank(A)<(d+1)) % if T is degenerated, take some chance to find a non-degenerated one % by random process if (trail>10) info.iter = 0; info.time = etime(clock,initTime); info.feasible = -3; x = zeros(NumPts, 1); return end base = 0; for cnt = 1:NumColor T(cnt) = base+rand_int(1,1,[1 ColorPartition(cnt)]); base = base + ColorPartition(cnt); end trail = trial + 1; end Y = inv(A); M = zeros(1, NumPts); for i = 1:NumColor M(ColorMap(i).list) = ... Y(i,:) * [Pts(:,ColorMap(i).list);ones(1,ColorPartition(i))]; end M(T) = 1; LUM = Y * [b;1]; NegColorList = find(LUM<(-TOLERANCE))'; NumNegColor = length(NegColorList); % Initialized: T LUM M NegColorList NumNegColor % Initialize the counter of iterations. LoopCnt = 0; % Initialized: LoopCnt % The iterations of updating the colorful set of points until the convex % hull of the set contains b. When all elements in LUM are non-negative, % the convex hull contains b. while (NumNegColor > 0) % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_maxvolume'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>10) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; x = zeros(NumPts, 1); return; end end % Changed: LoopCnt % Find which color of the colorful set to update, and which point of % that color to bring into the set. The general rule of updating the % colorful set is described at the begining of this file. In the % implementation aspect, two facts are utilized: % (1) The points in T that have negative coefficients in LUM is % seperated from b by their corresponding affine hyperplanes, % which is generated by the points in T except themselves. % (2) If the bottom facet of a hyper simplex does not change, its % hyper volume is proportional to the distance between its top % vertex and the hyperplane that contains the bottom facet. if ( NumNegColor > 1 ) % If there are multiple candidates colors to be chosen from, % calculate and compare the colorful simplex volumes, and choose the % color that leading to the maximum volume. tmpT = T; maxVol = 0; for i = NegColorList % Find the local maximum volume replacement for the current % color. The point indices of this color are buffered in % ColorMap. The search of local maximum volume replacement is % implemented by the search of minimum M element corresponding to % the points of this color, since the bottom facet of the hyper % simplex does not change. [dum, tmp] = min(M(ColorMap(i).list)); j = ColorMap(i).list(tmp); % Get the volume of the local maximum replacement. This section % may not need to get the exact value of volume, because any % value proportional to the volume can be used to find the best % replacement by comparison. tmpT(i) = j; % The colorful set this % replacement leads to. selected_pts = Pts(1:d, tmpT); for cnt=2:(d+1) selected_pts(:,cnt) = selected_pts(:,cnt) ... - selected_pts(:,1); end Vol = abs(det(selected_pts(:, 2:(d+1)))); % Vol is d! times of % the actual volume. tmpT(i) = T(i); % Restore the temporary % variable. % Record the global maximum volume replacement by comparison. if (Vol>maxVol) maxVol = Vol; iMaxVol = i; jMaxVol = j; end end else % If there is only one candidate color can be updated, decide which % point to bring into the colorful set, without calculating or % comparing the resulted colorful simplex volumes. iMaxVol = NegColorList; [dum, tmp] = min(M(ColorMap(iMaxVol).list)); jMaxVol = ColorMap(iMaxVol).list(tmp); end T(iMaxVol) = jMaxVol; % Initialized: iMaxVol jMaxVol % Changed: T % Update the state variables according to the initial colorful set. % After this section, it can be proved that the state variables satisfy % following conditions: % Among the points of the same color i, the distance between point j % and aff(T\{T(j)}) is proportional to M(j). The sign of M(j) indicates % which side of the hyperplane point j locates. A = [Pts(:, T); ones(1,NumColor)]; Y = inv(A); M = zeros(1, NumPts); for i = 1:NumColor M(ColorMap(i).list) = ... Y(i,:)*[Pts(:,ColorMap(i).list); ones(1,ColorPartition(i))]; end M(T) = 1; LUM = Y * [b;1]; NegColorList = find(LUM<(-TOLERANCE))'; NumNegColor = length(NegColorList); % Changed: LUM M NegColorList NumNegColor end % Changed: T % Prepare the outputs. The solution x needs to be calculated from % OriginPts, whose point coordinates are not normalized. The calculation % does not need to handle the case of affinely dependent colorful set, % due to the update rule in this algorithm. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = linsolve([OriginPts(:,T); ones(1, NumColor)], [b; 1]); return cfp/cfp_init_random.m000070001206620011610000000041761065052111600175760ustar00tstephenmast_faculty00004050013607function initT = cfp_init_random(Pts, b, ColorPartition) % % A random algorithm to find a colorful set of points from given colorful % points. % % % * Syntax * % % initT = cfp_init_random(Pts, ColorPartition , b) % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hull. % b is a column vector representing a point in the d-Euclidean space. % ColorPartition is a row vector of length (d+1). Each element is an % integer not less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. % % % * Output Arguments * % % initT is a row vector of length (d+1). Its elements are column indices of % Pts, specifying a colorful set of points (one point for each color). % % *** % * Algorithm * % *** % Select one point from each color randomly. % % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % July 2007: Unified interface in the package for the thesis % "Colourful Feasibility Problem: Algorithm, Bounds and % Implications". % % Get the number of colors. l = length(ColorPartition); % Allocate memory for initT. initT = zeros(1, l); % The variable base helps to enmulate all the point indices of each colors. base = 0; % Randomly select one point from each color. for i = 1:l initT(i) = rand_int(1, 1, [(base+1) (base+ColorPartition(i))]); base = base + ColorPartition(i); end return colorful % points. % % % * Syntax * % % initT = cfp_init_random(Pts, ColorPartition , b) % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space.cfp/cfp_gencore_highdensity.m000070001206620011610000000105051060752310200213040ustar00tstephenmast_faculty00004050013607function [Pts,Partition,b]=cfp_gencore_highdensity(d,r) % % A random generator of colorful feasibility problem core cases with large % number of feasible solutions. These random problems are essentially some % particular structured configurations up to perturbation and shuffling % of the order of points. % % % * Syntax * % % [Pts, Partition, b] = cfp_gencore_highdensity(d) % [Pts, Partition, b] = cfp_gencore_highdensity(d, r) % % % * Description * % % [Pts,Partition,b]=cfp_gencore_highdensity(d,r) randomly generates a % colorful feasibility problem core case with large number of feasible % solutions. If r<=1/d, then the number of solutions reaches the maximum % % *** % * Input Argument * % *** % The input argument d is the dimension for Euclidean space. % The optional argument r defines how close do d points of the same color % cluster. The default is 1/d to garantee there exist d^(d+1)+1 valid % solutions. % % % * Output Arguments * % % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is % the number of dimensions of the Euclidean space. The points in each color % of Pts must contain b in their convex hulls. All the colorful points are % unit vectors. Scaling the colorful points does not affect whether a % convex hull generated by them contain the origin, and b is the origin. % Hence, all the colorful points can be scaled to unit vectors. % b is a column vector representing a point, and it is always generated % as the origin. This output argument is for future potential update. % Partition is a row vector of length (d+1). Each element is an % integer no less than (d+1), specifying the number of points in a color. % For example [3 4 3] tells that the first 3 points in Pts are in the first % color, the following 4 points are in the second color, and so on. This % function only assigns (d+1) points to each color, since in practice a % subset of size (d+1) containing b in the convex hull can always be found % when there are more than (d+1) points. Partition is an output % argument for future potential update. % % **** % * References * % **** % [1] A Deza, S Huang, T Stephen and T Terlaky, "Colourful Simplicial % Depth", Discrete & Computational Geometry, Volume 35, 597-615. %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % August 2005: Added comments. % May 2006: Added CoreViolate parameter. % April 2007: Removed CoreViolate parameter. % Renamed to cfp_gencore_highdensity(). %% Apply the default input arguments. if ((nargin<2)||isempty(r)) r = 1/d; end %% Generate regular simplex points % to guide the distribution of colorful points. RegularPts = regular_simplex(d); c = sum(RegularPts,2)/(d+1); n = norm(RegularPts(:,1)-c, 2); for i=1:(d+1) RegularPts(:,i) = RegularPts(:,i) - c; RegularPts(:,i) = RegularPts(:,i)/n; end %% Allocate memory for Pts. Pts = zeros(d, (d+1)*(d+1)); %% Generate the points of each color. ColorOrder = randperm(d+1); iColor = 0; for base = 0:(d+1):(d*d+d) % Increment the color. iColor = iColor + 1; % Buffer a vertex of the regular simplex. c = RegularPts(:,ColorOrder(iColor)); % Generate a random place to place a special point in the set. i = rand_int(1,1,[1 (d+1)]); % Generate d points around a vertex of the regular simplex. L = [((base+1):(base+i-1)) ((base+i+1):(base+d+1))]; for j = L t = randn(d,1); t = c + r*t/norm(t,2); Pts(:,j) = t/norm(t,2); end % Generate the last point of this color as a convex combination of the % antipodes of the first d points. Pts(:, (base+i)) = - Pts(:, L)* rand_real(d,1,[0 1]); Pts(:, (base+i)) = Pts(:, (base+i)) / norm(Pts(:, (base+i)),2); end %% Generate b as the origin. b = zeros(d,1); %% Partition tells that each color has (d+1) points. Partition = (d+1)*ones(1,(d+1)); return cfp/cfp_solver_enumstretch.m000070001206620011610000000475121061075140000212240ustar00tstephenmast_faculty00004050013607function [x,info] = cfp_solver_enumstretch(Pts,b,ColorPartition) % % Use enumeration algorithm with heuristic stretching the distance between % points to solve colorful feasibility problems. % % % * Syntax * % % [x,info]=cfp_solver_enumstretch(Pts) % [x,info]=cfp_solver_enumstretch(Pts,b) % [x,info]=cfp_solver_enumstretch(Pts,b,ColorPartition) % % % * Description * % % [x,info]=clp_solver_enummaxv(Pts,b,ColorPartition) % solves for x satisfying the constraints: % _ % | Pts*x = b % | if x(i) and x(j) have the same color, then x(i)*x(j)=0 % | for all valid i, x(i)>=0 % |_ sum(x) = 1 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it is the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % % % * Output Arguments * % % x is the solution of the problem. info is a struct that tells the exiting % state, following are its members. % info.iter: the number of inner iterations to solve the problem, which % indicates the number of colorful simplices tested in this % algorithm. % info.numset: the number of outer iterations to solve the problem, which % indicates the number of subset of points selected in this % algorithm. % info.time: the number of seconds spent by the solver. % info.feasible: returns 1 if the problem is feasible, 0 if the problem is % not feasible. % % *** % * Algorithm * % *** % We first choose a set of points and check all the colorful simplices in % it. If no feasible solution is found, we find another set, check all the % simplices in the new set, and then check simplices which contain points % from both of the two sets, at last combine the two sets into the checked % set. We go on with finding another set from unchecked set and continue % the algorithm. The algorithm terminates when either a solution found or % all the simplices were gone through. % The method we use to choose a new set is like this: first find 1 % unchecked ponit from each color (omit if all points in that color are % checked) using heuristic idea selecting the points far away from each % other. We select up to one more point form each color if there are some % more unchecked points to increase the total volume covered by the subset. % The complexity of testing each simplex is O(n^3). %% %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Hanxing Zhang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % August 2006: first edition and add comments by Hanxing Zhang % Oct 2006: interface, variable scope, and comments are updated by Sui % Huang % Mar 2007: modified the comment of nextEnum sub-routine % April 2007: Renamed to cfp_solver_enumstretch(). % Updated the interface by Sui Huang. % % * % * Some Data Structures intended to be Shared by nested functions * % * % M: stores the normalized coordinates of points % Unchk: the set of points generating colourful simplices that haven't % been tested % Chk: the set of points generating colourful simplices that have been % tested % S: the set of points moving from Unchk to Chk % % * % * Coding Issue * % * % The sub-functions are nested into the main solver function, so all local % variables defined in main solver function can be read/modified in the % sub-functions but not in outer scopes, this way of sharing data avoids a % danger: main solver function modifies data outside its scope by % unfortunately using the same global variable name with outer scope. % However, there is a drawback, some data which is not intended to be % shared between main solver function and sub-functions, such as some % counters, are forced to be shared if they are in the same variable name. % To overcome this drawback, differences in variable names are made between % main solver function and sub-functions. %% % Initialize the time counter. initTime = clock; % Initialized: initTime % Preprocessing data [d NumPts]=size(Pts); % Space dimension and the % number of points. if (nargin<3)||isempty(ColorPartition) ColorPartition = (d+1)*ones(1,d+1); % Default is (d+1) points for % each color. end if (nargin<2)||isempty(b) b=zeros(d,1); % Default is origin. end NumColor = length(ColorPartition); % The number of colors M = Pts; % Buffer the normalized coordinate data for cnt = 1:NumPts % Normalize all the points M(:,cnt) = M(:,cnt) - b; M(:,cnt) = M(:,cnt)/norm(M(:,cnt),2); end % Initialize the auxiliary indixing data structures: % A colourful set of points is represented by a structure holding subsets % of different colours, and each of these subset is represented by a vector % holding the indices of points. For each colourful set of points, an extra % vector may be used to track how many points of each colour do it has. base = 0; for cnt=1:NumColor % Tells which points each color has. ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end base = 0; for cnt=1:(NumColor) % Tells which points are not checked Unchk(cnt).list = (base+1) : (base+ColorPartition(cnt)); nsUnchk(cnt) = ColorPartition(cnt); base = base + ColorPartition(cnt); end for cnt=1:(NumColor) % An empty set of points EmptySet(cnt).list = []; nsEmptySet(cnt) = 0; end Chk = EmptySet; % Initialize the set of checked points nsChk = nsEmptySet; S = EmptySet; % Initialize the set S nsS = zeros(1,NumColor); info.numset = 0; % Number of colourful subsets info.iter = 0; % Number of simplices tested while (1) % Increment the subset count. info.numset = info.numset+1; % Update the set S. flag = newS(ColorPartition,b); if (flag==2) % All points are checked, which means there exist no colourful % simplex covering the origin. x = zeros(NumPts,1); info.feasible = 0; info.time = etime(clock,initTime); return end % Check the simplices inside S. This section will matter if and only % if all the colors in the set have at least one point. Because S is a % sequence of vectors, and each vector is a sequence of indices of % points, it provides an order of colours and an order of points in % each colours, for the colourful set it is representing. These % ordering allow us to enumerate all the colourful simplices generated % by the set S. A vector T is used to enumerate the selections of % vertices for colourful simplices in the set: % for example, T=[1 2 2] means choosing the first point % in the first colour, the second point in the second % colour, and the second point in the three, and use % them as the vertices of a colourful simplex. if all(nsS) % Check the colourful simplices of S. The simplices are divided % into subsets: all the vertices are the first points of their % colour, one vertex is not the first, two vertices are not the % first, etc. These subsets are enumerated by the 0-1 vector U. repColor = find(nsS==2); % repColor holds the indices of colours % that have two points in S lenRepColor = length(repColor); for len = 0:length(repColor) % Check the combinations of choosing len colours from the % colours that have two alternative points. For the chosen % colour, the second point will be used to generate a colourful % simplex with the points of other colours. U = zeros(1,length(repColor)); % U is a 0-1 vector identifying U(1:len) = 1; % a combination while (1) % Check the transversal T under the current combination U. % In this section each combination has only one transversal % identified by T. The reason why not directly enumerate T, % but enumerate U is that we try the colourful simplices % most probable to cover the origin first. T=ones(1,NumColor); T(repColor)=T(repColor)+U; info.iter = info.iter+1; % Check the colourful simplex represented by T for cnt=1:(d+1) L(cnt) = S(cnt).list(T(cnt)); end tmp = linsolve([M(:,L); ones(1,d+1)], [zeros(d,1); 1]); if all(tmp>=(-TOLERANCE)) x = zeros(NumPts,1); x(L) = tmp; info.feasible = 1; info.time = etime(clock,initTime); return end % Increment the current combination [U,endflag] = nextComb(U,lenRepColor,len); if endflag break end end end end % If this is the first set of points, then this iteration is finished. if info.numset==1 % add S to Chk for iColor=1:(d+1) Chk(iColor).list = [Chk(iColor).list S(iColor).list]; nsChk(iColor) = nsChk(iColor) + nsS(iColor); end % end the current iteration continue end % Check the colourful simplices generated by Union(S,Chk), and with % vertices from both S and Chk. The enumeration skips the colourful % simplices with vertices from purely S or Chk, which have already been % tested. The method is to enumerate a group of subsets of % Union(S,Chk), such that all colourful simplices generated by them are % not tested; then enumerate and test colourful simplices for each % individual subset. A subset is represented by a 0-1 vector U. For % example, U=[0 1 0] represents the subset containing all the points of % colour 2 from S, and the points of other colours from Chk. repColor = find(nsS>=1); % repColor lists what colours S has for len=1:min(d,length(repColor)) % len is the number of colors from % S points are selected to be % vertices of colourful simplices U=zeros(1,length(repColor)); U(1:len)=1; while (1) % Build a temporary set TmpSet with U TmpSet = Chk; nsTmpSet = nsChk; for cnt=(U.*repColor) if cnt>0 TmpSet(cnt)=S(cnt); nsTmpSet(cnt) = nsS(cnt); end end % Test all the colourful simplices generated by TmpSet T = ones(1,NumColor); while (1) % Increment the counter info.iter = info.iter + 1; % Check the colourful simplex represented by T for cnt=1:(d+1) L(cnt) = TmpSet(cnt).list(T(cnt)); end tmp = linsolve([M(:,L); ones(1,d+1)], [zeros(d,1); 1]); if all(tmp>=(-TOLERANCE)) x = zeros(NumPts,1); x(L) = tmp; info.feasible = 1; info.time = etime(clock,initTime); return end % Increment T T = nextEnum(T,nsTmpSet); if T(1)<0 break end end % Increment the combination U for current len. [U,endflag] = nextComb(U,length(repColor),len); if (endflag==1) break end end end % add S to Chk for iColor=1:(d+1) Chk(iColor).list = [Chk(iColor).list S(iColor).list]; nsChk(iColor) = nsChk(iColor) + nsS(iColor); end end % While main loop %% function Next = nextEnum(Current, UpBnd) % Obtain the next number in the enumeration represented by the input vector % Current, the first element of Current is the least significant digit, and % the vector UpBnd holds the upper bound of all the digits. For the i-th % digit, the minimum value is 1, and the maximum is UpBnd(i). Following are % some examples: % Current UpBnd Next % 2 1 1 3 2 3 3 1 1 % 3 1 1 3 2 3 1 2 1 l = length(UpBnd); Next = Current; for i=1:l; if Current(i)1) % Increment the combination Position(i) = Position(i)+1; Position(1:(i-1))=1:(i-1); Next = zeros(1,TotalSize); Next(Position) = 1; endflag = 0; return end end if Position(ChooseSize)1); T = zeros(1,d+1); end % Find the first part of the points and insert them to S. If there are some % colours that have only one point, then they will all be inserted to S; if % no, then a point in a colour that have multiple unchecked points will be % inserted to S. if ~isempty(singularColor) % Initialize the reference point for max volume heuristic p = zeros(d,1); % Insert points to S for i=singularColor T(i) = Unchk(i).list; sel_j=Unchk(i).list; p=p+M(:,sel_j); % add the point to S S(i).list=[S(i).list sel_j]; nsS(i)=nsS(i)+1; % remove the point from Unchk Unchk(i).list=setdiff(Unchk(i).list, sel_j); nsUnchk(i)=nsUnchk(i)-1; end % Compute the reference point for max volume heuristic p = p/length(singularColor); else % Select the colour i = multipleColor(1); % Insert the first point of colour i to S sel_j = Unchk(i).list(1); T(i) = sel_j; % add the point to S S(i).list=[S(i).list sel_j]; nsS(i)=nsS(i)+1; % remove the point from Unchk Unchk(i).list=setdiff(Unchk(i).list, sel_j); nsUnchk(i)=nsUnchk(i)-1; % Compute the reference point for max volume heuristic p = M(:,sel_j); end % Find the second part of points and insert them to S with max volume % heuristic, from the colors that have multiple unchecked points. If there % is no colour in Unchk that has only one point, then the first point of % the first colour in multipleColor would had been selected, and that % colour no longer need to be search that colour. iBegin = 1 + isempty(singularColor); for i = multipleColor(iBegin:length(multipleColor)) % Because it is assume that all points are normalized vectors, 2 is an % uppder bound of the minProd, which is the dot product of two vectors minProd = 2; % Go through all points of colour i, to find a point that minimize its % dot product with the reference point p for j = Unchk(i).list Prod = dot(p,M(:,j)); if Prod =0. % % **** % * Input Arguments * % **** % Pts are the coordinates of a set of points. Each column of Pts contains % the coordinates of one point. % b is a column vector containing the coordinates of one point inside the % convex hull of points represented by Pts. % tol is a small positive number used as tolerance to avoid numerical % error such as dividing a number by a small number. % % % * Output Arguments * % % X is the solution. Each element of X contains the coefficient of % corresponding point in Pts. If the problem is solved, then exitflag > 0, % otherwise exitflag <= 0. % % *** % * Algorithm * % *** % Uses a matrix to represent the constraints Pts*X=b and sum(X)=1, then a % pivoting algorithm is applied to the matrix for finding a solution that % satisfies the constraint X>=0 besides the other two. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005 : First version. % July 2005 : Added comments. % August 2005: Fixed a bug of detecting infeasible case. % % Initialize the matrices representing constraints, and some control % numbers. n = size(Pts, 2) + 1; % Width of M. M = [b Pts; ones(1,n)]; % Represents the constraints % Pts*X=b and sum(X)=1. m = size(M, 1); % Height of M. FlashPeriod = 25; % Period of refreshing M. LoopLimit = 1000; % Allowed iterations. % Initialized: n m M FlashPeriod LoopLimit % Initialize the basis, apply it on M, and remove the redundant constraints % from M. Also obtain the matrix OriginM for refreshing M periodically. BASIS = zeros(1, m); % Allocate memory. RowFlag = zeros(1, m); % Flags indicating redundancy. for i = 1:m for j = 2:n if (abs(M(i, j)) > tol) % Add the point to the basis and flag the row. BASIS(i) = j; RowFlag(i) = 1; % Pivot on M(i,j). M(i,:)=M(i,:)/M(i,j); for row=[(1:(i-1)) ((i+1):m)] M(row,:) = M(row,:) - M(row,j)*M(i,:); end M(:,j) = zeros(1,m); M(i,j) = 1; end end if ((~RowFlag(i)) && (abs(M(i,1))>tol)) % The problem is infeasible. X = zeros((n-1), 1); exitflag = -1; return; end end tmp = find(RowFlag); % Find the necessary rows. m = length(tmp); % Number of necessary rows. M = M(tmp,:); % Keep the necessary rows. BASIS = BASIS(tmp); % Keep the necessary column % indices in basis. OriginM = M; % OriginM is for periodical % refreshment of M. % Initialized: BASIS OriginM % Changed: M m % Solution search. LoopCnt = 0; FlashCnt = 0; while (1) % Search for the next pivoting location. Algorithm scans through all % the rows in the order of least column index and find the first % row with negative value at the first column, then find the minimum % column number (except 1) on that row with negative element. The row % and column number indicates the pivoting location. If the row number % is not found, then a valid solution is reached. If row number is % found but column number is not found, then the Caratheodary problem % is infeasible. [dum, rowOrder] = sort(BASIS, 'ascend'); % Least column index order. msg = 'v'; % 'v' stands for 'valid'. for i=rowOrder if (M(i,1)<=(-tol)) msg = ''; break; % The row index is found. end end if (msg == 'v') break; % Terminate, since valid % solution is reached. end msg = 'f'; % 'f' stands for 'infeasible'. for j=2:n if (M(i,j)<=(-tol)) msg = ''; break; % The column index is found. end end if (msg == 'f') break; % Terminate, since the problem % is infeasible. end % Initialized: i j % Update BASIS according to the next pivoting location. BASIS(i) = j; % Changed: BASIS % Count the number of iterations. if (LoopCnt>LoopLimit) % Return an error if the problem is not solved in too many % iterations. error('too many iterations'); end LoopCnt = LoopCnt+1; FlashCnt = FlashCnt + 1; % Changed: LoopCnt FlashCnt % Update M if (FlashCnt ~= FlashPeriod) % Pivot on M(i,j). M(i,:)=M(i,:)/M(i,j); for row=[(1:(i-1)) ((i+1):m)] M(row,:) = M(row,:) - M(row,j)*M(i,:); end M(:,j) = zeros(n,1); M(i,j) = 1; else % Sort the basis to ascendent order before recalculating M from % OriginM. The purpose is to speed up the calculation of least % column index order of row numbers, since it should be found % faster if there is less disorder in BASIS. BASIS = sort(BASIS, 'ascend'); % Recalculate M from OriginM. M(:,BASIS) = eye(size(M,1)); NonB = setdiff(1:m, BASIS); M(:, NonB) = inv(OriginM(:,BASIS)) * OriginM(:,NonB); % Reset FlashCnt. FlashCnt = 0; end end % Prepare the outputs. if (msg == 'v') % Valid solution is found. exitflag = 1; X = zeros((n-1), 1); X(BASIS-1) = inv(OriginM(:,BASIS)) * OriginM(:,1); elseif (msg == 'f') % The problem is infeasible. exitflag = -1; X = zeros((n-1), 1); end returncfp/private/accdot.m000070001206620011610000000013031060756425000173470ustar00tstephenmast_faculty00004050013607function s = accdot(t,u) % Accurate dot product calculation reducing numerical error. % Input : u and v are vectors of the same dimension. % Output : s is the dot product of u and v. % Description: % let x=[x1 x2 x3 ...] and y=[y1 y2 y3 ...], such that |x1*y1| is much % larger than other |xi*yi| but not too much larger than % |x2*y2+x3*y3+...|. A simple implementation of dot product may return % only dot(x,y)=x1*y1. This routine can reduce the error caused by these % kind of cases. % The draw back is that it increase the complexity from O(n) to % O(nlgn). v = t.*u; posv = sort(v(v>=0),'ascend'); negv = sort(v(v<0) ,'descend'); s = sum(posv)+sum(negv); returncfp/private/accsum.m000070001206620011610000000010501060756417200173670ustar00tstephenmast_faculty00004050013607function s = accsum(v) % Accurate summation reducing numerical error. % Input : v is a vector. % Output : s is the sum of elements in v. % Description: % A critical case numerical error is sum([1 1e-10 1e-10 ... 1e-10]) may % return only 1, discarding all elements after the first. This routine % can reduce the error caused by these kind of cases. % The draw back is that it increase the complexity from O(n) to % O(nlgn). posv = sort(v(v>=0),'ascend'); negv = sort(v(v<0) ,'descend'); s = sum(posv)+sum(negv); returncfp/private/accnorm.m000070001206620011610000000010701060756422000175320ustar00tstephenmast_faculty00004050013607function l = accnorm(v) % Accurate 2-norm calculation reducing numerical error. % Input : v is a vector. % Output : l is the 2-norm of v. % Description: % For example, let x=[x1 x2 x3 ...] and x1 is much larger than other % |xi| but not too much larger than sum of other |xi|. A simple % implementation of 2-norm may let norm(x) return |x1|. This routine % can reduce the error caused by these kind of cases. % The draw back is that it increase the complexity from O(n) to % O(nlgn). v = sort(abs(v),'ascend'); l = norm(v,2); returncfp/private/rand_real.m000070001206620011610000000020141027232213400200300ustar00tstephenmast_faculty00004050013607function r = rand_real(m, n, rg) % % Generate real number/numbers between rg(1) and rg(2), inclusively. % % % * Syntax * % % r = rand_real(m,n,rg) % % **** % * Input Arguments * % **** % m and n are the height and width of the output matrix. % rg is a two element vector specifying the range of the random real % number/numbers to be generated, inclusively. rg(1)<=rg(2) must be % satisfied. % % % * Output Arguments * % % r is the m by n matrix of random real numbers between rg(1) and rg(2). % % See also: RAND_INT %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % r = rand(m,n); r = rg(1) + (rg(2)-rg(1)) * r; return; rand_real(m, n, rg) % % Generate real number/numbers between rg(1) and rg(2), inclusively. % % % * Syntax * % % r = rand_real(m,n,rg) % % **** % * Input Arguments * % **** % m and n are the height and width of the output matrix. % rg is a two element vector specifying the range of the random real % number/numbers to be generated, inclusively. rg(1)<=rg(2) must be % satisfied. % % % * Output Arguments *cfp/private/regular_simplex.m000070001206620011610000000034601043563266000213220ustar00tstephenmast_faculty00004050013607function RegularPts = regular_simplex(d); % % Generate the vertices of a regular simplex in hyperspace. % % % * Syntax * % % RegularPts = regular_simplex(d) % % % * Description * % % RegularPts=regular_simplex(d) generates the vertices of a regular simplex % in d dimensional Euclidean space. % % *** % * Input Argument * % *** % d is the number of dimensions of the Euclidean space. % RegularPts is a d by (d+1) matrix. Each of its column stores the % coordinates of one vertex. The distances between any pair of vertices are % the same. % % *** % * Algorithm * % *** % The algorithm of this routine uses the fact that, if the edge length of a % d-dimensional regular simplex is L, then its height is L*sqrt((d+1)/2d). % This fact can be proved by induction. Conceptually the the algorithm % obtains an additional vertex by adding an additional dimension to update % a lower dimensional regular simplex vertex set to a higher dimensional % one. This routine implements it with a faster way without accumulation of % numerical error. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % July 2005: First version. % August 2005: Added comments. % May 2006: Added dimension error check. if (d<=0) error('d must be at least 1'); end RegularPts = zeros(d, d+1); EdgeLength = 2; RegularPts(1,1) = -1; RegularPts(1,2) = 1; for i=2:d H = sqrt((i+1)/(2*i)) * EdgeLength; RegularPts(i, i+1) = H; RegularPts(i, i+2:(d+1)) = H/(i+1); end returncfp/private/rand_int.m000070001206620011610000000020421027232541400177040ustar00tstephenmast_faculty00004050013607function r = rand_int(m,n,rg); % % Generate integer/integers between rg(1) and rg(2), inclusively. % % % * Syntax * % % r = rand_int(m,n,rg) % % **** % * Input Arguments * % **** % m and n are the height and width of the output matrix. % rg is a two element vector specifying the range of the random % integer/integers to be generated, inclusively. rg(1)<=rg(2) must be % satisfied. % % % * Output Arguments * % % r is the m by n matrix of random integers between rg(1) and rg(2). % % See also: RAND_REAL %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % May 2005: First version. % July 2005: Added comments. % r = rg(1)*ones(m,n); diff = rg(2)-rg(1) + 0.99999; r = r + floor(rand(m,n)*diff); returncfp/test_infeasible.m000070001206620011610000000044241061556456200176140ustar00tstephenmast_faculty00004050013607function test_infeasible(ds, name_gen) for d = ds time_summary = []; feas_summary = []; record.sdprelax = {}; NumCase = 1000; fprintf(['d = ' num2str(d) ' ']); NumBack=0; for i = 1:NumCase for c=1:NumBack fprintf('\b'); end NumBack = fprintf('i = %d', i); filname=['infeasi_cases/infeasi' num2str(d) 'd' num2str(i) '.mat']; if (exist(filname,'file')==2) load(filname); else [Pts,ColorPartition,b]=feval(name_gen,d); save(filname, 'Pts', 'b', 'ColorPartition'); end [x,info]=cfp_solver_sdprelax(Pts,b,ColorPartition); record.sdprelax{i}=info; end feas_summary.sdprelax = get_feas_summary(record, 'sdprelax'); time_summary.sdprelax = get_time_summary(record, 'sdprelax'); save(['results/' name_gen num2str(d) 'd.mat'], ... 'record', 'time_summary', 'feas_summary'); fprintf('\n'); end end function summary = get_feas_summary(record, name_solver) infoarray = getfield(record, name_solver); summary.totalcases = length(infoarray); summary.feasible = 0; summary.infeasible = 0; summary.unknown = 0; summary.relaxfeasible = 0; for i = 1:(summary.totalcases) info = infoarray{i}; if (info.feasible==0) summary.infeasible = summary.infeasible + 1; elseif (info.feasible==-1) summary.unknown = summary.unknown + 1; elseif (info.feasible==1) summary.feasible = summary.feasible + 1; end if (info.relaxfeasi==1) summary.relaxfeasible = summary.relaxfeasible + 1; end end end function summary = get_time_summary(record, name_solver) infoarray = getfield(record, name_solver); summary.totalcases = length(infoarray); summary.total = 0; summary.validcases = 0; summary.max = 0; summary.min = Inf; for i = 1:(summary.totalcases) info = infoarray{i}; if (info.feasible == 0) summary.validcases = summary.validcases + 1; summary.total = summary.total + info.time; if (info.time>summary.max) summary.max = info.time; end if info.time=0 % % **** % * Input Arguments * % **** % Pts is a matrix storing the coordinates of points. Each column of Pts % stores the coordinate of one point. The number of rows is d, which is the % number of dimensions of the Euclidean space. The points in each color of % Pts must contain b in their convex hulls. % b is a column vector representing a point in the d-Euclidean space. % This argument is optional. In default it will be the origin. % ColorPartition is a row vector of length (d+1). Each element is an % integer, specifying the number of points in a color. For example [3 4 3] % tells that the first 3 points in Pts are in the first color, the % following 4 points are in the second color, and so on. This argument is % optional. In default it assumes (d+1) points in each of the (d+1) colors. % If the problem is not in the default case, user must provide this % argument. % options is a struct that holds the addition parameters. This struct is % for the purpose of extensibility. The field options.initT indicates the % initial colourful simplex of the algorithm. For example, % options.initT=[1 5 7] corresponds to the colourful simplices generated by % the points in the first, the fifth, and the seventh columns of Pts. % % % * Output Arguments * % % x is the solution of the problem. % info is a struct that tells the exiting state, following are its members. % info.iter: the number of iterations to solve the problem. % info.time: the number of seconds spent by the solver. % info.feasible: 1 if feasible, -1 if exceeding maximum loop limit, -2 if % numerical error. % % *** % * Algorithm * % *** % This algorithm is a variance of algorithm 1 in the publication "Colourful % Linear Programming and its Relatives" by IMRE BARANY and SHMUEL ONN % (Math. Oper. Res. 22, 550-557, 1997). % The algorithm updates a colorful set of points T and a point xk on the % surface of conv(T) at each iteration. The algorithm finds a linear % combination transforming T into xk, such that some points in T has zero % as coefficients; then replaces all of the zero-coefficient points in the % following way: % Step 1: p = xk; % Step 2: for all zero-coefficient points in T % i) replace it with a point of the same color minimizing the % inner product with p, say t. % ii) let p become the projection of the origin on the line % segment between t and p. % After replacing the points, xk is updated to the point on the surface of % conv(T), such that its norm is minimized. % % There are some notes for this algorithm: % 1) The accumlation of numerical error on xk cannot be avoided, because % the update of xk depends on its previous value. % 2) The complexity of finding the minimum-norm-point of a simplex depends % on the complexity of convex quadratic programing subroutine. % %%%%%%%%%%%%%%%%%%%%%%%%% Internal Comments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Written by Sui Huang, Advanced Optimization Lab, McMaster University, % Hamilton, Ontario, Canada. % % **** % * Modification History * % **** % Dec 2005: First rough version for quick test. % Named clp_solver_gravity(). % Feb 2006: Refined version. % * Handle degenerate case % * More numerically accurate way instead of simple using sum(), % norm() or dot() functions in some critical part. % May 2006: Fix a bug in generating data structure ColorMap. % April 2007: Renamed to cfp_solver_multiupdate(). % July 2007: Updated comments. % % * % * Dependencies * % * % Following functions are not in basic MATLAB library, and this routine % depends on them: % linprog() optimization toolbox % quadprog() optimization toolbox % % **** % * Some Local Variables * % **** % T : A row vector containing the column indices of Pts. It indicates a % colorful set of points. This set is updated in each iteration until % it contains b in its convex hull. % xk : A point in the colorful convex hull, whose distance to b is reduced % after each iteration. % p : A vector presenting a point belong to the convex hull of the % colorful set, notated conv(T). % a : A scalar between 0 and 1 to shrink a vector. % % Initialize the time counter. initTime = clock; % Initialized: initTime % Assign some global control numbers and apply the default arguments. [d NumPts]=size(Pts); % Space dimension and number % of points. NumColor = d+1; % Number of colors. TOLERANCE = 10^(-12); % Allowed numerical error. LoopLimit = 1000000; % Allowed iterations. if (nargin==3)||((nargin==4)&&(~isfield(options,'initT'))) options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<3) ColorPartition = (d+1)*ones(1,NumColor); % Default is (d+1) points for % each color. options.initT = zeros(1,NumColor); base = 1; for i=1:NumColor options.initT(i) = base; base = base + ColorPartition(i); end end if (nargin<2) b=zeros(d,1); % Default is origin. end % Initialized: NumPts NumColor d TOLERANCE LoopLimit ColorPartition b % Preprocess the inputs: % _ % | b is translated to the origin % | The coordinates after translation are kept in OriginPts % |_ The coordinates after translation and normalization are kept in Pts OriginPts = Pts; for cnt = 1:NumPts OriginPts(:,cnt) = OriginPts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt) - b; Pts(:,cnt) = Pts(:,cnt)/accnorm(Pts(:,cnt)); end b = zeros(d,1); % Initialized: OriginPts % Changed: Pts b % construct ColorMap. ColorMap is an alternative data structure to present % which point is in which color to ease the programming. ColorMap(NumColor).list = []; base = 0; for cnt=1:NumColor ColorMap(cnt).list = (base+1) : (base+ColorPartition(cnt)); base = base + ColorPartition(cnt); end % Keep: ColorMap % Initialize some variables for iterations. T = options.initT; color_out_list = 2:(d+1); xk = Pts(:,T(1)); % Initialize xk to the first point in T. LoopCnt = 0; % Counter of iterations. % Initialized: T xk LoopCnt color_out_list % Test if the initial colorful set is feasible by trying to express b as a % convex combination of T. Gaussian elimination is used by the function % linsolve() to find the coefficients of mapping T to b. [tmp, recp_cond] = linsolve([OriginPts(:,T); ones(1, NumColor)], [b;1]); if ((recp_cond < TOLERANCE) && any(tmp < -TOLERANCE)) % When the simplex is degenerate, use linear programming to check if b % is in the simplex. [tmp,LPfval,FeasibleFlag]... =linprog(sparse(zeros(d+1,1)),[],[],... [OriginPts(:,T); ones(1, NumColor)],[b;1],... zeros(d+1,1),[],[],optimset('Display','off','LargeScale','off')); else FeasibleFlag = all(tmp >= -TOLERANCE); end if (FeasibleFlag > 0) % feasible solution is found. info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = 1; x = zeros(NumPts, 1); x(T) = tmp; return; end % The iterations updating T until b is in conv(T). while any(abs(xk)>TOLERANCE) % Count the number of iterations. LoopCnt = LoopCnt + 1; if (LoopCnt>LoopLimit)&&(mod(LoopCnt,LoopLimit)==1) % Give a warning if the problem is not solved in too many % iterations. sbuf=sprintf('Warning: over loop limit in routine %s\n', ... 'cfp_solver_multiupdate'); disp(sbuf); sbuf=sprintf('Loop limit: %f Current loop count: %f\n', ... LoopLimit, LoopCnt'); disp(sbuf); if (floor(LoopCnt/LoopLimit)>10) x = zeros(NumPts, 1); info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -1; return end end % Changed: LoopCnt % Replace all zero-coefficient points. p = xk; % Initialize the projection % of origin. for color_out_index = color_out_list minProd = TOLERANCE; % Initialize the minimum % inner product. for j=ColorMap(color_out_index).list % Search for the point of % minimum inner product p. Prod = accdot(Pts(:,j), p); if (Prod < minProd) j_in = j; minProd = Prod; end end T(color_out_index) = j_in; % Replace one point. t = Pts(:,j_in); % t is the new point. p = (accdot(t-p,t)*p + accdot(p-t,p)*t) ... % p is the projection / accdot(t-p,t-p); % origin on a line % segment. end % Changed: T % use quadratic optimization routine to obtain the minimum-norm-point % in conv(T). Following is the formulation of the problem in 2D, which % can be generalized to high dimensional space. % Let the vertices of simplex be (x11,x12,x13), (x21,x22,x23), % (x31,x32,x33). Let c1,c2,c3>=0 and c1+c2+c3=1 be the coefficients of % the vertices to generate a point in simplex. The square of 2-norm of % a point in simplex is (the objective function to be minimized): % c1*c1*(x11*x11+x12*x12+x13*x12) % + ... % + ci*cj*(xi1*xj1+xi2*xj2+xi3*xj3) % + ... % + c3*c3*(x31*x31+x32*x32+x33*x33) % The variables are c1,c2,c3. The constraints are c1,c2,c3>=0 and % c1+c2+c3=1. % Get the matrix for objective function. H = zeros(NumColor,NumColor); for i=1:NumColor for j=i:NumColor % Use a more numerically accurate way to calculate dot product, % since numerical stability is important. H(i,j) = accsum(Pts(:,T(i)).*Pts(:,T(j))); H(j,i) = H(i,j); end end % Get the optimal coefficients. [c,dummy,FeasibleFlag] ... = quadprog(H,[],[],[],ones(1,NumColor),... 1,zeros(NumColor,1),[],... ones(1,NumColor)/NumColor,... optimset('Display','off','LargeScale','off')); if (FeasibleFlag<=0) info.iter = LoopCnt; info.time = etime(clock,initTime); info.feasible = -2; x = zeros(NumPts,1); return end % Get the minimum-norm-point in the simplex. xk = zeros(d,1); for i = 1:d xk(i) = accdot(Pts(i,T), c'); end % Get the list of colors that the points can be replaced. color_out_list = find(abs(transpose(c))