Esempio n. 1
0
    def redraw_fn(f, axes):
        img = imread(img_files[f])

        x1, y1, w1, h1 = track_gt[f]
        x2, y2, w2, h2 = tuple(sample[f].tolist())
        x1 = int(x1 - w1 / 2)
        x2 = int(x2 - w2 / 2)
        y1 = int(y1 - h1 / 2)
        y2 = int(y2 - h2 / 2)
        if not redraw_fn.initialized:
            im = axes.imshow(img, animated=True)
            bb1 = Rectangle(
                (x1, y1),
                w1,
                h1,
                fill=False,  # remove background
                edgecolor="red",
                gid='gt')
            bb2 = Rectangle(
                (x2, y2),
                w2,
                h2,
                fill=False,  # remove background
                edgecolor="blue",
                gid='sample')

            t1 = axes.text(0,
                           0,
                           '[{} {}]'.format(x1, y1),
                           bbox=dict(facecolor='red', alpha=0.5))
            t2 = axes.text(300,
                           0,
                           '[{} {}]'.format(x2, y2),
                           bbox=dict(facecolor='blue', alpha=0.5))

            axes.add_patch(bb1)
            axes.add_patch(bb2)
            redraw_fn.im = im
            redraw_fn.bb1 = bb1
            redraw_fn.bb2 = bb2
            redraw_fn.t1 = t1
            redraw_fn.t2 = t2
            redraw_fn.initialized = True
        else:
            redraw_fn.im.set_array(img)
            redraw_fn.bb1.set_xy((x1, y1))
            redraw_fn.bb1.set_width(w1)
            redraw_fn.bb1.set_height(h1)
            redraw_fn.t1.set_text('[{} {}]'.format(x1, y1))
            redraw_fn.bb2.set_xy((x2, y2))
            redraw_fn.bb2.set_width(w2)
            redraw_fn.bb2.set_height(h2)
            redraw_fn.t2.set_text('[{} {}]'.format(x2, y2))
Esempio n. 2
0
        def redraw_fn(f, axes):
            img = imread(img_files[f])
            x, y, w, h = tuple(bbox[f, :])
            w = w - x
            h = h - y
            frame = frames[f]
            vis = viss[f]
            if not redraw_fn.initialized:
                im = axes.imshow(img, animated=True)
                bb = Rectangle(
                    (x, y),
                    w,
                    h,
                    fill=False,  # remove background
                    edgecolor="red")

                t1 = axes.text(0,
                               0,
                               '[f:{} vis:{:1.2f}]'.format(frame, vis),
                               bbox=dict(facecolor='red', alpha=0.5))

                axes.add_patch(bb)
                redraw_fn.im = im
                redraw_fn.bb1 = bb
                redraw_fn.t1 = t1
                redraw_fn.initialized = True
            else:
                redraw_fn.im.set_array(img)
                redraw_fn.bb1.set_xy((x, y))
                redraw_fn.bb1.set_width(w)
                redraw_fn.bb1.set_height(h)
                redraw_fn.t1.set_text('[f:{} vis:{:1.2f}]'.format(frame, vis))
def create_bbox(bbox, color):
    return Rectangle(
        (bbox[0], bbox[1]),
        bbox[2],
        bbox[3],
        fill=False,  # remove background\n",
        edgecolor=color)
Esempio n. 4
0
def redraw_fn(f, ax):
    img = imgs[f]
    box = boxs[f]

    x, y, w, h = box
    if not redraw_fn.initialized:
        redraw_fn.img_handle = ax.imshow(img)
        box_artist = Rectangle((x, y), w, h,
                               fill=False,  # remove background
                               lw=2,
                               edgecolor="red")
        ax.add_patch(box_artist)
        redraw_fn.box_handle = box_artist
        redraw_fn.last_time = time.time()
        redraw_fn.text_handle = ax.text(0., 1 - 0.05,
                                        'Resolution {}x{}, FPS: {:.2f}'.format(img.shape[1], img.shape[0], 0),
                                        transform=ax.transAxes,
                                        color='yellow', size=12)
        redraw_fn.initialized = True
    else:
        redraw_fn.img_handle.set_array(img)
        redraw_fn.box_handle.set_xy((x, y))
        redraw_fn.box_handle.set_width(w)
        redraw_fn.box_handle.set_height(h)
        current_time = time.time()
        redraw_fn.text_handle.set_text('Resolution {}x{}, FPS: {:.2f}'.format(img.shape[1], img.shape[0],
                                                                              1 / (current_time - redraw_fn.last_time)))
        redraw_fn.last_time = current_time
Esempio n. 5
0
def make_placement_plot(nodes, pl, scl, dest):
    # Read bookshelf files
    parse_bookshelf_scl(scl)

    node_dict = dict()
    parse_bookshelf_nodes(nodes, node_dict)
    parse_bookshelf_pl(pl, node_dict)

    fig = plt.figure()  # Figure
    ax = fig.add_subplot(1, 1, 1)  # AxesSubplot

    patches = set()

    for k, v in node_dict.items():
        llx, lly = v.llx, v.lly
        w, h = v.width, v.height
        patches.add(Rectangle((llx, lly), w, h))

    print("Adding collection.")
    ax.add_collection(PatchCollection(patches, alpha=0.4))
    print("Done.")
    fig.show()
    ax.set_xlim([0, 1000])
    ax.set_ylim([0, 1000])
    fig.savefig('test.png')
Esempio n. 6
0
 def plotobs(self, ax, scale=1):
     '''plot all obstacles'''
     obstacles = scale * np.array(self.obstacles)
     if self.dim == 2:
         for box in obstacles:
             l = box[2] - box[0]
             w = box[3] - box[1]
             box_plt = Rectangle((box[0], box[1]),
                                 l,
                                 w,
                                 color='k',
                                 zorder=1)
             ax.add_patch(box_plt)
     elif self.dim == 3:
         for box in obstacles:
             X, Y, Z = cuboid_data(box)
             ax.plot_surface(X,
                             Y,
                             Z,
                             rstride=1,
                             cstride=1,
                             color=(0.1, 0.15, 0.3, 0.2),
                             zorder=1)
     else:
         print('can not plot for given dimensions')
Esempio n. 7
0
def square(r, c, size=1, facecolor='k', edgecolor='0.7', linewidth=None):
    from matplotlib.pyplot import Rectangle
    # r and c must be swapped: row -> y axis, col -> x axis
    return Rectangle((c, r),
                     size,
                     size,
                     facecolor=facecolor,
                     edgecolor=edgecolor,
                     linewidth=linewidth)
Esempio n. 8
0
def bound_words(fig, bounds, hold=True):
    ax = fig.gca()

    for bound in bounds:
        _, x, y, width, height = bound
        ax.add_artist(
            Rectangle((x, y), width, height, fill=False, edgecolor='k'))

    if hold:
        show()
Esempio n. 9
0
    def redraw_fn(idx, axes):
        idx += 1
        img = imread(img_files[idx])
        x_gt, y_gt, w_gt, h_gt = vot_rect(bboxes_gt[idx])
        b_seq = bbox_seq[idx - 1].split(',')
        b_seq = map(float, b_seq)
        overlap = float(overlap_seq[idx - 1])
        objectness = float(objectness_seq[idx - 1])

        if not redraw_fn.initialized:
            # import pdb; pdb.set_trace()
            axes, axes_p = axes
            redraw_fn.im_p = axes_p.imshow(imread(plot_png))
            redraw_fn.im = axes.imshow(img)
            redraw_fn.bb1 = Rectangle((x_gt, y_gt), w_gt, h_gt, fill=False, edgecolor='red', linewidth=5)
            redraw_fn.bb2 = Rectangle((b_seq[0], b_seq[1]), b_seq[2], b_seq[3], fill=False, edgecolor='blue', linewidth=5)
            axes.add_patch(redraw_fn.bb2)
            axes.add_patch(redraw_fn.bb1)
            redraw_fn.text1 = axes.text(0.03, 0.97, '{}: {}'.format(seq, idx+1), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'yellow', 'alpha':0.7}, transform=axes.transAxes)
            redraw_fn.text2 = axes.text(0.03, 0.92, 'olap: {:.2f}'.format(overlap), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'blue', 'alpha':0.7}, transform=axes.transAxes)
            redraw_fn.text3 = axes.text(0.03, 0.87, 'obj: {:.2f}'.format(objectness), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'red', 'alpha':0.7}, transform=axes.transAxes)
            redraw_fn.text1_p = axes_p.text(0.03, 0.97, '{}: {}'.format(seq, idx+1), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'yellow', 'alpha':0.7}, transform=axes_p.transAxes)
            redraw_fn.text2_p = axes_p.text(0.03, 0.92, 'olap: {:.2f}'.format(overlap), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'blue', 'alpha':0.7}, transform=axes_p.transAxes)
            redraw_fn.text3_p = axes_p.text(0.03, 0.87, 'obj: {:.2f}'.format(objectness), fontdict={'size':10,},
                    ha='left', va='top', bbox={'facecolor':'red', 'alpha':0.7}, transform=axes_p.transAxes)
            redraw_fn.initialized = True
        else:
            # import pdb; pdb.set_trace()
            redraw_fn.im.set_array(img)
            # redraw_fn.im_p.set_array(imread(plot_png))
            set_bbox(redraw_fn.bb1, vot_rect(bboxes_gt[idx]))
            set_bbox(redraw_fn.bb2, b_seq)
            redraw_fn.text1.set_text('{}: {}'.format(seq, idx+1))
            redraw_fn.text2.set_text('olap: {:.2f}'.format(overlap))
            redraw_fn.text3.set_text('obj: {:.2f}'.format(objectness))
            redraw_fn.text1_p.set_text('{}: {}'.format(seq, idx+1))
            redraw_fn.text2_p.set_text('olap: {:.2f}'.format(overlap))
            redraw_fn.text3_p.set_text('obj: {:.2f}'.format(objectness))
Esempio n. 10
0
def make_plot(language, xs, ys):

    settings = dict(xmin=0,
                    xmax=5,
                    ymin=0,
                    ymax=0.6,
                    magmin=0.05,
                    magmax=0.5,
                    coercivitymin=1.5,
                    coercivitymax=4)

    colour_main = "#ffffff"
    colour_highlight = "#ffffff"
    pyplot.gcf().set_size_inches(80 / 25.4, 58 / 25.4)
    pyplot.xlabel(r"$B_{\mathrm{cr}} / B_\mathrm{c}$")
    pyplot.ylabel(r"$M_{\mathrm{rs}} / M_{\mathrm{s}}$")
    pyplot.xlim(settings["xmin"], settings["xmax"])
    pyplot.ylim(settings["ymin"], settings["ymax"])
    pyplot.gca().add_patch(
        Rectangle((0, 0), settings["xmax"], settings["ymax"], fc=colour_main))
    pyplot.gca().add_patch(
        Rectangle((settings["coercivitymin"], settings["magmin"]),
                  settings["coercivitymax"] - settings["coercivitymin"],
                  settings["magmax"] - settings["magmin"],
                  fc=colour_highlight))
    pyplot.annotate("SD", (0.05, 0.53))
    pyplot.annotate("PSD", (1.60, 0.42))
    pyplot.annotate({"it": "PD", "en": "MD"}[language], (4.1, 0.01))
    pyplot.hlines([settings["magmin"], settings["magmax"]], 0., 5.)
    pyplot.vlines([settings["coercivitymin"], settings["coercivitymax"]], 0.0,
                  0.6)
    pyplot.subplots_adjust(left=0.15, bottom=0.18, right=0.97, top=0.96)
    pyplot.plot(xs,
                ys,
                "o",
                color="none",
                mew=0.6,
                ms=4.0,
                mec="black",
                mfc="none",
                alpha=0.6)
    pyplot.savefig(os.path.join("..", "script-output", "fig-day-plot.pdf"),
                   transparent=True)
Esempio n. 11
0
def draw_mesh_boundary(mesh: Mesh, ax):
    width = mesh.x_range[1] - mesh.x_range[0]
    height = mesh.y_range[1] - mesh.y_range[0]
    r = Rectangle((-width / 2, -height / 2),
                  width,
                  height,
                  fill=False,
                  linewidth=0.5,
                  edgecolor='black',
                  linestyle='--',
                  zorder=20)
    ax.add_artist(r)
Esempio n. 12
0
def generate_plot(circuit):
    x_coords = [c.x for c in circuit.terminals]
    y_coords = [c.y for c in circuit.terminals]
    x_min, y_min = min(x_coords), min(y_coords)
    x_max, y_max = max(x_coords), max(y_coords)

    #---------------------------------------
    # Make placement plot
    #---------------------------------------
    from matplotlib.pyplot import Rectangle
    from matplotlib.collections import PatchCollection

    fig = plt.figure()
    fig.set_size_inches(10, 10)
    ax = fig.add_subplot(1, 1, 1)

    # Plot the placement
    patches = set()

    for comb in circuit.combs:
        patches.add(Rectangle((comb.x, comb.y), comb.w, comb.h))
    ax.add_collection(
        PatchCollection(patches,
                        facecolor='#147DFF',
                        edgecolor='dimgrey',
                        lw=0.25))

    patches = set()
    for latch in circuit.latches:
        patches.add(Rectangle((latch.x, latch.y), latch.w, latch.h))
    ax.add_collection(
        PatchCollection(patches,
                        facecolor='#969696',
                        edgecolor='dimgrey',
                        lw=0.25))

    #    ax.set_xlim([0, x_max])
    #    ax.set_ylim([0, y_max])
    ax.autoscale()
    fig.savefig('foo2.png', dpi=200)
Esempio n. 13
0
def draw_cell_boundary(ax,
                       width,
                       height,
                       x_offset=0,
                       y_offset=0,
                       color=(0.8, 0.8, 0.8)):
    r = Rectangle((-width / 2 + x_offset, -height / 2 + y_offset),
                  width,
                  height,
                  fill=False,
                  linewidth=1,
                  edgecolor=color,
                  linestyle='--')
    ax.plot(x_offset, y_offset, 'b+', color=color)
    ax.add_artist(r)
    return r
Esempio n. 14
0
def extended_hinton(ax,
                    V,
                    C,
                    vmax=None,
                    cmin=None,
                    cmax=None,
                    cmap=None,
                    matrix_style=False,
                    alpha=1,
                    enforce_box=False):
    if cmap is None:
        cmap = cm.jet

    if vmax is None: vmax = np.amax(np.abs(V))
    if cmax is None: cmax = np.amax(C)
    if cmin is None: cmin = np.amin(C)

    cnorm = Normalize(vmin=cmin, vmax=cmax, clip=True)
    cmapable = ScalarMappable(norm=cnorm, cmap=cmap)

    if matrix_style:
        V, C = V.T, C.T

    ax.patch.set_facecolor([0, 0, 0, 0])

    for (x, y), w in np.ndenumerate(V):
        s = C[x, y]
        color = cmap(cnorm(s))  # cmap(s / cmax)
        size = np.abs(w / vmax)
        rect = Rectangle([x - size / 2, y - size / 2],
                         size,
                         size,
                         facecolor=color,
                         edgecolor=color,
                         alpha=alpha)
        ret = ax.add_patch(rect)

    if enforce_box:
        ax.axis('tight')
        try:
            ax.set_aspect('equal', 'box')
        except:
            pass
    #ax.autoscale_view()
    #ax.invert_yaxis()
    return cnorm
Esempio n. 15
0
    def drawPlot(self):
        ion()
        self.fig = plt.figure()
        # draw cart
        self.axes = self.fig.add_subplot(111, aspect='equal')
        self.box = Rectangle(xy=(self.cart_location - self.cartwidth / 2.0, -self.cartheight), 
                             width=self.cartwidth, height=self.cartheight)
        self.axes.add_artist(self.box)
        self.box.set_clip_box(self.axes.bbox)

        # draw pole
        self.pole = Line2D([self.cart_location, self.cart_location + np.sin(self.pole_angle)], 
                           [0, np.cos(self.pole_angle)], linewidth=3, color='black')
        self.axes.add_artist(self.pole)
        self.pole.set_clip_box(self.axes.bbox)

        # set axes limits
        self.axes.set_xlim(-10, 10)
        self.axes.set_ylim(-0.5, 2)
Esempio n. 16
0
def render_batch_sample_predictions(positives,
                                    batch_sample,
                                    color=("g", "b", "purple")):
    images = batch_sample.to("cpu").detach(
    ) if batch_sample.device.type == "cuda" else batch_sample.detach()
    # config artist assign
    n_row, n_col, figsize = [2, 4,
                             (15,
                              7.5)] if len(images) == 8 else [2, 2, (8, 8)]
    fig, axis = figure_preproduction(n_row, n_col, figsize)
    for i, (mods, positive) in enumerate(zip(images, positives)):
        ax = axis[divmod(i, n_col)]
        ax.imshow(mods[1], cmap="gray")
        for x, y, w, h, lbl in positive:
            ax.add_patch(
                Rectangle((x - w / 2, y - h / 2),
                          w,
                          h,
                          fill=False,
                          color=color[int(lbl)]))
    plt.show()
Esempio n. 17
0
def make_color_legend_rects(colors, labels=None):
    """ 
    Make list of rectangles and labels for making legends.

    Parameters
    ----------
    colors : pandas.Series or list
        Pandas series whose values are colors and index is labels.
        Alternatively, you can provide a list with colors and provide the labels
        as a list.

    labels : list
        If colors is a list, this should be the list of corresponding labels.

    Returns
    -------
    out : pd.Series
        Pandas series whose values are matplotlib rectangles and whose index are
        the legend labels for those rectangles. You can add each of these
        rectangles to your axis using ax.add_patch(r) for r in out then create a
        legend whose labels are out.values and whose labels are
        legend_rects.index:
            for r in legend_rects:
                ax.add_patch(r)
            lgd = ax.legend(legend_rects.values, labels=legend_rects.index)

    """
    from matplotlib.pyplot import Rectangle
    if labels:
        d = dict(zip(labels, colors))
        se = pd.Series(d)
    else:
        se = colors
    rects = []
    for i in se.index:
        r = Rectangle((0, 0), 0, 0, fc=se[i])
        rects.append(r)
    out = pd.Series(rects, index=se.index)
    return out
Esempio n. 18
0
    def redraw_fn(idx, axes):
        idx += 1
        img = imread(img_files[idx])
        if not redraw_fn.initialized:
            redraw_fn.im = axes.imshow(img)

            if args.r is not None:
                x, y, w, h = bbox_seq_dict[args.r][idx]
                redraw_fn.bb1 = Rectangle((x, y),
                                          w,
                                          h,
                                          fill=False,
                                          edgecolor='red',
                                          alpha=0.7,
                                          linewidth=3)
                axes.add_patch(redraw_fn.bb1)
            if args.g is not None:
                x, y, w, h = bbox_seq_dict[args.g][idx]
                redraw_fn.bb2 = Rectangle((x, y),
                                          w,
                                          h,
                                          fill=False,
                                          edgecolor='green',
                                          alpha=0.7,
                                          linewidth=3)
                axes.add_patch(redraw_fn.bb2)
            if args.b is not None:
                x, y, w, h = bbox_seq_dict[args.b][idx]
                redraw_fn.bb3 = Rectangle((x, y),
                                          w,
                                          h,
                                          fill=False,
                                          edgecolor='blue',
                                          alpha=0.7,
                                          linewidth=3)
                axes.add_patch(redraw_fn.bb3)
            if args.y is not None:
                x, y, w, h = bbox_seq_dict[args.y][idx]
                redraw_fn.bb4 = Rectangle((x, y),
                                          w,
                                          h,
                                          fill=False,
                                          edgecolor='yellow',
                                          alpha=0.7,
                                          linewidth=3)
                axes.add_patch(redraw_fn.bb4)

            redraw_fn.text1 = axes.text(0.03,
                                        0.97,
                                        '{}: {}'.format(seq, idx + 1),
                                        fontdict={
                                            'size': 10,
                                        },
                                        ha='left',
                                        va='top',
                                        bbox={
                                            'facecolor': 'yellow',
                                            'alpha': 0.7
                                        },
                                        transform=axes.transAxes)
            redraw_fn.initialized = True
        else:
            redraw_fn.im.set_array(img)
            if args.r is not None:
                set_bbox(redraw_fn.bb1, bbox_seq_dict[args.r][idx])
            if args.g is not None:
                set_bbox(redraw_fn.bb2, bbox_seq_dict[args.g][idx])
            if args.b is not None:
                set_bbox(redraw_fn.bb3, bbox_seq_dict[args.b][idx])
            if args.y is not None:
                set_bbox(redraw_fn.bb4, bbox_seq_dict[args.y][idx])
            redraw_fn.text1.set_text('{}: {}'.format(seq, idx + 1))
Esempio n. 19
0
def show_locomotion(motor_diameter, wheel_diameter, motor_shift, pcb_thick,
                    module, pinion_z, gear_z):
    pinion_reference_diameter = module * pinion_z
    gear_reference_diameter = module * gear_z
    gear_external_diameter = module * (gear_z + 2)

    ax = plt.gca()
    ax.cla()

    # Motor and pinion
    motor_height = wheel_diameter / 2. + motor_shift
    motor = Circle(
        (0, motor_height),
        radius=motor_diameter / 2.,
        color='black',
        linewidth=0,
    )
    pinion = Circle(
        (0, motor_height),
        radius=pinion_reference_diameter / 2.,
        color='yellow',
        linewidth=0,
    )
    ax.add_artist(motor)
    ax.add_artist(pinion)

    # PCB
    height = motor_height - motor_diameter / 2. - pcb_thick
    width = motor_diameter + 2 * wheel_diameter
    pcb = Rectangle(
        (-width / 2., height),
        width=width,
        height=pcb_thick,
        color='green',
        linewidth=0,
    )
    ax.add_artist(pcb)

    # Gears and wheels
    wheel_shift = (pinion_reference_diameter + gear_reference_diameter) / 2.
    alpha = asin(motor_shift / wheel_shift)
    wheel_shift = wheel_shift * cos(alpha)
    height = wheel_diameter / 2.
    gear0 = Circle(
        (-wheel_shift, height),
        radius=gear_reference_diameter / 2.,
        color='gray',
        linewidth=0,
    )
    gear1 = Circle(
        (wheel_shift, height),
        radius=gear_reference_diameter / 2.,
        color='gray',
        linewidth=0,
    )
    wheel0 = Circle((-wheel_shift, height),
                    radius=wheel_diameter / 2.,
                    color='blue',
                    linewidth=0,
                    alpha=0.5)
    wheel1 = Circle((wheel_shift, height),
                    radius=wheel_diameter / 2.,
                    color='blue',
                    linewidth=0,
                    alpha=0.5)
    ax.add_artist(gear0)
    ax.add_artist(gear1)
    ax.add_artist(wheel0)
    ax.add_artist(wheel1)

    # Change plot limits to fit everything
    x_limit = pinion_reference_diameter + wheel_diameter
    y_limit = max(wheel_diameter, motor_height + motor_diameter / 2.)
    ax.set_xlim((-x_limit, x_limit))
    ax.set_ylim((0, y_limit))

    ax.set_aspect('equal')

    # Calculate free space between the PCB and the floor
    pcb_floor_space = min(motor_height - motor_diameter / 2. - pcb_thick,
                          motor_height - motor_diameter / 2.)
    wheel_wheel_space = 2 * wheel_shift - wheel_diameter
    gear_wheel_space = (wheel_diameter - gear_external_diameter) / 2.
    ax.set_title('''PCB to floor: %.2f mm
Between wheels: %.2f mm
Gear (external diameter) to wheel: %.2f mm''' %
                 (pcb_floor_space, wheel_wheel_space, gear_wheel_space))

    plt.show()
Esempio n. 20
0
        cds=so2_cds_uncorr,
        velo=PLUME_VELO,
        pix_dists=pix_dists_line,
        cds_err=calib.err(),
        pix_dists_err=pix_dist_err)

    # IMPORTANT STUFF FINISHED (below follow some plots)
    ax2 = plot_retrieval_points_into_image(so2_img_corr)
    pcs_line.plot_line_on_grid(ax=ax2, ls="-", color="g")
    ax2.legend(loc="best", framealpha=0.5, fancybox=True, fontsize=20)
    ax2.set_title("Dilution corrected AA image", fontsize=12)
    ax2.get_xaxis().set_ticks([])
    ax2.get_yaxis().set_ticks([])

    x0, y0, w, h = pyplis.helpers.roi2rect(AMBIENT_ROI)
    ax2.add_patch(Rectangle((x0, y0), w, h, fc="none", ec="c"))

    fig, ax3 = subplots(1, 1)
    ax3.plot(so2_cds_uncorr, ls="-", color="#ff33e3",
             label=r"Uncorr: $\Phi_{SO2}=$%.2f (+/- %.2f) kg/s"
                   % (phi_uncorr / 1000.0, phi_uncorr_err / 1000.0))
    ax3.plot(so2_cds_corr, "-g", lw=3,
             label=r"Corr: $\Phi_{SO2}=$%.2f (+/- %.2f) kg/s"
                   % (phi_corr / 1000.0, phi_corr_err / 1000.0))

    ax3.set_title("Cross section profile", fontsize=12)
    ax3.legend(loc="best", framealpha=0.5, fancybox=True, fontsize=12)
    ax3.set_xlim([0, len(pix_dists_line)])
    ax3.set_ylim([0, 5e18])
    ax3.set_ylabel(r"$S_{SO2}$ [cm$^{-2}$]", fontsize=14)
    ax3.set_xlabel("PCS", fontsize=14)
Esempio n. 21
0
def runpar(f, g, H, Lg, Lh, l, u, bound, circle, A=None, b=None, E=None, d=None, Tol=1e-2, Heur=0, TolType='r', Vis=0, nsize=12, SD=1, qpsolver='cvxopt'):

    # Optional Inputs
    # Tolerance
    # Heuristic lattice (0 - off, 1 - on)
    # Tolerance type (r - relative, a - absolute)
    # Visualisation (0 - off, 1 - on)
    # Step Debugging (0 - off, 1 - on)
    # Node Size
    # QP Solver (cvxopt, quadprog, nag)

    # MPI
    from mpi4py import MPI

    # MPI comm
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    # Number of processors
    numprocs = comm.Get_size()

    # Print node names for each processors
    print('Processor %i is on node %s') % (rank,str(MPI.Get_processor_name()))

    # Create local groups for load balacing on each node
    from numpy import ceil
    nodes = [[0]]
    bins = int(ceil(numprocs/nsize))
    for i in range(bins):
        nodes.append([])
    for p in range(1,numprocs):
        nodes[(p % bins)+1].append(p)
    print nodes

    # Get D
    D = len(l)
    if(D > 25):
        raise RuntimeError('Hashing for greater than 25D not yet implemented.')

    # Balance Test
    def balance_test(lst):

        for p1 in reversed(range(0,len(lst))):

            for p2 in range(0,p1):

                if( abs(lst[p1]-lst[p2])/(max(min(lst[p1],lst[p2]),1))  > 0.1):

                    return True

        return False

    if(Heur == 0):
        ksp = 3**D
        kspi = ksp

    else:
        # Load relevant normalised lattice
        from numpy import loadtxt, array, sqrt
        if(D == 2):
            lat = array([[0., 0.], [1., 0.], [-1., 0.],
            [0.5, sqrt(3.)/2.], [-0.5, sqrt(3.)/2.],
            [0.5, -sqrt(3.)/2.], [-0.5, -sqrt(3.)/2.]])
        elif(D == 3):
            lat = loadtxt('d3')
        elif(D == 4):
            lat = loadtxt('d4')
        elif(D == 5):
            lat = loadtxt('d5')
        elif(D == 6):
            lat = loadtxt('e6')
        elif(D == 7):
            lat = loadtxt('e7')
        elif(D == 8):
            lat = loadtxt('e8')
        else:
            raise RuntimeError('A lattice for '+str(D)+' Dimensions has yet to be provided.')

        # Get kissing number + 1
        ksp = lat.shape[0]
        kspi = 2**D

    # Master Process
    if(rank == 0):

        # Necessary functions
        from itertools import product
        from numpy import array, sqrt, empty, zeros, inf, hstack, isinf, argmin, argmax, all,ones, identity, vstack, dot
        from numpy.linalg import norm
        from math import floor
        from time import time

        # Import cvxopt solver
        from cvxopt import matrix
        from cvxopt.solvers import qp, options

        # Set tolerance options
        options['show_progress'] = False
        options['abstol'] = 1e-9
        options['reltol'] = 1e-8
        options['feastol'] = 1e-9

        # Initialise empty arrays
        if A is None:
            A = empty((0,D))
            b = empty(0)

        if E is None:
            E = empty((0,D))
            d = empty(0)

        # Check if circle has feasible point
        def mfeasible(c, lfather=None, ufather=None):

            #box containing the ball
            c.lReduced = c.xc - c.r * ones(D)
            c.uReduced = c.xc + c.r * ones(D)

            # check if the sub-ball is in the domain reduced of the father
            def checkAndUpdateBound():

                # intersection between the box of the ball and the box reduced of the father
                for i in range(0,D):

                    if c.lReduced[i]<lfather[i]:
                        c.lReduced[i]=lfather[i]

                    if c.uReduced[i]>ufather[i]:
                        c.uReduced[i]=ufather[i]

            checkAndUpdateBound()

            # Solve QP to check feasibility
            sol = qp(matrix(2*identity(D)),matrix(-2*c.xc),matrix(vstack([-1*identity(D),identity(D),A])),matrix(hstack([-l,u,b])),matrix(E),matrix(d))

            mxopt = array(sol['x']).flatten()
            mr = sol['primal objective']
            mr = mr + dot(c.xc,c.xc)

            # Check if point lies inside domain
            if(mr <= (c.r**2)):
                mf = 1
            else:
                mf = 0
                mxopt = None

            return mf, mxopt

        # Timer
        timer = time()


        r = norm(u-l)/2 # Radius
        xc = (u+l)/2 # Centre

        cn = circle(xc,r)

        mfeas, cxopt = mfeasible(cn,l,u)

        # Upper bound
        ubound = f(cxopt)

        #lower bound and reduced domain
        _, l, u = bound(cn,Lg,Lh,f,g,H,D,A,b,E,d,ubound,True)
        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        # 0.c
        # Split ball
        if(Heur == 0):

            # Split circle into more circles
            inc = r/sqrt(D) # Increment
            rn = r/2 # New radius

            # Create square spoke configuration
            spk = array([p for p in product([-inc,0,inc], repeat=D)])

        else:

            # Split circle into more circles
            inc = r # Increment
            rn = r/2 # New radius

            # Scale configuration
            spk = inc*lat


        # Array to distribute amongst processes
        darray = empty((kspi,D+1))
        boundarray = empty(2*D)
        boundarray = hstack([l,u])
        reqidsend = []
        reqboundsend = []

        # Create surrounding circles
        for i in range(0,kspi):

            # Create centre
            xcn = xc + spk[i,:]

            # Add to distribution list
            darray[i,:] = hstack([array([rn]),xcn])

        # 0.c
        # Distribute data evenly amongst processes
        ihi = 0
        trem = kspi
        prem = numprocs-1

        for p in range(0,numprocs-1):

            tproc = int(round(trem/prem))

            ilo = ihi + 1
            ihi = ihi + tproc

            print('Master sending data elements [%i:%i] to processor %i') % (ilo-1,ihi,p+1)
            comm.Ssend(array([ihi-ilo+1],dtype='i'), dest=p+1, tag=9) # send array size
            reqidsend.append(comm.Issend(darray[ilo-1:ihi,:], dest=p+1, tag=10)) # send data array (Isend?)
            reqboundsend.append(comm.Issend(boundarray, dest=p+1, tag=6))

            prem = prem - 1
            trem = trem - tproc

        # Initial communication setup
        lclists = [1 for i in range(1,numprocs)]
        zerolist = [0 for i in range(1,numprocs)]
        confd = empty(1,dtype='i')
        reqbrecv = []
        reqbsend = []
        rarr = empty((numprocs-1,2))
        reqdreq = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqconf = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqdreqn = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqconfn = [MPI.REQUEST_NULL for i in range(1,numprocs)]

        # Initial local upper bound
        U = inf

        # 0.d-e
        # Initial rlist, xclist and comm setup
        rlist = []
        xclist = []
        rxcndat = empty((numprocs-1,2),dtype='i')
        dwait = 0
        reqxcndat = []
        reqxcnrecv = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqxcnsend = [MPI.REQUEST_NULL for i in range(1,numprocs)]

        # Loop counter
        #itr = 0

        # Asynchronously receive U and len(clist)
        for p in range(0,numprocs-1):

            # New Receive
            reqbrecv.append(comm.Irecv(rarr[p], source=p+1, tag=2))

            # Send U
            reqbsend.append(comm.Issend(array([U]), dest=p+1, tag=3))

        # Make sure data has been sent
        print('Master waiting for initial data sends to complete...')
        for p in range(0,numprocs-1):
            reqidsend[p].Wait()
            reqboundsend[p].Wait()
        print('done.')

        # Asynchronously receive xcn from all workers
        for p in range(0,numprocs-1):

            reqxcndat.append(comm.Irecv(rxcndat[p], source=p+1, tag=12))

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        # 1.
        #and(rad > 1e-15)
        #and((time()-timer) < 3000)
        while((lclists != zerolist)and(not(all(rxcndat == 0)))):

            # Update iteration count
            #itr = itr + 1

            # 1.a
            # Asynchronously receive U and len(clist)
            for p in range(0,numprocs-1):

                if(reqbrecv[p].Test()):

                    # Update U and len(clist)
                    if(rarr[p,0] < U):
                        U = rarr[p,0]
                    lclists[p] = rarr[p,1]

                    # New Receive
                    reqbrecv[p] = comm.Irecv(rarr[p], source=p+1, tag=2)

            # 1.b
            # Asynchronously send U = min(p in {1,...,P}) Up
            # where Up = rarr[p]
            for p in range(0,numprocs-1):

                # If previous communication has finished start new
                if(reqbsend[p].Test()):

                    # Send U
                    reqbsend[p] = comm.Issend(array([U]), dest=p+1, tag=3)


            # 1.c
            # If data check requested, process accordingly
            # If all data sizes received and previous sends have completed
            if(MPI.Request.Testall(reqxcndat))and(MPI.Request.Testall(reqxcnsend)):

                # If not waiting to receive data
                if(dwait == 0):

                    print('Data check from all processors received.')

                    # If any of the processors has ran out of work, ensure it is skipped
                    plist = []
                    for p in range(0,numprocs-1):
                        if(rxcndat[p,1] == 0):
                            reqxcnrecv[p] = MPI.REQUEST_NULL
                        else:
                            plist.append(p)

                    # Set up arrays to store data
                    rxcn = [None for p in range(0,numprocs-1)]
                    for p in plist:
                        rxcn[p] = empty(rxcndat[p,0],dtype='i')

                    # Receive data from all workers
                    for p in plist:
                        reqxcnrecv[p] = comm.Irecv(rxcn[p], source=p+1, tag=14)

                    # Waiting for data
                    dwait = 1

                # If data from all workers received
                if(MPI.Request.Testall(reqxcnrecv)):
                    # Arrays to send
                    nc = [None for p in range(0,numprocs-1)]

                    # Perform data check for all workers
                    for p in plist:

                        # If radius already in list
                        if rxcndat[p,1] in rlist:

                            # Check if xcns already exist
                            ridx = rlist.index(rxcndat[p,1])
                            nc[p] = array(map(int,[a in xclist[ridx] for a in rxcn[p]]),dtype='i')

                            # Add any new xcns to xclist
                            xclist[ridx]+=[rxcn[p][i] for i in range(0,len(nc[p])) if nc[p][i]==0]

                        # Else add radius and xcns to respective lists
                        else:
                            rlist.append(rxcndat[p,1])
                            xclist.append(list(rxcn[p]))
                            nc[p] = zeros(rxcndat[p,0],dtype='i')

                        # Send result of check back (Isend?)
                        reqxcnsend[p] = comm.Issend(nc[p], dest=p+1, tag=14)
                        print('Data check returned to processor %i.') % (p+1)

                    # Post new receives for all processors
                    for p in range(0,numprocs-1):

                        # Ansynchronously receive xcn
                        reqxcndat[p] = comm.Irecv(rxcndat[p], source=p+1, tag=12)

                    # Not waiting for data
                    dwait = 0

            #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            # 1.d
            # Load Balancing spread across nodes

            # Take snapshot of load
            slist = lclists[:]

            # Get load on each node
            lnode = []
            for node in nodes:

                # Master proc, skip
                if(len(node)==1):

                    pass

                # Actual Node with workers
                else:

                    # Create list
                    blist = []
                    for n in node:
                        blist.append(slist[n-1])

                    # Get load per node
                    lnode.append(blist)

            # Get total load per node
            tload = [sum(lnode[i]) for i in range(len(lnode))]

            # Iteration counter
            it = 0

            while((balance_test(tload))and(it < numprocs)):

                # Subtract smallest load
                ml = min(tload)
                tload = map(lambda x: x-ml, tload)

                # Find amount to redistribute
                load = int(floor(sum(tload)/len(lnode)))

                # Find nodes with smallest & largest load
                minn = argmin(tload)
                maxn = argmax(tload)

                # Calculate node load to send
                nload = min(tload[maxn],max(load-tload[minn],0))

                # Find procs with smallest & largest load on max/min nodes
                lminp = argmin(lnode[minn])
                lmaxp = argmax(lnode[maxn])

                # Get proc number
                gminp = nodes[minn+1][lminp]
                gmaxp = nodes[maxn+1][lmaxp]

                # Calculate actual load to send
                lfrac = 3
                aload = min(int(lnode[maxn][lmaxp]/lfrac),max(nload-lnode[minn][lminp],0))

                # Fraction of processors on node
                dfrac = len(nodes[minn+1])

                # Send load from largest to smallest if previous send has completed and aload/dfrac > 0
                if((reqdreqn[gmaxp-1].Test())and(reqconfn[gmaxp-1].Test())and(int(aload/dfrac) > 0)):

                    # Send load from largest to smallest
                    print('Intercomm: Master allocating %i subproblems from processor %i to node %i processors ') % (aload,gmaxp,minn+1),
                    print nodes[minn+1][0:]

                    # Send data allocation request
                    reqdreqn[gmaxp-1] = comm.Issend(array([minn+1,aload],dtype='i'), dest=gmaxp, tag=24)
                    print('Intercomm: Data allocation request sent asynchronously.')

                    # Wait for confirmation of data send
                    reqconfn[gmaxp-1] = comm.Irecv(confd, source=gmaxp, tag=26)

                # Update load per node
                for i in range(len(nodes[minn+1])):
                    lnode[minn][i]+= min(int(aload/dfrac),lnode[maxn][lmaxp])
                lnode[maxn][lmaxp] -= min(aload,lnode[maxn][lmaxp])

                # Update tload
                tload = [sum(lnode[i]) for i in range(len(lnode))]

                # Iteration counter
                it += 1

            # 1.e
            # Load Balancing on each node

            # For each node (excl master)
            for node in nodes:

                # Master proc, skip
                if(len(node)==1):

                    pass

                # Actual Node with workers
                else:

                    # Copy list
                    blist = []
                    for n in node:
                        blist.append(lclists[n-1])

                    # Subtract smallest load
                    ml = min(blist)
                    blist = map(lambda x: x-ml, blist)

                    # Find load amount to redistribute
                    load = int(floor(sum(blist)/len(blist)))

                    # Iteration counter
                    biter = 0

                    while((balance_test(blist))and(biter < len(blist))):

                        # Find procs with smallest & largest load
                        minp = argmin(blist)
                        maxp = argmax(blist)

                        # Convert to global proc numbers
                        gminp = node[minp]
                        gmaxp = node[maxp]

                        # Calculate actual load to send
                        aload = max(load-int(blist[minp]),0)

                        # If previous send has completed and aload > 0
                        if((reqdreq[gmaxp-1].Test())and(reqconf[gmaxp-1].Test())and(aload > 0)):

                            # Send load from largest to smallest
                            print('Master allocating %i subproblems from processor %i to processor %i') % (aload,gmaxp,gminp)

                            # Send data allocation request
                            reqdreq[gmaxp-1] = comm.Issend(array([gminp,aload],dtype='i'), dest=gmaxp, tag=0)
                            print('Data allocation request sent asynchronously.')

                            # Wait for confirmation of data send
                            reqconf[gmaxp-1] = comm.Irecv(confd, source=gmaxp, tag=22)

                        # Update blist
                        blist[minp] += min(aload,blist[maxp])
                        blist[maxp] -= min(aload,blist[maxp])

                        # Update iteration counter
                        biter += 1
            #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

        # 2
        # If all finished, send kill signals
        print('Master sending kill signals...')
        for p in range(0,numprocs-1):
            comm.Ssend(array([1],dtype='i'), dest=p+1, tag=4)

        # Kill any pending data checks (Isend?)
        for p in range(0,numprocs-1):
            reqxcnsend[p] = comm.Issend(array([0],dtype='i'), dest=p+1, tag=14)

        # Clean up redundant messages
        for p in range(0,numprocs-1):
            #reqbsend[p].Cancel()
            reqbrecv[p].Cancel()
            #reqdreq[p].Cancel()
            #reqbsend[p].Free()
            reqbrecv[p].Free()
            #reqdreq[p].Free()

        # 3
        # Receive xopt from all processors
        reqe = []
        earr = empty((numprocs-1,D))
        U = inf
        for p in range(0,numprocs-1):

            # New Receive
            #print('Master posting asynchronous receive of final data from processor %i') % (p+1)
            reqe.append(comm.Irecv(earr[p], source=p+1, tag=5))
            #print('posted.')

        for p in range(0,numprocs-1):

            print('Master waiting to receive final data from processor %i') % (p+1)
            reqe[p].Wait()
            print('Final data from processor %i received') % (p+1)

            # Find xopt with smallest U
            if(not(any(isinf(earr[p])))):
                if(f(earr[p]) < U):
                    xopt = earr[p]
                    U = f(xopt)
        #xopt = empty(D)
        # How do you count iterations?
        itr = None

        # Output end result
        print('Minimum value of %f at (') % U, #f(xopt),
        for i in range(0,D-1):
            print('%f,') % xopt[i],
        print('%f)') % xopt[D-1]
        print('found with'),
        if(TolType == 'a'):
            print('absolute'),
        else:
            print('relative'),
        print('tolerance %f.') % Tol
        tol = Tol
        xs = xopt
        fxs = U #f(xopt)
        print('Elapsed time %f seconds.') % (time()-timer)

        return xs, fxs, tol, itr

    # Worker processes
    else:

        # import necessary functions
        from heapq import heappush, heappop
        from numpy import array, sqrt, dot, identity, hstack, vstack, inf, empty, ones, zeros, tile, roll, all
        from numpy.linalg import norm
        from itertools import product
        from sys import float_info
        from math import floor, ceil
        from time import time

        # Vector Hash function: http://stackoverflow.com/questions/5928725/hashing-2d-3d-and-nd-vectors
        #htsize = 499 # Hash Table size
        res = 1e-5 # Resolution
        # Twenty five arbitrarily chosen 8-digit primes
        primes = [73856093, 19349663, 83492791, 15485863, 86028121, 32452843, 67867967, 49979687,
                  86028157, 13769629, 95189161, 29223841, 83972821, 39271703, 79186817, 47286739,
                  98767549, 14139199, 64244023, 18551173, 55621541, 10920859, 53615137, 24405817,
                  43176253]


        # Pick up scattered list
        rsize = array([0],dtype='i')
        comm.Recv(rsize, source=0, tag=9)
        rarray = empty((rsize[0],D+1))
        boundarray = empty(2*D)
        comm.Recv(rarray, source=0, tag=10)
        comm.Recv(boundarray, source=0, tag=6)
        print('Processor %i received initial data') % rank

        lr = boundarray[0:D]
        ur = boundarray[D:2*D]

        # Hash function
        def hashnd(x):
            result = 0
            for i in range(0,D):
                result = result ^ (int(floor(x[i]/res))*primes[i])
            return result

        # Hash radius
        def hashrn(r):
            return int(r*1e8)

        # Initialise empty arrays
        if A is None:
            A = empty((0,D))
            b = empty(0)

        if E is None:
            E = empty((0,D))
            d = empty(0)

        # QuadProg++ solver (fast!)
        if(qpsolver == 'quadprog'):

            # Import QuadProg++ solver
            from PyQuadProg import PyQuadProg

            # Check if circle has feasible point
            def mfeasible(c):

                # Solve QP to check feasibility
                sol = PyQuadProg(2*identity(D),-2*c.xc,E.transpose(),-1*d,vstack([identity(D),-1*identity(D),-1*A]).transpose(),hstack([-l,u,b]))
                mxopt = sol.x.getArray()
                mr = dot(mxopt,mxopt) + dot(mxopt,-2*c.xc) + dot(c.xc,c.xc)

                # Check if point lies inside domain
                if(mr < (c.r**2)):
                    mf = 1
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # CVXOPT QP solver (slow)
        elif(qpsolver == 'cvxopt'):

            # Import cvxopt solver
            from cvxopt import matrix
            from cvxopt.solvers import qp, options

            # Set tolerance options
            options['show_progress'] = False
            options['abstol'] = 1e-9
            options['reltol'] = 1e-8
            options['feastol'] = 1e-9

            # Check if circle has feasible point
            def mfeasible(c, lfather=None, ufather=None):

                #box containing the ball
                c.lReduced = c.xc - c.r * ones(D)
                c.uReduced = c.xc + c.r * ones(D)

                # check if the sub-ball is in the domain reduced of the father
                def checkAndUpdateBound():

                    check=1

                    for i in range(0,D):

                        # check the intersection between the subball and the reduction of the father's ball
                        # if there isn't intersection, then discard the subball (check = 0)
                        if c.lReduced[i]>ufather[i] or c.uReduced[i]<lfather[i]:
                            check=0
                            break

                        # intersection of the subball with the orginal domain (reduced at first step)
                        if c.lReduced[i]<lr[i]:
                            c.lReduced[i]=lr[i]

                        if c.uReduced[i]>ur[i]:
                            c.uReduced[i]=ur[i]

                    return check

                check=1
                if lfather is not None and ufather is not None:
                    check = checkAndUpdateBound()

                if check==1:
                    # Solve QP to check feasibility
                    sol = qp(matrix(2*identity(D)),matrix(-2*c.xc),matrix(vstack([-1*identity(D),identity(D),A])),matrix(hstack([-lr,ur,b])),matrix(E),matrix(d))

                    mxopt = array(sol['x']).flatten()
                    mr = sol['primal objective']
                    mr = mr + dot(c.xc,c.xc)

                    # Check if point lies inside domain
                    if(mr <= (c.r**2)):
                        mf = 1
                    else:
                        mf = 0
                        mxopt = None
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # NAG QP solver (fast!)
        elif(qpsolver == 'nag'):

            # Import QP Solver
            from qpsolver_lincon import qpsolver_lincon

            # Check if circle has feasible point
            def mfeasible(c):

                # Solve QP to check feasibility
                mxopt = c.xc.copy()
                mr = qpsolver_lincon(2*identity(D),-2*c.xc,hstack([l,-inf,d]),hstack([u,b,d]),mxopt,vstack([A,E]),D,A.shape[0]+E.shape[0])
                mr = mr + dot(c.xc,c.xc)

                # Check if point lies inside domain
                if(mr < (c.r**2)):
                    mf = 1
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # Visualisation
        if(Vis == 1):

            from matplotlib.pyplot import figure, Rectangle, Circle, gca, show, title, axis, draw
            from colorsys import hsv_to_rgb
            from random import random

            # Draw bound constraints [l,u]
            fig = figure('Processor '+str(rank))
            gca().add_patch(Rectangle((l[0],l[1]), u[0]-l[0], u[1]-l[1], fill=False))
            axis([l[0]-1,u[0]+1,l[1]-1,u[1]+1])
            title('Processor '+str(rank))
            show(block=False)

            # Circle drawing procedure
            def drawc(c):

                # Draw circle colured according to partition
                gca().add_patch(Circle((c.xc[0],c.xc[1]), radius=c.r , color=hsv_to_rgb(random(),1,1), fill=False))
                axis('equal')
                draw()

        # Priority queue
        clist = []                      # list of entries arranged in a heap

        # Add a new task
        def add_task(task):
            heappush(clist, (task.lbound, task))

        # Remove and return the lowest priority task. Raise KeyError if empty.
        def pop_task():
            while clist:
                return heappop(clist)
            raise KeyError('Pop from an empty priority queue!')

        # Remove and return (in an mpi transfer array) the n lowest priority tasks
        def npop_task(n):
            carray = empty((n,(3*D)+2))
            for i in range(0,n):
                celm = pop_task()
                carray[i,0:D+2] = hstack([array([celm[0],celm[1].r]),celm[1].xc])
                carray[i,D+2:2*D+2] = celm[1].lReduced
                carray[i,2*D+2:3*D+2] = celm[1].uReduced

            return carray


        # Initial local upper bound
        U = inf

        # Bound communication setup
        rarr = empty(1)
        karr = empty(1,dtype='i')
        kill = 0
        dwait = 0
        dwaits = 0
        reqdsend = MPI.REQUEST_NULL
        reqdsizesend = MPI.REQUEST_NULL
        reqconf = MPI.REQUEST_NULL
        reqnsend = MPI.REQUEST_NULL
        dwaitn = 0
        dwaitsn = 0
        reqdsendn = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqdsizesendn = [MPI.REQUEST_NULL for i in range(1,numprocs)]
        reqconfn = MPI.REQUEST_NULL

        # 1.b-c
        # Bound intial list and convert to priority queue
        for k in range(0,rsize):

            # Create circle
            cn = circle(rarray[k,1:D+1],rarray[k,0])

            # Check if circle is feasible
            mfeas, cxopt = mfeasible(cn,lr,ur)

            # If circle has a feasible point (i.e. it's feasible)
            if(mfeas != 0):

                # Upper bound
                ubound = f(cxopt)

                # Update U and xopt
                if(ubound < U):
                    U = ubound
                    xopt = cxopt

                # Bound circle
                cn.lbound, cn.lReduced, cn.uReduced = bound(cn,Lg,Lh,f,g,H,D,A,b,E,d,U,True,cn.r*2)

                # Add to priority queue
                add_task(cn)

                # Visualise
                if(Vis ==1):
                    drawc(cn)

        initialRadius = cn.r*2

        # 1.d
        # Asynchronously send U and len(clist)
        reqbsend = comm.Issend(array([U,len(clist)]), dest=0, tag=2)

        # 1.e
        # Asynchronously receive U
        reqbrecv = comm.Irecv(rarr, source=0, tag=3)

        # Debug Output
        if (SD == 1):
            #if(rank == 0):
            print('Time: %f') % (time()),
            print('Processor %i Number of elements: %i') % (rank,len(clist))
            print('U: %f') % U
            #print('L: %f') % L
            #print('Circle radius: %e') % rad
            print('----------------------------')

        # Intial data request
        rq_proc_load = empty(2,dtype='i')
        rq_proc_loadn = empty(2,dtype='i')
        reqd = comm.Irecv(rq_proc_load, source=0, tag=0)
        reqdn = comm.Irecv(rq_proc_loadn, source=0, tag=24)

        # Initial kill signal request
        reqk = comm.Irecv(karr, source=0, tag=4)

        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        # 2
        optimality = False
        while(kill == 0):

            # Set tolerance
            if((TolType == 'r')and(abs(U) > float_info.epsilon)):
                cutoff = U - Tol*abs(U)
            else:
                cutoff = U - Tol

            # Prune list
            i = 0
            while(i < len(clist)):

                if(clist[i][0] > cutoff):
                    del clist[i]
                    i=i-1
                i = i+1

            # If there is work left to do
            if(len(clist) != 0):

                # Get circle with smallest lbound
                L, cslb = pop_task()

                if(Heur == 0):

                    # Split circle into more circles
                    inc = cslb.r/sqrt(D) # Increment
                    rn = cslb.r/2 # New radius
                    xc = cslb.xc # Centre

                    # Create square spoke configuration
                    spk = array([p for p in product([-inc,0,inc], repeat=D)])

                    # Move centre to start of spoke array
                    spk = roll(spk,int(ceil(ksp/2)),axis=0)

                else:

                    # Split circle into more circles
                    inc = cslb.r # Increment
                    rn = cslb.r/2 # New radius
                    xc = cslb.xc # Centre

                    # Scale configuration
                    spk = inc*lat

                # Create surrounding circles
                # Create centre
                nc = zeros(ksp)
                xcn = tile(xc,(ksp,1)) + spk

                # Check if circles exists locally
                for k in range(0,len(clist)):
                    for i in range(0,ksp):
                        if(all(xcn[i,:] == clist[k][1].xc)):
                            nc[i] = 1

                # Check if circles exists globally
                # Remove local duplicates
                dxcn = []
                hdxcn = []
                for i in range(0,ksp):
                    if(nc[i] == 0):
                        dxcn.append(xcn[i,:])
                        hdxcn.append(hashnd(xcn[i,:]))
                xcn = array(dxcn)
                hxcn = array(hdxcn,dtype='i')
                del dxcn[:]
                del hdxcn[:]

                # Send data asynchronously
                #print('Processor %i sending data check to master processor.') % rank
                comm.Send(array([len(hxcn),hashrn(rn)],dtype='i'), dest=0, tag=12) # send array size
                _ = comm.Issend(hxcn, dest=0, tag=14) # send data array (Isend?)
                #print('Data check sent. Awaiting response.')

                # Receive data asynchronously
                nc = empty(len(hxcn),dtype='i')
                reqdcheck = comm.Irecv(nc, source=0, tag=14)
                #print('Data check completed successfully.')

                # Start bounding balls
                lcn = []
                lmfeas = []
                lcxopt = []
                lubound = []

                for i in range(0,len(xcn)):

                    # Create circle
                    lcn.append(circle(xcn[i,:],rn))
                    mfeas, cxopt = mfeasible(lcn[i],cslb.lReduced,cslb.uReduced)
                    lmfeas.append(mfeas)
                    lcxopt.append(cxopt)

                    # Bound if feasible
                    if(mfeas != 0):

                        # Lower bound
                        lcn[i].lbound, lcn[i].lReduced, lcn[i].uReduced = bound(lcn[i],Lg,Lh,f,g,H,D,A,b,E,d,U,optimality,initialRadius)

                        # Upper bound
                        lubound.append(f(cxopt))

                    else:

                        # Don't need upper bound
                        lubound.append(None)

                    if(reqdcheck.Test()): # Test if data check received
                        break
                else:
                    print('Processor %i started waiting for data check.') % rank
                    wtimer = time() # Time wait time
                    reqdcheck.Wait() # Wait for data check
                    print('Processor %i spent %f seconds waiting for data check from master.') % (rank,time()-wtimer)

                # Finish bounding
                for j in range(0,len(xcn)):

                    # If circle doesn't already exist somewhere
                    if(nc[j] == 0):

                        # If circle already bounded
                        if(j <= i):

                            # And circle feasible
                            if(lmfeas[j] != 0):

                                # Update U and xopt
                                if(lubound[j] < U):
                                    U = lubound[j]
                                    xopt = lcxopt[j]

                                # Add to priority queue
                                add_task(lcn[j])

                                # Visualise
                                if(Vis ==1):
                                    drawc(lcn[j])

                        else:

                            # Create circle
                            cn = circle(xcn[j,:],rn)
                            mfeas, cxopt = mfeasible(cn,cslb.lReduced,cslb.uReduced)

                            # If circle has a feasible point (i.e. it's feasible)
                            if(mfeas != 0):

                                # Upper bound
                                ubound = f(cxopt)

                                # Update U and xopt
                                if(ubound < U):
                                    U = ubound
                                    xopt = cxopt

                                # Lower bound
                                cn.lbound, cn.lReduced, cn.uReduced = bound(cn,Lg,Lh,f,g,H,D,A,b,E,d,U,optimality,initialRadius)

                                # Add to priority queue
                                add_task(cn)

                                # Visualise
                                if(Vis ==1):
                                    drawc(cn)

                # Intercomm: Send data if requested and previous data send has completed
                if((reqdn.Test())and(MPI.Request.Testall(reqdsendn))and(MPI.Request.Testall(reqdsizesendn))and(reqconfn.Test())):

                    print('Intercomm: Node %i needs data from processor %i') % (rq_proc_loadn[0],rank)
                    # Workload to send
                    nit = min(int(rq_proc_loadn[1]/len(nodes[rq_proc_loadn[0]])),len(clist)/len(nodes[rq_proc_loadn[0]]))

                    if(nit > 0):

                        print('Intercomm: Sending %i subproblems from processor %i to node %i each of processors') % (nit,rank,rq_proc_loadn[0]),
                        print nodes[rq_proc_loadn[0]][0:]

                        # Send data asynchronously
                        for p in nodes[rq_proc_loadn[0]]:
                            reqdsizesendn[p-1] = comm.Issend(array([nit,rank],dtype='i'), dest=p, tag=30) # send array size
                            reqdsendn[p-1] = comm.Issend(npop_task(nit), dest=p, tag=28) # send data array

                        print('Intercomm: Data sent asynchronously.')
                        # Send confirmation to master
                        reqconfn = comm.Issend(array([1],dtype='i'), dest=0, tag=26)

                    else:
                        print('Intercomm: Not enough data to send.')
                        # Send confirmation to master
                        reqconfn = comm.Issend(array([1],dtype='i'), dest=0, tag=26)

                    # Wait for other data requests
                    reqdn = comm.Irecv(rq_proc_loadn, source=0, tag=24)

                # Send data if requested and previous data send has completed
                if((reqd.Test())and(reqdsend.Test())and(reqdsizesend.Test())and(reqconf.Test())):

                    print('Processor %i needs data from processor %i') % (rq_proc_load[0],rank)
                    # Workload to send
                    nit = min(rq_proc_load[1],len(clist))

                    print('Sending %i subproblems from processor %i to processor %i') % (nit,rank,rq_proc_load[0])
                    # Send data asynchronously (Isend?)
                    reqdsizesend = comm.Issend(array([nit,rank],dtype='i'), dest=rq_proc_load[0], tag=11) # send array size
                    reqdsend = comm.Issend(npop_task(nit), dest=rq_proc_load[0], tag=1) # send data array (Isend?)

                    print('Data sent asynchronously.')
                    # Send confirmation to master (Isend?)
                    reqconf = comm.Issend(array([1],dtype='i'), dest=0, tag=22)

                    # Wait for other data requests
                    reqd = comm.Irecv(rq_proc_load, source=0, tag=0)

                # Debug Output
                if (SD == 1):
                    #if(rank == 0):
                    print('Time: %f') % (time()),
                    print('Processor %i Number of elements: %i') % (rank,len(clist))
                    print('U: %f') % U
                    print('LL: %f') % L
                    #print('Circle radius: %e') % rad
                    print('----------------------------')

            # Run out of work
            else:

                # Notify master that ran out of work if previous send completed
                if(reqnsend.Test()):

                    print('Time: %f') % (time()),
                    print('Processor %i ran out of work!') % rank

                    reqnsend = comm.Issend(array([0,0],dtype='i'), dest=0, tag=12)

            # If not waiting to receive data size
            if(dwaits == 0):

                # Receive data
                print('Processor %i asynchronously waiting to receive data.') % rank
                darrsize = array([0,0],dtype='i')
                reqdsize = comm.Irecv(darrsize, source=MPI.ANY_SOURCE, tag=11)

                # Waiting for data size
                dwaits = 1

            # If data size received
            if(reqdsize.Test()):

                # If not waiting to receive data
                if(dwait == 0):

                    darr = empty((darrsize[0],(3*D)+2))
                    reqds = comm.Irecv(darr,source=darrsize[1], tag=1)

                    # Waiting for data
                    dwait = 1

                # If data received
                if(reqds.Test()):

                    for i in range(0,darrsize[0]):
                        ctemp = circle(darr[i,2:2+D],darr[i,1])
                        ctemp.lbound = darr[i,0]
                        ctemp.lReduced = darr[i,2+D:2+2*D]
                        ctemp.uReduced = darr[i,2+2*D:2+3*D]

                        add_task(ctemp)

                    print('Data received succesfully.')

                    # Not waiting for data size or data
                    dwaits = 0
                    dwait = 0

            # Intercomm: If not waiting to receive data size
            if(dwaitsn == 0):

                # Receive data
                print('Intercomm: Processor %i asynchronously waiting to receive data.') % rank
                darrsizen = array([0,0],dtype='i')
                reqdsizen = comm.Irecv(darrsizen, source=MPI.ANY_SOURCE, tag=30)

                # Waiting for data size
                dwaitsn = 1

            # Intercomm: If data size received
            if(reqdsizen.Test()):

                # If not waiting to receive data
                if(dwaitn == 0):

                    darrn = empty((darrsizen[0],(3*D)+2))

                    reqdsn = comm.Irecv(darrn,source=darrsizen[1], tag=28)

                    # Waiting for data
                    dwaitn = 1

                # If data received
                if(reqdsn.Test()):

                    for i in range(0,darrsizen[0]):
                        ctemp = circle(darrn[i,2:2+D],darrn[i,1])
                        ctemp.lbound = darrn[i,0]
                        ctemp.lReduced = darrn[i,2+D:2+2*D]
                        ctemp.uReduced = darrn[i,2+2*D:2+3*D]

                        add_task(ctemp)

                    print('Intercomm: Data received succesfully.')

                    # Not waiting for data size or data
                    dwaitsn = 0
                    dwaitn = 0

            # Asynchronously send UL and len(clist)
            # If previous communication has finished start new
            if(reqbsend.Test()):

                # Send UL and len(clist)
                reqbsend = comm.Issend(array([U,len(clist)]), dest=0, tag=2)

            if(reqbrecv.Test()):

                # Update U
                if(rarr[0] < U):
                    U = rarr[0]

                # New Receive
                reqbrecv = comm.Irecv(rarr, source=0, tag=3)

            # Asynchronously receive kill signal
            if(reqk.Test()):
                kill = 1

        # Say if finished!
        print('Processor %i has finished!') % rank

        # Clean up redundant messages
        #reqbsend.Cancel()
        reqbrecv.Cancel()
        #reqd.Cancel()
        #reqbsend.Free()
        reqbrecv.Free()
        #reqd.Free()

        # Send xopt to master
        print('Processor %i sending final data to master') % rank
        if('xopt' not in locals()):  # No xopt
            xopt = inf*ones(D)
        comm.Ssend(xopt, dest=0, tag=5)

        # Display figures and wait
        if(Vis == 1):
            show()

        return None, None, None, None
Esempio n. 22
0
def animate(i):
    pass


N = 10
width = 10
tab = permutation(N)

fig = figure(figsize=(len(tab), 3))
axis('off')
axis('equal')
axis([0, len(tab) * width, 0, width])

rectangles = [
    gca().add_patch(
        Rectangle(array([i * width, 0]), width - 1, width - 1, fc='b'))
    for i in range(N)
]
annotations = [
    gca().annotate(tab[i],
                   array([i * width, 0]) + array([(width - 1) * .5,
                                                  (width - 1) * .5]),
                   color='w',
                   weight='bold',
                   fontsize=20,
                   ha='center',
                   va='center') for i in range(N)
]
indices = [n for n in range(N)]

ani = FuncAnimation(fig,
Esempio n. 23
0
File: T1.py Progetto: Nuos/oBB
def runpar(f,
           g,
           H,
           Lg,
           Lh,
           l,
           u,
           bound,
           circle,
           A=None,
           b=None,
           E=None,
           d=None,
           Tol=1e-2,
           Heur=0,
           TolType='r',
           Vis=0,
           SD=1,
           Rtol=1e-15,
           TimeQP=0,
           TimeWidle=0,
           qpsolver='cvxopt'):

    # Optional Inputs
    # Tolerance
    # Heuristic lattice (0 - off, 1 - on)
    # Tolerance type (r - relative, a - absolute)
    # Visualisation (0 - off, 1 - on)
    # Step Debugging (0 - off, 1 - on)
    # Radius Tolerance
    # Time Worker Idling (0 - off, 1 - on)
    # Time QP solves (0 - off, 1 - on)
    # QP Solver (quadprog, cvxopt, nag)

    # MPI
    from mpi4py import MPI

    # MPI comm
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    # Get D
    D = len(l)

    # Master Process
    if (rank == 0):

        # Number of processors
        numprocs = comm.Get_size()

        # Import necessary functions
        from numpy import array, pi, sqrt, dot, identity, hstack, vstack, empty, inf
        from numpy.linalg import norm
        from time import time
        from itertools import product
        from sys import float_info

        # Initialise empty arrays
        if (A is None):
            A = empty((0, D))
            b = empty(0)

        if (E is None):
            E = empty((0, D))
            d = empty(0)

        # QuadProg++ solver (fast!)
        if (qpsolver == 'quadprog'):

            # Import QuadProg++ solver
            from PyQuadProg import PyQuadProg

            # Check if circle has feasible point
            def mfeasible(c):

                # Solve QP to check feasibility
                sol = PyQuadProg(
                    2 * identity(D), -2 * c.xc, E.transpose(), -1 * d,
                    vstack([identity(D), -1 * identity(D),
                            -1 * A]).transpose(), hstack([-l, u, b]))
                mxopt = sol.x.getArray()
                mr = dot(mxopt, mxopt) + dot(mxopt, -2 * c.xc) + dot(
                    c.xc, c.xc)

                # Check if point lies inside domain
                if (mr < (c.r**2)):
                    mf = 1
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # CVXOPT QP solver (slow)
        elif (qpsolver == 'cvxopt'):

            # Import cvxopt solver
            from cvxopt import matrix
            from cvxopt.solvers import qp, options

            # Set tolerance options
            options['show_progress'] = False
            options['abstol'] = 1e-9
            options['reltol'] = 1e-8
            options['feastol'] = 1e-9

            # Check if circle has feasible point
            def mfeasible(c):

                # Solve QP to check feasibility
                sol = qp(matrix(2 * identity(D)), matrix(-2 * c.xc),
                         matrix(vstack([-1 * identity(D),
                                        identity(D), A])),
                         matrix(hstack([-l, u, b])), matrix(E), matrix(d))
                mxopt = array(sol['x']).flatten()
                mr = sol['primal objective']
                mr = mr + dot(c.xc, c.xc)

                # Check if point lies inside domain
                if (mr < (c.r**2)):
                    mf = 1
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # NAG QP solver (fast!)
        elif (qpsolver == 'nag'):

            # Import QP Solver
            from qpsolver_lincon import qpsolver_lincon

            # Check if circle has feasible point
            def mfeasible(c):

                # Solve QP to check feasibility
                mxopt = c.xc.copy()
                mr = qpsolver_lincon(2 * identity(D), -2 * c.xc,
                                     hstack([l, -inf, d]), hstack([u, b,
                                                                   d]), mxopt,
                                     vstack([A, E]), D,
                                     A.shape[0] + E.shape[0])
                mr = mr + dot(c.xc, c.xc)

                # Check if point lies inside domain
                if (mr < (c.r**2)):
                    mf = 1
                else:
                    mf = 0
                    mxopt = None

                return mf, mxopt

        # Visualisation
        if (Vis == 1):

            from matplotlib.pyplot import figure, Rectangle, Circle, gca, show, title, axis, draw

            # Draw bound constraints [l,u]
            fig = figure('Processor ' + str(rank))
            gca().add_patch(
                Rectangle((l[0], l[1]), u[0] - l[0], u[1] - l[1], fill=False))
            axis([l[0] - 1, u[0] + 1, l[1] - 1, u[1] + 1])
            title('Master Processor')
            show(block=False)

            # Circle drawing procedure
            def drawc(c, col):

                # Draw circle
                gca().add_patch(
                    Circle((c.xc[0], c.xc[1]),
                           radius=c.r,
                           color=col,
                           fill=False))
                axis('equal')
                draw()

        if (Heur == 0):

            ksp = 3**D

        else:
            # Load relevant normalised lattice
            from numpy import loadtxt
            from pkg_resources import resource_stream
            if (D == 2):
                lat = array([[0., 0.], [1., 0.], [-1., 0.],
                             [0.5, sqrt(3.) / 2.], [-0.5, sqrt(3.) / 2.],
                             [0.5, -sqrt(3.) / 2.], [-0.5, -sqrt(3.) / 2.]])
            elif (D == 3):
                lat = loadtxt(resource_stream('obb', 'lattices/d3'))
            elif (D == 4):
                lat = loadtxt(resource_stream('obb', 'lattices/d4'))
            elif (D == 5):
                lat = loadtxt(resource_stream('obb', 'lattices/d5'))
            elif (D == 6):
                lat = loadtxt(resource_stream('obb', 'lattices/e6'))
            elif (D == 7):
                lat = loadtxt(resource_stream('obb', 'lattices/e7'))
            elif (D == 8):
                lat = loadtxt(resource_stream('obb', 'lattices/e8'))
            else:
                raise RuntimeError('A lattice for ' + str(D) +
                                   ' Dimensions has yet to be provided.')

            # Get kissing number + 1
            ksp = lat.shape[0]

        # Set up initial circle
        c0 = circle((u + l) / 2, norm(u - l) / 2)
        c0.xopt = c0.xc

        # Bound circle
        c0.lbound = bound(c0, Lg, Lh, f, g, H, D)

        # Upper bound
        c0.ubound = f(c0.xopt)

        # Set up circle list
        clist = [c0]
        cslb = clist[0]

        # Update global bounds
        U = cslb.ubound
        L = cslb.lbound
        xopt = cslb.xopt
        rad = cslb.r

        # Loop counter
        itr = 0
        timer = time()
        if (TimeQP == 1):
            qptime = 0

        # Debug Output
        if (SD == 1):
            print('----------------------------')
            print('Number of elements: %i') % len(clist)
            print('U: %f') % U
            print('L: %f') % L
            print('Circle radius: %e') % rad
            print('----------------------------')

        # Set tolerance
        if ((TolType == 'r') and (abs(U) > float_info.epsilon)):
            cutoff = (U - L) / abs(U)
        else:
            cutoff = U - L

        #and((time()-timer) < 3000)
        while ((cutoff > Tol) and (rad > Rtol)):

            # Update iteration count
            itr = itr + 1

            # Prune list
            i = 0
            while (i < len(clist)):
                if (clist[i].lbound > U):

                    # Visualise
                    if (Vis == 1):
                        drawc(clist[i], 'k')

                    del clist[i]
                    i = i - 1
                i = i + 1

            if (Heur == 0):

                # Split circle into more circles
                inc = (cslb.r) / sqrt(D)  # Increment
                rn = (cslb.r) / 2  # New radius
                xc = cslb.xc  # Centre

                # Visualise
                if (Vis == 1):
                    drawc(cslb, 'k')

                clist.remove(cslb)  # Remove split circle from list

                # Create square spoke configuration
                spk = array([p for p in product([-inc, 0, inc], repeat=D)])

            else:

                # Split circle into more circles
                inc = cslb.r  # Increment
                rn = (cslb.r) / 2  # New radius
                xc = cslb.xc  # Centre

                # Visualise
                if (Vis == 1):
                    drawc(cslb, 'k')

                clist.remove(cslb)  # Remove split circle from list

                # Scale configuration
                spk = inc * lat

            # List to distribute amongst processes
            dlist = []

            # Create surrounding circles
            for i in range(0, ksp):

                # Create centre
                xcn = xc + spk[i, :]

                # Check if circle exists
                nc = 0
                for k in range(0, len(clist)):
                    if (all(xcn == clist[k].xc)):
                        nc = 1

                # If circle doesn't exist
                if (nc == 0):

                    # Create circle
                    cn = circle(xcn, rn)

                    # Time QP Solve
                    if (TimeQP == 1):
                        eltime = MPI.Wtime()
                    mfeas, cn.xopt = mfeasible(cn)
                    if (TimeQP == 1):
                        qptime += MPI.Wtime() - eltime

                    # If circle has a feasible point (i.e. it's feasible)
                    if (mfeas != 0):

                        # Add to distribution list
                        dlist.append(cn)

                        # Visualise
                        if (Vis == 1):
                            drawc(cn, 'b')

            # Distribute data evenly amongst processes
            ihi = 0
            trem = len(dlist)
            prem = numprocs
            req = []

            for p in range(0, numprocs - 1):

                tproc = int(round(trem / prem))

                ilo = ihi + 1
                ihi = ihi + tproc

                req.append(
                    comm.isend(dlist[ilo - 1:ihi],
                               dest=numprocs - 1 - p,
                               tag=0))

                prem = prem - 1
                trem = trem - tproc

            # Distribute remaining data to self
            tproc = int(round(trem / prem))

            # Bound each item allocated to self
            for k in range(ihi, ihi + tproc):

                # Bound circle
                dlist[k].ubound = f(dlist[k].xopt)

                dlist[k].lbound = bound(dlist[k], Lg, Lh, f, g, H, D)

                # Add to circle list
                clist.append(dlist[k])

            # Gather data back up
            for p in range(0, numprocs - 1):

                # Make sure data has been sent
                req[p].Wait()

                # Get list of bounded circles from other processes
                dlist = comm.recv(source=numprocs - 1 - p, tag=1)

                # Add to clist
                clist += dlist

            # Find circle c with smallest ubound
            cslb = min(clist, key=lambda x: x.ubound)

            # Update global feasible upper bound
            U = cslb.ubound
            xopt = cslb.xopt
            rad = cslb.r

            # Find circle with smallest lbound
            cslb = min(clist, key=lambda x: x.lbound)
            L = cslb.lbound

            # Set tolerance
            if ((TolType == 'r') and (abs(U) > float_info.epsilon)):
                cutoff = (U - L) / abs(U)
            else:
                cutoff = U - L

            # Debug Output
            if (SD == 1):
                print('Number of elements: %i') % len(clist)
                print('U: %f') % U
                print('L: %f') % L
                print('Circle radius: %e') % rad
                print('----------------------------')

        # Output end result
        print('Minimum value of %f at (') % f(xopt),
        for i in range(0, D - 1):
            print('%f,') % xopt[i],
        print('%f)') % xopt[D - 1]
        print('found with'),
        if ((TolType == 'r') and (abs(U) > float_info.epsilon)):
            print('relative'),
        else:
            print('absolute'),
        print('tolerance %f in %i iterations.') % (cutoff, itr)
        tol = cutoff
        xs = xopt
        fxs = f(xopt)
        print('Elapsed time %f seconds.') % (time() - timer)
        if (TimeQP == 1):
            print('Time taken for QP solves is %f seconds') % qptime

        # Kill worker processes
        for p in range(0, numprocs - 1):

            comm.send(None, dest=numprocs - 1 - p, tag=0)

        # Display figures and wait
        if (Vis == 1):
            show()

        return xs, fxs, tol, itr

    # Worker processes
    else:

        # Idle time
        if (TimeWidle == 1):
            eltime = MPI.Wtime()
            itime = 0

        # Pick up scattered list
        rlist = comm.recv(source=0, tag=0)

        # Idle time
        if (TimeWidle == 1):
            itime += MPI.Wtime() - eltime

        while (rlist != None):

            # Bound each item in the list
            for k in range(0, len(rlist)):

                # Bound circle
                rlist[k].ubound = f(rlist[k].xopt)

                rlist[k].lbound = bound(rlist[k], Lg, Lh, f, g, H, D)

            # Send bounded list
            comm.send(rlist, dest=0, tag=1)

            # Idle time
            if (TimeWidle == 1):
                eltime = MPI.Wtime()

            # Pick up next scattered list
            rlist = comm.recv(source=0, tag=0)

            # Idle time
            if (TimeWidle == 1):
                itime += MPI.Wtime() - eltime

        # Output idle time
        if (TimeWidle == 1):
            print('Processor %i has been idle for %f seconds') % (rank, itime)
        return None, None, None, None