def find_transform(x, y, limit, threshold=1e-7): """ find a integer solution to ax + b - cxy - dy = 0 this will give us the mobius transform: T(x) = y :param x: numeric constant to check :param y: numeric manipulation of constant :param limit: range to look at :param threshold: optimal solution threshold. :return MobiusTransform in case of success or None. """ x1 = x x2 = dec(1.0) x3 = -x * y x4 = -y solver = Solver('mobius', Solver.CBC_MIXED_INTEGER_PROGRAMMING) a = solver.IntVar(-limit, limit, 'a') b = solver.IntVar(-limit, limit, 'b') c = solver.IntVar(-limit, limit, 'c') d = solver.IntVar(-limit, limit, 'd') f = solver.NumVar(0, 1, 'f') solver.Add(f == (a * x1 + b * x2 + c * x3 + d * x4)) solver.Add(a * x1 + b >= 1) # don't except trivial solutions and remove some redundancy solver.Minimize(f) status = solver.Solve() if status == Solver.OPTIMAL: if abs(solver.Objective().Value()) <= threshold: res_a, res_b, res_c, res_d = int(a.solution_value()), int(b.solution_value()),\ int(c.solution_value()), int(d.solution_value()) ret = MobiusTransform( np.array([[res_a, res_b], [res_c, res_d]], dtype=object)) ret.normalize() return ret else: return None
def _parse_declaration(solver: pywraplp.Solver, core_line: str, line_nr: int, var_names: set): spl_whitespace = core_line.split(maxsplit=1) if spl_whitespace[0] != "int": raise ValueError("Declaration on line %d should start with \"int \"." % line_nr) if len(spl_whitespace) != 2: raise ValueError("Declaration on line %d has no variables." % line_nr) spl_variables = spl_whitespace[1].split(",") for raw_var in spl_variables: clean_var = raw_var.strip() if not re.match(_REGEXP_SINGLE_VAR_NAME_ALL, clean_var): raise ValueError( "Non-permitted variable name (\"%s\") on line %d." % (clean_var, line_nr)) if clean_var in var_names: raise ValueError("Variable \"%s\" declared again on line %d." % (clean_var, line_nr)) var_names.add(clean_var) solver.IntVar(-solver.infinity(), solver.infinity(), clean_var)