Exemplo n.º 1
0
def main():
    # Take command line arguments
    parser = argparse.ArgumentParser()
    # parser.add_argument("input", help="Input file");
    parser.add_argument("-i", "--input", required=True, help="input file")
    parser.add_argument("-v",
                        "--verbose",
                        help="verbose mode",
                        action="store_true")
    parser.add_argument("-s",
                        "--solver",
                        choices=["sat", "csp", "asp", "ilp", "prop"],
                        default="prop",
                        help="selects which solver to use (default: prop)")
    args = parser.parse_args(map(lambda x: x.lower(), sys.argv[1:]))

    input = args.input
    verbose = args.verbose
    solver = args.solver

    # Read sudoku from input file
    if verbose:
        print("Reading sudoku from " + input + "..")
    k, sudoku = read_sudoku_from_file(input)
    if sudoku == None:
        print("Exiting..")
        return

    # Print information, in verbose mode
    if verbose:
        print("Input sudoku:")
        print(pretty_repr(sudoku, k))

    # Solve the sudoku using the selected solver
    solved_sudoku = None
    if solver == "sat":
        timer = Timer(name="solving-time",
                      text="Did SAT encoding & solving in {:.2f} seconds")
        if verbose:
            print("Solving sudoku using the SAT encoding..")
            timer.start()
            # with suppress_stdout_stderr():
            solved_sudoku = solve_sudoku_SAT(sudoku, k)
        if verbose:
            timer.stop()
    elif solver == "csp":
        timer = Timer(name="solving-time",
                      text="Did CSP encoding & solving in {:.2f} seconds")
        if verbose:
            print("Solving sudoku using the CSP encoding..")
            timer.start()
            # with suppress_stdout_stderr():
            solved_sudoku = solve_sudoku_CSP(sudoku, k)
        if verbose:
            timer.stop()
    elif solver == "asp":
        timer = Timer(name="solving-time",
                      text="Did ASP encoding & solving in {:.2f} seconds")
        if verbose:
            print("Solving sudoku using the ASP encoding..")
            timer.start()
            # with suppress_stdout_stderr():
            solved_sudoku = solve_sudoku_ASP(sudoku, k)
        if verbose:
            timer.stop()
    elif solver == "ilp":
        timer = Timer(name="solving-time",
                      text="Did ILP encoding & solving in {:.2f} seconds")
        if verbose:
            print("Solving sudoku using the ILP encoding..")
            timer.start()
            # with suppress_stdout_stderr():
            solved_sudoku = solve_sudoku_ILP(sudoku, k)
        if verbose:
            timer.stop()
    elif solver == "prop":
        timer = Timer(
            name="solving-time",
            text="Did recursive solving with propagation in {:.2f} seconds")
        if verbose:
            print("Solving sudoku using recursion and propagation..")
            timer.start()
            # with suppress_stdout_stderr():
            solved_sudoku = solve_sudoku_prop(sudoku, k)
        if verbose:
            timer.stop()

    # Print the solved sudoku
    if solved_sudoku == None:
        print("NO SOLUTION FOUND")
    else:
        if check_solved_sudoku(solved_sudoku, k) == True:
            print(pretty_repr(solved_sudoku, k))
        else:
            print("INCORRECT SOLUTION FOUND")
            print(pretty_repr(solved_sudoku, k))
Exemplo n.º 2
0
    def train_loop(
        self,
        *,
        model,
        config,
        writer,
        kfp_writer,
        train_dataloader,
        label_mappings,
        val_dataloader,
        train_sampler=None,
    ):
        """

        Args:
            model: model to train
            config (CfgNode): estimator config
            writer: Tensorboard writer object
            device: model training on device (cpu|cuda)
            train_dataloader (torch.utils.data.DataLoader):
            label_mappings (dict): a dict of {label_id: label_name} mapping
            val_dataloader (torch.utils.data.DataLoader):
        """
        model = model.to(self.device)
        params = [p for p in model.parameters() if p.requires_grad]
        if config.optimizer.name == "Adam":
            optimizer = torch.optim.Adam(params, **config.optimizer.args)

            # use fixed learning rate when using Adam
            lr_scheduler = torch.optim.lr_scheduler.LambdaLR(
                optimizer, lambda x: 1.0)
        elif config.optimizer.name == "SGD":
            optimizer = torch.optim.SGD(
                params,
                lr=config.optimizer.args.lr,
                momentum=config.optimizer.args.momentum,
                weight_decay=float(config.optimizer.args.weight_decay),
            )
            lr_scheduler = torch.optim.lr_scheduler.StepLR(
                optimizer,
                step_size=config.optimizer.args.lr_step_size,
                gamma=config.optimizer.args.lr_gamma,
            )
        else:
            raise ValueError(f"only valid optimizers are 'SGD' and 'Adam' but "
                             f"received paramater {config.optimizer.name}")

        accumulation_steps = config.train.get("accumulation_steps",
                                              DEFAULT_ACCUMULATION_STEPS)
        logger.debug("Start training")
        total_timer = Timer(name="total-time",
                            text=const.TIMING_TEXT,
                            logger=logging.info)
        total_timer.start()
        for epoch in range(config.train.epochs):
            with Timer(
                    name=f"epoch-{epoch}-train-time",
                    text=const.TIMING_TEXT,
                    logger=logging.info,
            ):
                train_one_epoch(
                    writer=writer,
                    model=model,
                    optimizer=optimizer,
                    data_loader=train_dataloader,
                    device=self.device,
                    epoch=epoch,
                    lr_scheduler=lr_scheduler,
                    accumulation_steps=accumulation_steps,
                    log_frequency=self.config.train.log_frequency,
                )
            if self.config.system.distributed:
                train_sampler.set_epoch(epoch)
            self.checkpointer.save(self, epoch=epoch)
            with Timer(
                    name=f"epoch-{epoch}-evaluate-time",
                    text=const.TIMING_TEXT,
                    logger=logging.info,
            ):
                evaluate_per_epoch(
                    model=model,
                    data_loader=val_dataloader,
                    device=self.device,
                    writer=writer,
                    kfp_writer=kfp_writer,
                    epoch=epoch,
                    metrics=self.metrics,
                    label_mappings=label_mappings,
                )
        total_timer.stop()
Exemplo n.º 3
0
from storer.fileops.filecopier import CopyTask

from codetiming import Timer                # https://github.com/realpython/codetiming
from datetime import datetime, timedelta

SOURCE_PATH = "/home/jfcm02/Proyectos/Desarrollo/TestData/source_files"
DESTINATION_PATH = "/home/jfcm02/Proyectos/Desarrollo/TestData/dest_files"

# filecmp.dircmp(SOURCE_PATH,DESTINATION_PATH).report()
copia1 = CopyTask(SOURCE_PATH, DESTINATION_PATH, pbar=True)

print(copia1)
print(r"Número de Ficheros en {} = {}".format(SOURCE_PATH, len(copia1.sourcefiles)))
print("Tamaño total de la carpeta origen: {:.2f}MBs".format(round(copia1.totalsize/1024/1024, 2)))

t = Timer(name="class", logger=None)
t.start()

# copia1.do_copy()
# copia1.do_copy(datetime.strptime("2019/01/01", "%Y/%m/%d"))
# copia1.do_copy(to_date=datetime.strptime("2019/01/01", "%Y/%m/%d"))
copia1.do_copy(datetime.strptime("2019/01/01", "%Y/%m/%d"),
               datetime.strptime("2019/01/31", "%Y/%m/%d"))

elapsed_time = t.stop()

print("Ficheros seleccionados para copiar: {} ({:.2f}MBs)".format(len(copia1.selectedfiles), round(copia1.selectedsize/1024/1024, 2)))
print("Ficheros con mismo nombre pero distintos (renombrar): {}".format(copia1.renamedfiles))
print("Ficheros idénticos (saltar): {}".format(copia1.skippedfiles))
print("Ficheros copiados: {} (tamaño: {:.2f}MBs)".format(copia1.copiedfiles, round(copia1.copiedsize/1024/1024, 2)))
print("Tiempo transcurrido: {:.4f} segundos".format(round(elapsed_time, 4)))
Exemplo n.º 4
0
            label='Prominent Peaks')  # Sub plot one minima identification
        # plt.scatter(self.peaks_x, self.eval_height, color = 'black', s = 5, marker = 'X', label = 'Eval_height')
        # plt.scatter(self.intersect_x, self.intersect_y, color = 'orange', s = 5, marker = 'o', label = 'Intercetion')
        plt.vlines(self.prom_x,
                   self.prom_y_min,
                   self.prom_y_max,
                   color='black',
                   linewidth=1,
                   linestyle='dashed',
                   label='Peak Prominence')
        # plt.hlines(self.prom_y_min, self.min_pwidth, self.max_pwidth, color='green')
        fig.legend()
        fig.suptitle("FT-IR Spectra Comparison")
        plt.xlabel('Wavenumber (cm-1)')
        plt.ylabel("Reflectance")
        plt.ylim(0.00, 1.20)
        plt.show()


# ----- Main Loop -----
print("---------- START ----------")
pri_spectra = Spectra(file_import_selection())
pri_spectra.x_y_assignment()
pri_spectra.x_axis_limiting()
pri_spectra.baseline_correction()
pri_spectra.peak_profile_generation()
pri_spectra.plot()
print("-----------END-----------")
# ----- End Timer -----
t.stop()
Exemplo n.º 5
0
                                     distance[i][k] + distance[k][j])
        #print(distance)
    #print_solution(distance)


# Printing the solution
def print_solution(distance):
    for i in range(nV):
        for j in range(nV):
            if (distance[i][j] == INF or distance[i][j] > 9000):
                print("INF", end=" ")
            else:
                print(distance[i][j], end="  ")
        print(" ")


G = loadGraph('testExample.txt')
nV = len(G)
'''
G =  [[0, 5, INF, 10],
        [INF, 0, 3, INF],
        [INF, INF, 0,   1],
        [INF, INF, INF, 0]
        ]
nV=len(G)
'''
floyd_warshall(G)

#t.stop() vraća lijepo formatiran rezultat pa nije potreban print
execution_time = t.stop()
Exemplo n.º 6
0
def test_error_if_timer_not_running():
    """Test that timer raises error if it is stopped before started"""
    t = Timer(text=TIME_MESSAGE)
    with pytest.raises(TimerError):
        t.stop()
Exemplo n.º 7
0
class Merge(object):
    def __init__(self, indb=None, outdb=None, host=None):
        """Load a small bounding box for each country using the modified raw_countries
        table. Included in the source code for osm-stats-workers is a GeoJson file with
        the boundries used to display country boundaries. As those boundaries were only
        used by the front end, the boundaries are not in the database. The modified
        raw_countries table is the same data with a new column added for the geometry."""
        if indb is None:
            indb = "leaderboard"
        self.indb = Pydb(indb, host)
        self.countries = dict()
        geoquery = "SELECT id,St_AsText(ST_Envelope(ST_Buffer(ST_Centroid(boundary), 1, 4))) FROM raw_countries;"
        log = PixelSpinner("Loading Country boundaries...")
        self.indb.dbcursor.execute(geoquery)
        for row in self.indb.dbcursor.fetchall():
            log.next()
            self.countries[row[0]] = row[1]
        self.timer = Timer()
        if outdb is None:
            outdb = "galaxy"
        self.outdb = Pydb(outdb, host)

    def getBbox(self, cid):
        """Get the bounding box for a country"""
        if cid in self.countries:
            return self.countries[cid]
        else:
            return None

    def mergeUsers(self):
        """Merge the raw_users table from the leaderboard into osmstats"""
        inquery = "SELECT id,name FROM raw_users;"
        logging.info(
            "Merging leaderboard user table into Galaxy osmstats database")
        self.indb.dbcursor.execute(inquery)
        for entry in self.indb.dbcursor.fetchall():
            outquery = "INSERT INTO users(id,name) VALUES({id}, \'{name}\') ON CONFLICT(id) DO UPDATE SET id="
            # watch out for single quotes in user names
            value = entry[1].replace("'", "'")
            outquery += str(entry[0]) + ", name=\'" + value + "\'"
            query = outquery.format(id=int(entry[0]), name=value)
            self.outdb.dbcursor.execute(query)

    def mergeHashtags(self):
        """Merge the raw_hashtags table from the leaderboard into osmstats"""
        log = PixelSpinner(
            "Merging leaderboard hashtags table into Galaxy osmstats database. this may take a will..."
        )
        self.timer.start()
        inquery = "SELECT changeset_id,hashtag FROM raw_changesets_hashtags INNER JOIN raw_hashtags ON (raw_changesets_hashtags.hashtag_id = id);"
        self.indb.dbcursor.execute(inquery)
        self.timer.stop()
        for entry in self.indb.dbcursor.fetchall():
            log.next()
            outquery = "INSERT INTO changesets(id,hashtags) VALUES({id}, ARRAY['{hashtags}']) ON CONFLICT(id) DO UPDATE SET id="
            # watch out for single quotes in user names
            fixed = entry[1].replace("'", "'")
            outquery += str(
                entry[0]
            ) + ", hashtags=ARRAY_APPEND(changesets.hashtags, '" + fixed + "')"
            self.outdb.dbcursor.execute(
                outquery.format(id=int(entry[0]), hashtags=fixed))

    def mergeStatistics(self, timestamp):
        """Merge the raw_changesets table from the leaderboard into osmstats"""
        log = PixelSpinner(
            "Merging leaderboard statistics into Galaxy osmstats database")
        log.next()

        self.timer.start()
        query = "SELECT id, road_km_added, road_km_modified, waterway_km_added, waterway_km_modified, roads_added, roads_modified, waterways_added, waterways_modified, buildings_added, buildings_modified, pois_added, pois_modified, editor, user_id, created_at, closed_at, updated_at,country_id FROM raw_changesets INNER JOIN raw_changesets_countries ON (raw_changesets_countries.changeset_id = id);"
        self.indb.dbcursor.execute(query)
        self.timer.stop()
        result = self.indb.dbcursor.fetchone()
        while result is not None:
            stats = dict()
            added = dict()
            modified = dict()
            # non statistics fields
            stats['change_id'] = result[0]
            stats['editor'] = result[11]
            stats['user_id'] = result[14]
            stats['created_at'] = result[15]
            stats['closed_at'] = result[16]
            if stats['created_at'] is None and stats['closed_at'] is None:
                result = self.indb.dbcursor.fetchone()
                continue
            if stats['created_at'] is None:
                stats['created_at'] = stats['closed_at']
            if stats['closed_at'] is None:
                stats['closed_at'] = stats['created_at']
            stats['updated_at'] = result[17]
            stats['country_id'] = result[18]
            if self.getBbox(result[18]) is None:
                logging.warning(
                    "Country ID %s is not in the geoboundaries table" %
                    result[18])
                result = self.indb.dbcursor.fetchone()
                continue
            stats['bbox'] = "ST_Multi(ST_GeomFromText('"
            stats['bbox'] += self.getBbox(result[18]) + "')"
            # Added fields
            added['highway_km'] = result[1]
            added['waterway_km'] = result[3]
            added['highways'] = result[4]
            added['waterways'] = result[7]
            added['buildings'] = result[9]
            added['pois'] = result[11]
            # Modified fields
            modified['highway_km'] = result[2]
            modified['waterway_km'] = result[4]
            modified['highways'] = result[6]
            modified['waterways'] = result[8]
            modified['buildings'] = result[10]
            modified['pois'] = result[12]
            # Get the next row, since we're done with this one
            result = self.indb.dbcursor.fetchone()

            # Build the hstore for the added statistics
            hadd = "HSTORE(ARRAY["
            for key, value in added.items():
                hadd += "ARRAY['" + key + "','" + str(value) + "'],"
            length = len(hadd) - 1
            hadd = hadd[:length]
            hadd += "])"

            # Build the hstore for the added statistics
            hmod = "HSTORE(ARRAY["
            for key, value in modified.items():
                hmod += "ARRAY['" + key + "','" + str(value) + "'],"
            length = len(hmod) - 1
            hmod = hmod[:length]
            hmod += "])"

            query = "INSERT INTO changesets(id, editor, user_id, created_at, closed_at, updated_at, added, modified, bbox)"
            query += " VALUES({id}, '{editor}', {user_id}, '{created_at}', '{closed_at}', '{updated_at}', {add}, {mod}, {bbox})) ON CONFLICT(id) DO UPDATE SET editor='{editor}', user_id={user_id}, created_at='{created_at}', closed_at='{closed_at}', updated_at='{updated_at}', added={add}, modified={mod}, bbox={bbox});"
            outquery = query.format(id=stats['change_id'],
                                    editor=stats['editor'],
                                    user_id=stats['user_id'],
                                    created_at=stats['created_at'],
                                    closed_at=stats['closed_at'],
                                    updated_at=stats['updated_at'],
                                    bbox=stats['bbox'],
                                    add=hadd,
                                    mod=hmod)
            #print(outquery)
            self.outdb.dbcursor.execute(outquery)
        handles, labels = axs2[0, 0].get_legend_handles_labels()
        fig2.legend(handles, labels, loc='upper right')
        peak_plotting_t.stop()
        plt.show()


# Main Loop - Processing the spectrum
print("---------- START ----------")
# TODO: Add method to init all functions within the class (automate)
# Assigning spectrum object names
pri_spectrum = Spectrum('Import')
sec_spectrum = Spectrum('reference')
pri_spectrum.file_import_selection()
pri_spectrum.x_y_assignment()
pri_spectrum.x_axis_limiting()
pri_spectrum.normalise_data()
pri_spectrum.peak_detection()
pri_spectrum.peak_deconvolution()
pri_spectrum.peak_comparison()
# pri_spectrum.spectrum_peak_output()
# sec_spectrum.file_import_selection()
# sec_spectrum.x_y_assignment()
# sec_spectrum.x_axis_limiting()
# sec_spectrum.normalise_data()
# sec_spectrum.peak_detection()
# sec_spectrum.peak_deconvolution()
# sec_spectrum.peak_comparison()
pri_spectrum.plot()

total_runtime_t.stop()
print("-----------END-----------")
Exemplo n.º 9
0
class Binary_ILP_case:
    # variables: list of sympy symbols
    # obj_fn [sympy expression]: the function to maximize or minimize
    # b: array of constraints
    def __init__(self,
                 variables,
                 obj_fn,
                 b,
                 maximize=True,
                 expected_obj_val=None):

        # init
        self.variables = variables
        self.obj_fn = obj_fn
        self.b = b  # all inEquality functions must be less than for now.
        self.expected_obj_val = expected_obj_val

        self._variables = []
        self._obj_fn = obj_fn
        self._b = b[:]

        self.var_ref = {}  # True means _xi = xi, False means _xi = (1-xi)
        self.counter_var_ref = {}  # get x1 from _x1

        self.i = 0
        self.algo = self.get_supported_algos()

        self.goal = 'maximize'

        if (maximize == False):
            self.goal = 'minimize'

        self.timer = Timer(name="class", logger=None)
        self.pre_process()

    def __repr__(self):  # for shell
        return self.get_print_string()

    def __str__(self):  # for print
        return self.get_print_string()

    def get_print_string(self):

        variables = ''

        for var in self.variables:
            variables += str(var) + ', '

        variables = variables[:-2]

        result = 'Case:'.ljust(10) + variables + '\n'
        result += 'Z:'.ljust(10) + str(self.obj_fn) + '\n\n'

        first_line = True
        for inEq in self.b:
            if first_line:
                result += 'b:'.ljust(10) + str(inEq) + '\n'
                first_line = False
            else:
                result += ''.ljust(10) + str(inEq) + '\n'

        result += '\n'

        if self.expected_obj_val:
            result += 'Exp val:'.ljust(10) + str(self.expected_obj_val)

        return result

    def pre_process(self):

        # print('pre_processing...')

        self.covert_all_constraints_to_less_than()

        # update variable reference and objective fxn reference
        obj_args = self.obj_fn.args

        # when calling args, sympy will change the order of variables appearing in expression with the constant at the first place, and
        # some arbitary order for the rest of the variables

        for var in self.variables:
            _var = "_" + str(var)
            _var = Symbol(_var)
            self._variables.append(_var)
            self.counter_var_ref[_var] = var
            self.var_ref[var] = VarRef(_var, False)

        for item in obj_args:

            if not isinstance(item, numbers.Integer):

                if not isinstance(item, symbol.Symbol):
                    coeff = item.args[0]
                    var = item.args[1]
                else:
                    coeff = 1
                    var = item

                _var = self.var_ref[var].counter_part

                if coeff > 0:
                    self.var_ref[var] = VarRef(_var,
                                               True)  # True for isReverse
                    self._obj_fn = self._obj_fn.subs(var, (1 - _var))
                    self._b = self.get_substitute_b(self._b, var, (1 - _var))

                else:
                    self._obj_fn = self._obj_fn.subs(var, _var)
                    self._b = self.get_substitute_b(self._b, var, _var)

        # print('vars:', self.variables)
        # print('_vars', self._variables)
        # print('var_ref', self.var_ref)
        # print('obj_fn', self.obj_fn)
        # print('_obj_fn', self._obj_fn)
        # print('b', self.b)
        # print('_b', self._b)
        # print('counter_far_ref', self.counter_var_ref)
        # print('\n\n')

    def translate_result(self, result):

        # print('translating result...')
        # print('result', result)

        if result.obj_val == -oo:
            return result

        var_vals_ref = {}

        for item in result.var_vals:

            _var = item.var
            val = item.val

            var = self.counter_var_ref[_var]

            if self.var_ref[var].isReverse:
                var_vals_ref[var] = 1 - val
            else:
                var_vals_ref[var] = val

        # print('var_vals_ref', var_vals_ref)

        sorted_var_vals = []  #based on order of vars

        # print('self.vars', self.variables)

        for var in self.variables:
            sorted_var_vals.append(VarVal(var, var_vals_ref[var]))

        return Result(result.obj_val, sorted_var_vals)

    def covert_all_constraints_to_less_than(self):

        # print('start covert_all_constraints_to_less_than', self._b)

        _b = []

        for inEq in self._b:

            # print('inEqu is: ', inEq)
            if isinstance(inEq, (StrictLessThan, LessThan)):
                _b.append(inEq)
            else:
                _b.append(inEq.reversedsign)

        self._b = _b

    def _(self, var):
        return self.var_ref[var].counter_part

    def get_preprocessed_result(self):

        return {
            '_variables': self._variables,
            '_obj_fn': self._obj_fn,
            '_b': self._b
        }

    def get_supported_algos(self):
        class Algo:
            def __init__(self):
                self.brutal_divide_and_conquer = 'brutal_divide_and_conquer'
                self.brutal_explicit_enumeration = 'brutal_explicit_enumeration'
                self.implicit_enumeration = 'implicit_enumeration'

        return Algo()

    def reset_counter(self):
        self.i = 0

    def get_run_count(self):
        return self.i

    def get_substitute_b(self, old_b, var, val):

        # to do: add check in this fxn, if result is false, the function that call this function should stop evaluate this possibility
        # print('calc get_substitute_b,', old_b, var, val)
        # val could be value, or the counter part of var
        # example: get_substitute_b(b, x1, (1-_x1))

        result = []

        for inEq in old_b:
            result.append(inEq.subs(var, val))

        # print('sub b result', result)

        return result

    def is_feasible(self, b, var_vals, debug=False):

        # if debug:
        # print('checking is feasible, b:', b, ' var_vals:', var_vals)

        for constraint in b:

            c = constraint

            for var_val in var_vals:
                c = c.subs(var_val.var, var_val.val)

                if c == False:
                    # if debug:
                    # print('\nConstraint not met: ', constraint, ' with var vals: ', var_vals, '\n')
                    return False
        if debug:
            print('\nFeasible, retunning true !!!\n')
            print('b:', b, ' var_vals:', var_vals)
        return True

    def get_obj_fn_val(self, obj_fn, var_vals):

        obj_val = obj_fn
        for item in var_vals:
            obj_val = obj_val.subs(item.var, item.val)

        return obj_val

    def solve(self, algo, print_run_count=False):

        variables = self._variables[:]
        obj_fn = self._obj_fn
        b = self._b[:]

        self.reset_counter()
        self.timer.start()

        if algo == self.algo.brutal_divide_and_conquer:
            result = self.solve_by_brutal_divide_and_conquer(
                variables, obj_fn, b)

        if algo == self.algo.brutal_explicit_enumeration:
            result = self.solve_by_brutal_explicit_enumeration(
                variables, obj_fn, b)

        if algo == self.algo.implicit_enumeration:
            result = self.solve_by_implicit_enumeration(variables, obj_fn, b)

        elapsed_time = self.timer.stop()

        if print_run_count:
            print("Run count", self.get_run_count())
            print("Runnint time - {algo} : {time:,.4f} second".format(
                algo=algo, time=elapsed_time))

        return self.translate_result(result)

    def solve_by_brutal_divide_and_conquer(self, variables, obj_fn, b):

        self.i += 1

        # if number of free vars is greater than 1, pick one var, update objective function and inequality constraints
        if len(variables) > 1:

            fix_var = variables[0]  # modify vars list

            obj_zero = obj_fn.subs(fix_var, 0)
            b_zero = self.get_substitute_b(b, fix_var, 0)
            result_zero = self.solve_by_brutal_divide_and_conquer(
                variables[1:], obj_zero, b_zero)

            obj_one = obj_fn.subs(fix_var, 1)
            b_one = self.get_substitute_b(b, fix_var, 1)
            result_one = self.solve_by_brutal_divide_and_conquer(
                variables[1:], obj_one, b_one)

            if result_zero.obj_val > result_one.obj_val:
                return Result(obj_val=result_zero.obj_val,
                              var_vals=[VarVal(var=fix_var, val=0)] +
                              result_zero.var_vals)
            else:
                # print('result_one', fix_var, obj_fn)
                return Result(obj_val=result_one.obj_val,
                              var_vals=[VarVal(var=fix_var, val=1)] +
                              result_one.var_vals)

        else:  # base case

            var = variables[0]

            is_feasible_zero = self.is_feasible(b, [VarVal(var, 0)])

            if not is_feasible_zero:
                obj_val_zero = -oo
            else:
                obj_val_zero = obj_fn.subs(var, 0)

            is_feasible_one = self.is_feasible(b, [VarVal(var, 1)])

            if not is_feasible_one:
                obj_val_one = -oo
            else:
                obj_val_one = obj_fn.subs(var, 1)

            if obj_val_zero > obj_val_one:
                result = Result(obj_val=obj_val_zero,
                                var_vals=[VarVal(var=var, val=0)])
            else:
                result = Result(obj_val=obj_val_one,
                                var_vals=[VarVal(var=var, val=1)])

            # print('result', result)
            return result

    def solve_by_brutal_explicit_enumeration(self, variables, obj_fn, b):

        all_cases = list(product([0, 1], repeat=len(variables)))

        best_result = Result(obj_val=-oo, var_vals=[])

        for case in all_cases:
            var_vals = []
            for i in range(0, len(variables)):
                var_vals.append(VarVal(variables[i], case[i]))

            obj_val = self.get_obj_fn_val(obj_fn, var_vals)
            self.i += 1
            if obj_val > best_result.obj_val and self.is_feasible(b, var_vals):
                best_result = Result(obj_val, var_vals)

        return best_result

    def sort_vars_by_priority_for_implicit_enumeration(self, variables):

        # to be implemented
        return variables

    def solve_by_implicit_enumeration(self, variables, obj_fn, b):

        # implicit enumeration assume all vars has a negative coefficient in objective function and thus best obj val will be set all vars to 0
        debug = False

        self.i += 1

        # print('running with vars:', variables)
        # print('fn:', obj_fn)
        # print('b:', b)

        best_result = Result(obj_val=-oo, var_vals=[])

        fix_var = variables.pop(0)

        # branch to fix_var = 0

        var_vals = [VarVal(fix_var, 0)]

        for var in variables:
            var_vals.append(VarVal(var, 0))

        if self.is_feasible(b, var_vals, debug=debug):  # best case scenario
            obj_val = self.get_obj_fn_val(obj_fn, var_vals)

            # print('all 0 is feasible, returning val:', obj_val)
            return Result(obj_val, var_vals)

        elif len(variables) > 0:  # can be divided further

            obj_zero = obj_fn.subs(fix_var, 0)
            b_zero = self.get_substitute_b(b, fix_var, 0)
            result_zero = self.solve_by_implicit_enumeration(
                variables[:], obj_zero, b_zero)

            if result_zero.obj_val > best_result.obj_val:
                # print('best result updated from: ', best_result.obj_val, ' to: ', result_zero.obj_val)
                best_result = Result(result_zero.obj_val,
                                     [VarVal(fix_var, 0)] +
                                     result_zero.var_vals)

        # branch to fix_var = 1

        var_vals[0].val = 1

        if self.is_feasible(b, var_vals, debug=debug):
            obj_val = self.get_obj_fn_val(obj_fn, var_vals)

            if obj_val > best_result.obj_val:
                # print('best result updated from: ', best_result.obj_val, ' to: ', obj_val)
                best_result = Result(obj_val, var_vals)

        elif len(variables) > 0:

            obj_one = obj_fn.subs(fix_var, 1)
            b_one = self.get_substitute_b(b, fix_var, 1)
            result_one = self.solve_by_implicit_enumeration(
                variables[:], obj_one, b_one)

            if result_one.obj_val > best_result.obj_val:
                # print('best result updated from: ', best_result.obj_val, ' to: ', result_one.obj_val)
                best_result = Result(result_one.obj_val, [VarVal(fix_var, 1)] +
                                     result_one.var_vals)

        # print('\nreturning best result', best_result, '\n')
        return best_result